mirror of
https://github.com/corda/corda.git
synced 2025-01-22 12:28:11 +00:00
add support for the ARM hardware floating point ABI
This ABI's calling convention passes arguments and returns results using VFP registers, so we need to tweak vmNativeCall to match it. Thanks to Damjan Jovanovic for pointing this out and providing an initial patch.
This commit is contained in:
parent
836fc21106
commit
a97c5728bb
27
src/arm.S
27
src/arm.S
@ -9,6 +9,8 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "types.h"
|
||||
|
||||
.text
|
||||
|
||||
#define LOCAL(x) .L##x
|
||||
@ -29,14 +31,18 @@ GLOBAL(vmNativeCall):
|
||||
r2 : memoryTable
|
||||
r3 : memoryCount
|
||||
[sp, #0] -> r6 : gprTable
|
||||
[sp, #4] -> r7 : vfpTable
|
||||
[sp, #8] -> r8 : returnType
|
||||
*/
|
||||
mov ip, sp // save stack frame
|
||||
stmfd sp!, {r4-r6, lr} // save clobbered non-volatile regs
|
||||
stmfd sp!, {r4-r8, lr} // save clobbered non-volatile regs
|
||||
|
||||
// mv args into non-volatile regs
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
ldr r6, [ip]
|
||||
ldr r7, [ip, #4]
|
||||
ldr r8, [ip, #8]
|
||||
|
||||
// setup stack arguments if necessary
|
||||
sub sp, sp, r5 // allocate stack
|
||||
@ -51,11 +57,28 @@ LOCAL(loop):
|
||||
// setup argument registers if necessary
|
||||
tst r6, r6
|
||||
ldmneia r6, {r0-r3}
|
||||
#if defined(__VFP_FP__) && (! defined(__SOFTFP__))
|
||||
// and VFP registers
|
||||
vldmia r7, {d0-d8}
|
||||
#endif
|
||||
|
||||
blx r4 // call function
|
||||
add sp, sp, r5 // deallocate stack
|
||||
|
||||
ldmfd sp!, {r4-r6, pc} // restore non-volatile regs and return
|
||||
#if defined(__VFP_FP__) && (! defined(__SOFTFP__))
|
||||
cmp r8,#FLOAT_TYPE
|
||||
bne LOCAL(double)
|
||||
fmrs r0,s0
|
||||
b LOCAL(exit)
|
||||
|
||||
LOCAL(double):
|
||||
cmp r8,#DOUBLE_TYPE
|
||||
bne LOCAL(exit)
|
||||
fmrrd r0,r1,d0
|
||||
#endif
|
||||
|
||||
LOCAL(exit):
|
||||
ldmfd sp!, {r4-r8, pc} // restore non-volatile regs and return
|
||||
|
||||
.globl GLOBAL(vmJump)
|
||||
.align 2
|
||||
|
46
src/arm.h
46
src/arm.h
@ -60,7 +60,8 @@
|
||||
|
||||
extern "C" uint64_t
|
||||
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
|
||||
unsigned memoryCount, void* gprTable);
|
||||
unsigned memoryCount, void* gprTable, void* vfpTable,
|
||||
unsigned returnType);
|
||||
|
||||
namespace vm {
|
||||
|
||||
@ -131,7 +132,7 @@ atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned argumentsSize UNUSED,
|
||||
unsigned returnType UNUSED)
|
||||
unsigned returnType)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
const unsigned Alignment = 1;
|
||||
@ -143,6 +144,10 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
uintptr_t gprTable[GprCount];
|
||||
unsigned gprIndex = 0;
|
||||
|
||||
const unsigned VfpCount = 16;
|
||||
uintptr_t vfpTable[VfpCount];
|
||||
unsigned vfpIndex = 0;
|
||||
|
||||
uintptr_t stack[(argumentCount * 8) / BytesPerWord]; // is > argumentSize to account for padding
|
||||
unsigned stackIndex = 0;
|
||||
|
||||
@ -150,6 +155,36 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
for (unsigned ati = 0; ati < argumentCount; ++ ati) {
|
||||
switch (argumentTypes[ati]) {
|
||||
case DOUBLE_TYPE:
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
{
|
||||
if (vfpIndex + Alignment <= VfpCount) {
|
||||
if (vfpIndex % Alignment) {
|
||||
++ vfpIndex;
|
||||
}
|
||||
|
||||
memcpy(vfpTable + vfpIndex, arguments + ai, 8);
|
||||
vfpIndex += 8 / BytesPerWord;
|
||||
} else {
|
||||
vfpIndex = VfpCount;
|
||||
if (stackIndex % Alignment) {
|
||||
++ stackIndex;
|
||||
}
|
||||
|
||||
memcpy(stack + stackIndex, arguments + ai, 8);
|
||||
stackIndex += 8 / BytesPerWord;
|
||||
}
|
||||
ai += 8 / BytesPerWord;
|
||||
} break;
|
||||
|
||||
case FLOAT_TYPE:
|
||||
if (vfpIndex < VfpCount) {
|
||||
vfpTable[vfpIndex++] = arguments[ai];
|
||||
} else {
|
||||
stack[stackIndex++] = arguments[ai];
|
||||
}
|
||||
++ ai;
|
||||
break;
|
||||
#endif
|
||||
case INT64_TYPE: {
|
||||
if (gprIndex + Alignment <= GprCount) { // pass argument in register(s)
|
||||
if (Alignment == 1
|
||||
@ -193,11 +228,16 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||
memset(gprTable + gprIndex, 0, (GprCount-gprIndex)*4);
|
||||
gprIndex = GprCount;
|
||||
}
|
||||
if (vfpIndex < VfpCount) {
|
||||
memset(vfpTable + vfpIndex, 0, (VfpCount-vfpIndex)*4);
|
||||
vfpIndex = VfpCount;
|
||||
}
|
||||
|
||||
unsigned stackSize = stackIndex*BytesPerWord + ((stackIndex & 1) << 2);
|
||||
return vmNativeCall
|
||||
(function, stackSize, stack, stackIndex * BytesPerWord,
|
||||
(gprIndex ? gprTable : 0));
|
||||
(gprIndex ? gprTable : 0),
|
||||
(vfpIndex ? vfpTable : 0), returnType);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
Loading…
Reference in New Issue
Block a user