implement continuations support for ARM

This commit is contained in:
Joel Dice 2010-11-08 04:18:10 +00:00
parent 36a8ba28e5
commit 0f0427f23b

View File

@ -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)