From 4b67adaa0a100dd13928b6b4f4bb29cd509644d3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 8 Jun 2008 13:47:37 -0600 Subject: [PATCH] sketch vmNativeCall implementation for powerpc --- src/powerpc.S | 122 ++++++++++++++++++++++++++++++++++++++++++-------- src/powerpc.h | 17 ++++--- 2 files changed, 115 insertions(+), 24 deletions(-) diff --git a/src/powerpc.S b/src/powerpc.S index 7df5f6221e..a96afad74b 100644 --- a/src/powerpc.S +++ b/src/powerpc.S @@ -12,6 +12,7 @@ .text +BytesPerWord = 4 LinkageArea = 24 #ifdef __APPLE__ @@ -24,35 +25,118 @@ vmNativeCall: // save return address mflr r0 stw r0,8(r1) - - // r3 aka 24(r1): function - // r4 aka 28(r1): stack - // r5 aka 32(r1): stackSize - // r6 aka 36(r1): gprTable - // r7 aka 40(r1): fprTable - // r8 aka 48(r1): returnType + + // r3 aka r13: function + // r4 : stackTotal + // r5 : memoryTable + // r6 : memoryCount + // r7 : gprTable + // r8 : fprTable + // r9 aka r14: returnType + + // r15 : stack frame size + // r16 : temporary + // r17 : temporary + + // save registers used for local variables + stw r13,24(r1) + stw r14,28(r1) + stw r15,32(r1) + stw r16,36(r1) + stw r17,40(r1) // calculate aligned stack frame size - add r13,r5,LinkageArea + 15 - and r13,r13,-16 + add r15,r4,LinkageArea + LocalArea + 15 + and r15,r15,-16 // save and update stack pointer - sub r14,r1,r9 - stwu r1,r14 + sub r16,r1,r15 + stwu r16,(r1) // save our argument registers so we can clobber them - stw r3,24(r1) - stw r4,28(r1) - stw r5,32(r1) - stw r6,36(r1) - stw r7,40(r1) - stw r8,48(r1) - - // todo + mr r13,r3 + mr r14,r9 + li r16,0 + b test + +loop: + lwzx r17,r16,r5 + stwx r17,r16,r1 + add r16,r16,BytesPerWord + +test: + cmp r16,r6 + blt loop + + // do we need to load the floating point registers? + cmp r8,0 + be gpr + + // yes, we do + lfd fr1,0(r8) + lfd fr2,8(r8) + lfd fr3,16(r8) + lfd fr4,24(r8) + lfd fr5,32(r8) + lfd fr6,40(r8) + lfd fr7,48(r8) + lfd fr8,56(r8) + lfd fr9,64(r8) + lfd fr10,72(r8) + lfd fr11,80(r8) + lfd fr12,88(r8) + lfd fr13,96(r8) + +gpr: + // do we need to load the general-purpose registers? + cmp r7,0 + be call + + // yes, we do + mr r16,r7 + lwz r3,0(r16) + lwz r4,4(r16) + lwz r5,8(r16) + lwz r6,12(r16) + lwz r7,16(r16) + lwz r8,20(r16) + lwz r9,24(r16) + lwz r10,28(r16) + +call: + // load and call function address + mtctr r13 + bcctrl + + // handle return value based on expected type + cmp r14,VOID_TYPE + bne float + b exit + +float: + cmp r14,FLOAT_TYPE + be copy + cmp r14,DOUBLE_TYPE + bne exit + +copy: + // move floating point return value to GPRs via memory + sfd fr1,8(r1) + lwz r3,8(r1) + lwz r4,12(r1) + +exit: // restore stack pointer addi r1,r1,r13 + // restore registers used for local variables + lwz r13,24(r1) + lwz r14,28(r1) + lwz r15,32(r1) + lwz r16,36(r1) + lwz r17,40(r1) + // load return address lwz r0,8(r1) mtlr r0 diff --git a/src/powerpc.h b/src/powerpc.h index 544a914f9e..204565e422 100644 --- a/src/powerpc.h +++ b/src/powerpc.h @@ -34,8 +34,9 @@ #endif extern "C" uint64_t -vmNativeCall(void* function, void* stack, unsigned stackSize, - void* gprTable, void* fprTable, unsigned returnType); +vmNativeCall(void* function, unsigned stackTotal, void* memoryTable, + unsigned memoryCount, void* gprTable, void* fprTable, + unsigned returnType); namespace vm { @@ -52,6 +53,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, unsigned fprIndex = 0; uint64_t stack[argumentsSize]; + unsigned stackSkip = 0; unsigned stackIndex = 0; for (unsigned i = 0; i < argumentsSize; ++i) { @@ -59,7 +61,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, case FLOAT_TYPE: { if (fprIndex < FprCount) { fprTable[fprIndex++] = arguments[i]; - gprIndex += 1; + ++ gprIndex; + ++ stackSkip; } else { stack[stackIndex++] = arguments[i]; } @@ -68,8 +71,9 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, case DOUBLE_TYPE: { if (fprIndex < FprCount) { memcpy(fprTable + fprIndex, arguments + i, 8); - fprIndex += BytesPerWord / 4; + ++ fprIndex; gprIndex += BytesPerWord / 4; + stackSkip += BytesPerWord / 4; i += (BytesPerWord / 4) - 1; } else { memcpy(stack + stackIndex, arguments + i, 8); @@ -82,6 +86,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, if (gprIndex < GprCount) { memcpy(gprTable + gprIndex, arguments + i, 8); gprIndex += BytesPerWord / 4; + stackSkip += BytesPerWord / 4; i += (BytesPerWord / 4) - 1; } else { memcpy(stack + stackIndex, arguments + i, 8); @@ -93,6 +98,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, default: { if (gprIndex < GprCount) { gprTable[gprIndex++] = arguments[i]; + ++ stackSkip; } else { stack[stackIndex++] = arguments[i]; } @@ -100,7 +106,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, } } - return vmNativeCall(function, stack, stackIndex * BytesPerWord, + return vmNativeCall(function, (stackSkip + stackIndex) * BytesPerWord, + stack, stackIndex, (gprIndex ? gprTable : 0), (fprIndex ? fprTable : 0), returnType); }