diff --git a/src/compile-powerpc.S b/src/compile-powerpc.S index d0cf0e14f4..e760287f1e 100644 --- a/src/compile-powerpc.S +++ b/src/compile-powerpc.S @@ -24,12 +24,12 @@ # define GLOBAL(x) x #endif -#define THREAD_STACK 2144 -#define THREAD_CONTINUATION 2148 +#define THREAD_STACK 2148 +#define THREAD_CONTINUATION 2156 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2152 -#define THREAD_EXCEPTION_OFFSET 2156 -#define THREAD_EXCEPTION_HANDLER 2160 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 +#define THREAD_EXCEPTION_OFFSET 2164 +#define THREAD_EXCEPTION_HANDLER 2168 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/powerpc.S b/src/powerpc.S index fce2079af7..b8034f5a7a 100644 --- a/src/powerpc.S +++ b/src/powerpc.S @@ -17,14 +17,15 @@ #define GPR_COUNT 8 #define MEMORY_BASE BYTES_PER_WORD * (LINKAGE_AREA + GPR_COUNT) #define LOCAL(x) L##x - + #ifdef __APPLE__ -.globl _vmNativeCall -_vmNativeCall: +# define GLOBAL(x) _##x #else -.globl vmNativeCall -vmNativeCall: +# define GLOBAL(x) x #endif + +.globl GLOBAL(vmNativeCall) +GLOBAL(vmNativeCall): // save return address mflr r0 stw r0,8(r1) @@ -151,16 +152,80 @@ LOCAL(exit): // return blr -#ifdef __APPLE__ -.globl _vmJump -_vmJump: -#else -.globl vmJump -vmJump: -#endif +.globl GLOBAL(vmJump) +GLOBAL(vmJump): mtlr r3 mr r1,r5 mr r13,r6 mr r4,r7 mr r3,r8 blr + +#define CHECKPOINT_THREAD 4 +#define CHECKPOINT_STACK 24 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // r3: function + // r4: arguments + // r5: checkpoint + + mflr r0 + stw r0,8(r1) + + stwu r1,-(MEMORY_BASE+80)(r1) + + stw r13,MEMORY_BASE+0(r1) + stw r14,MEMORY_BASE+4(r1) + stw r15,MEMORY_BASE+8(r1) + stw r16,MEMORY_BASE+12(r1) + stw r17,MEMORY_BASE+16(r1) + stw r18,MEMORY_BASE+20(r1) + stw r19,MEMORY_BASE+24(r1) + stw r20,MEMORY_BASE+28(r1) + stw r21,MEMORY_BASE+32(r1) + stw r22,MEMORY_BASE+36(r1) + stw r23,MEMORY_BASE+40(r1) + stw r24,MEMORY_BASE+44(r1) + stw r25,MEMORY_BASE+48(r1) + stw r26,MEMORY_BASE+52(r1) + stw r27,MEMORY_BASE+56(r1) + stw r28,MEMORY_BASE+60(r1) + stw r29,MEMORY_BASE+64(r1) + stw r30,MEMORY_BASE+68(r1) + stw r31,MEMORY_BASE+72(r1) + + stw r1,CHECKPOINT_STACK(r5) + + mr r6,r3 + lwz r3,CHECKPOINT_THREAD(r5) + + mtctr r6 + bctrl + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + lwz r13,MEMORY_BASE+0(r1) + lwz r14,MEMORY_BASE+4(r1) + lwz r15,MEMORY_BASE+8(r1) + lwz r16,MEMORY_BASE+12(r1) + lwz r17,MEMORY_BASE+16(r1) + lwz r18,MEMORY_BASE+20(r1) + lwz r19,MEMORY_BASE+24(r1) + lwz r20,MEMORY_BASE+28(r1) + lwz r21,MEMORY_BASE+32(r1) + lwz r22,MEMORY_BASE+36(r1) + lwz r23,MEMORY_BASE+40(r1) + lwz r24,MEMORY_BASE+44(r1) + lwz r25,MEMORY_BASE+48(r1) + lwz r26,MEMORY_BASE+52(r1) + lwz r27,MEMORY_BASE+56(r1) + lwz r28,MEMORY_BASE+60(r1) + lwz r29,MEMORY_BASE+64(r1) + lwz r30,MEMORY_BASE+68(r1) + lwz r31,MEMORY_BASE+72(r1) + + lwz r1,0(r1) + lwz r0,8(r1) + mtlr r0 + blr diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 9973ccc544..be5cfac378 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -1691,6 +1691,55 @@ memoryBarrier(Context* c) // END OPERATION COMPILERS +unsigned +argumentFootprint(unsigned footprint) +{ + return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords); +} + +void +nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size UNUSED, + unsigned footprint, int32_t*, void* link, void*, + unsigned targetParameterFootprint, void** ip, void** stack) +{ + assert(c, *ip >= start); + assert(c, *ip <= start + (size / BytesPerWord)); + + int32_t* instruction = static_cast(*ip); + + if ((*start >> 26) == 32) { + // skip stack overflow check + start += 3; + } + + if (instruction <= start + 2 + or *instruction == lwz(0, 1, 8) + or *instruction == mtlr(0) + or *instruction == blr()) + { + *ip = link; + return; + } + + unsigned offset = footprint; + + if (TailCalls) { + if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { + offset += argumentFootprint(targetParameterFootprint) + - StackAlignmentInWords; + } + + // check for post-non-tail-call stack adjustment of the form "lwzx + // r0,0(r1); stwux r0,offset(r1)": + + // todo + + // todo: check for and handle tail calls + } + + *ip = static_cast(*stack)[offset + 2]; + *stack = static_cast(*stack) + offset; +} void populateTables(ArchitectureContext* c) @@ -1847,7 +1896,11 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords); + return ::argumentFootprint(footprint); + } + + virtual bool argumentAlignment() { + return false; } virtual unsigned argumentRegisterCount() { @@ -1916,6 +1969,15 @@ class MyArchitecture: public Assembler::Architecture { return (ceiling(sizeInWords + FrameFooterSize, alignment) * alignment); } + virtual void nextFrame(void* start, unsigned size, unsigned footprint, + int32_t* frameTable, void* link, void* stackLimit, + unsigned targetParameterFootprint, void** ip, + void** stack) + { + ::nextFrame(&c, static_cast(start), size, footprint, frameTable, + link, stackLimit, targetParameterFootprint, ip, stack); + } + virtual void* frameIp(void* stack) { return stack ? static_cast(stack)[2] : 0; } @@ -2141,7 +2203,7 @@ class MyAssembler: public Assembler { return arch_; } - virtual void saveFrame(unsigned stackOffset, unsigned) { + virtual void saveFrame(unsigned stackOffset) { Register returnAddress(0); emit(&c, mflr(returnAddress.low)); @@ -2206,16 +2268,16 @@ class MyAssembler: public Assembler { moveAndUpdateRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst); } - virtual void adjustFrame(unsigned footprint) { + virtual void adjustFrame(unsigned difference) { Register nextStack(0); Memory stackSrc(StackRegister, 0); moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &nextStack); - Memory stackDst(StackRegister, -footprint * BytesPerWord); + Memory stackDst(StackRegister, -difference * BytesPerWord); moveAndUpdateRM(&c, BytesPerWord, &nextStack, BytesPerWord, &stackDst); } - virtual void popFrame() { + virtual void popFrame(unsigned) { Register stack(StackRegister); Memory stackSrc(StackRegister, 0); moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack); @@ -2262,15 +2324,17 @@ class MyAssembler: public Assembler { moveRM(&c, BytesPerWord, &fps, BytesPerWord, &dst); } } else { - popFrame(); + popFrame(footprint); } } else { abort(&c); } } - virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) { - popFrame(); + virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint, + unsigned argumentFootprint) + { + popFrame(frameFootprint); assert(&c, argumentFootprint >= StackAlignmentInWords); assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); @@ -2289,9 +2353,10 @@ class MyAssembler: public Assembler { return_(&c); } - virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread) + virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, + unsigned stackOffsetFromThread) { - popFrame(); + popFrame(frameFootprint); Register tmp1(0); Memory stackSrc(StackRegister, 0); @@ -2401,6 +2466,14 @@ class MyAssembler: public Assembler { return c.code.length(); } + virtual unsigned frameEventCount() { + return 0; + } + + virtual FrameEvent* firstFrameEvent() { + return 0; + } + virtual void dispose() { c.code.dispose(); } diff --git a/src/powerpc.h b/src/powerpc.h index c5bf0613b5..fb84daf10a 100644 --- a/src/powerpc.h +++ b/src/powerpc.h @@ -14,20 +14,22 @@ #include "types.h" #include "common.h" +#define VA_LIST(x) (x) + #ifdef __APPLE__ # if __DARWIN_UNIX03 && defined(_STRUCT_PPC_EXCEPTION_STATE) # define IP_REGISTER(context) (context->uc_mcontext->__ss.__srr0) # define STACK_REGISTER(context) (context->uc_mcontext->__ss.__r1) # define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__r13) +# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__lr) # else # define IP_REGISTER(context) (context->uc_mcontext->ss.srr0) # define STACK_REGISTER(context) (context->uc_mcontext->ss.r1) # define THREAD_REGISTER(context) (context->uc_mcontext->ss.r13) +# define LINK_REGISTER(context) (context->uc_mcontext->ss.lr) # endif #else -# define IP_REGISTER(context) (context->uc_mcontext.gregs[32]) -# define STACK_REGISTER(context) (context->uc_mcontext.gregs[1]) -# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[13]) +# error "non-Apple PowerPC-based platforms not yet supported" #endif extern "C" uint64_t