From 0f0427f23b4c6731104f8f41f8f96353eb425256 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 8 Nov 2010 04:18:10 +0000 Subject: [PATCH] implement continuations support for ARM --- src/compile-arm.S | 159 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 12 deletions(-) diff --git a/src/compile-arm.S b/src/compile-arm.S index 3ac3310030..dcf1aec53b 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -8,17 +8,13 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#ifdef AVIAN_CONTINUATIONS -# error "Continuations not yet supported on ARM port" -#endif - #include "types.h" .text #define BYTES_PER_WORD 4 -#define LOCAL(x) L##x +#define LOCAL(x) .L##x #ifdef __APPLE__ # define GLOBAL(x) _##x @@ -33,6 +29,15 @@ #define THREAD_EXCEPTION_OFFSET 2156 #define THREAD_EXCEPTION_HANDLER 2160 +#define CONTINUATION_NEXT 4 +#define CONTINUATION_ADDRESS 16 +#define CONTINUATION_RETURN_ADDRESS_OFFSET 20 +#define CONTINUATION_FRAME_POINTER_OFFSET 24 +#define CONTINUATION_LENGTH 28 +#define CONTINUATION_BODY 32 + +#define ARGUMENT_BASE (BYTES_PER_WORD * 2) + .globl GLOBAL(vmInvoke) GLOBAL(vmInvoke): /* @@ -83,12 +88,8 @@ LOCAL(vmInvoke_argumentTest): // we use r8 to hold the thread pointer, by convention mov r8, r0 -.global GLOBAL(beforecall) -GLOBAL(beforecall): // load and call function address blx r1 -.global GLOBAL(aftercall) -GLOBAL(aftercall): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): @@ -99,6 +100,75 @@ GLOBAL(vmInvoke_returnAddress): .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): +#ifdef AVIAN_CONTINUATIONS + // call the next continuation, if any + ldr r5,[r8,#THREAD_CONTINUATION] + cmp r5,#0 + beq LOCAL(vmInvoke_exit) + + ldr r6,[r5,#CONTINUATION_LENGTH] + lsl r6,r6,#2 + neg r7,r6 + add r7,r7,#-80 + mov r4,sp + str r4,[sp,r7]! + + add r7,r5,#CONTINUATION_BODY + + mov r11,#0 + add r10,sp,#ARGUMENT_BASE + b LOCAL(vmInvoke_continuationTest) + +LOCAL(vmInvoke_continuationLoop): + ldr r9,[r7,r11] + str r9,[r10,r11] + add r11,r11,#4 + +LOCAL(vmInvoke_continuationTest): + cmp r11,r6 + ble LOCAL(vmInvoke_continuationLoop) + + ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] + ldr r10,LOCAL(vmInvoke_returnAddress_word) + ldr r11,LOCAL(vmInvoke_getAddress_word) +LOCAL(vmInvoke_getAddress): + add r11,pc,r11 + ldr r11,[r11,r10] + str r11,[sp,r7] + + ldr r7,[r5,#CONTINUATION_FRAME_POINTER_OFFSET] + ldr r11,[sp] + add r7,r7,sp + str r11,[r7] + str r7,[sp] + + ldr r7,[r5,#CONTINUATION_NEXT] + str r7,[r8,#THREAD_CONTINUATION] + + // call the continuation unless we're handling an exception + ldr r7,[r8,#THREAD_EXCEPTION] + cmp r7,#0 + bne LOCAL(vmInvoke_handleException) + ldr r7,[r5,#CONTINUATION_ADDRESS] + bx r7 + +LOCAL(vmInvoke_handleException): + // we're handling an exception - call the exception handler instead + mov r11,#0 + str r11,[r8,#THREAD_EXCEPTION] + ldr r11,[r8,#THREAD_EXCEPTION_STACK_ADJUSTMENT] + ldr r9,[sp] + neg r11,r11 + str r9,[sp,r11]! + ldr r11,[r8,#THREAD_EXCEPTION_OFFSET] + str r7,[sp,r11] + + ldr r7,[r8,#THREAD_EXCEPTION_HANDLER] + bx r7 + +LOCAL(vmInvoke_exit): +#endif // AVIAN_CONTINUATIONS + mov ip, #0 str ip, [r8, #THREAD_STACK] @@ -124,6 +194,71 @@ LOCAL(vmInvoke_return): .globl GLOBAL(vmJumpAndInvoke) GLOBAL(vmJumpAndInvoke): - // vmJumpAndInvoke should only be called when continuations are - // enabled - bkpt +#ifdef AVIAN_CONTINUATIONS + // r0: thread + // r1: address + // r2: (unused) + // r3: stack + // [sp,#0]: argumentFootprint + // [sp,#4]: arguments + // [sp,#8]: frameSize + + ldr r4,[sp] + ldr r5,[sp,#4] + ldr r6,[sp,#8] + + // restore (pseudo)-stack pointer (we don't want to touch the real + // stack pointer, since we haven't copied the arguments yet) + ldr r3,[r3] + + // make everything between sp and r3 one big stack frame while we + // shuffle things around + str r3,[sp] + + // allocate new frame, adding room for callee-saved registers + neg r10,r6 + add r10,r10,#-80 + mov r2,r3 + str r2,[r3,r10]! + + mov r8,r0 + + // copy arguments into place + mov r6,#0 + add r9,r3,#ARGUMENT_BASE + b LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + ldr r12,[r5,r6] + str r12,[r9,r6] + add r6,r6,#4 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmp r6,r4 + ble LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + mov sp,r3 + + // set return address to vmInvoke_returnAddress + ldr r10,LOCAL(vmInvoke_returnAddress_word) + ldr r11,LOCAL(vmJumpAndInvoke_getAddress_word) +LOCAL(vmJumpAndInvoke_getAddress): + add r11,pc,r11 + ldr lr,[r11,r10] + + bx r1 +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + bkpt +#endif // not AVIAN_CONTINUATIONS + +LOCAL(vmInvoke_returnAddress_word): + .word GLOBAL(vmInvoke_returnAddress)(GOT) +LOCAL(vmInvoke_getAddress_word): + .word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmInvoke_getAddress)+8) +LOCAL(vmJumpAndInvoke_getAddress_word): + .word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmJumpAndInvoke_getAddress)+8) +