corda/src/compile-x86.S

448 lines
11 KiB
ArmAsm
Raw Normal View History

2009-03-15 18:02:36 +00:00
/* Copyright (c) 2008-2009, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "types.h"
#define LOCAL(x) .L##x
#if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
# define GLOBAL(x) _##x
#else
# define GLOBAL(x) x
#endif
.text
#ifdef __x86_64__
2009-05-05 01:04:17 +00:00
#define THREAD_CONTINUATION 168
#define THREAD_EXCEPTION 64
2009-05-25 04:27:50 +00:00
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 176
2009-05-05 01:04:17 +00:00
#define THREAD_EXCEPTION_OFFSET 184
#define THREAD_EXCEPTION_HANDLER 192
#define CONTINUATION_NEXT 8
2009-05-23 22:15:06 +00:00
#define CONTINUATION_ADDRESS 32
#define CONTINUATION_RETURN_ADDRESS_OFFSET 40
#define CONTINUATION_FRAME_POINTER_OFFSET 48
#define CONTINUATION_LENGTH 56
#define CONTINUATION_BODY 64
2009-05-29 01:54:32 +00:00
#define CALLEE_SAVED_REGISTER_FOOTPRINT 48
.globl GLOBAL(vmInvoke)
GLOBAL(vmInvoke):
pushq %rbp
movq %rsp,%rbp
2007-12-11 21:26:59 +00:00
// %rdi: thread
// %rsi: function
// %rdx: arguments
// %rcx: argumentFootprint
// %r8 : frameSize
// %r9 : returnType (ignored)
// allocate stack space, adding room for callee-saved registers
2009-05-29 01:54:32 +00:00
subq %r8,%rsp
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
// save callee-saved registers
movq %rsp,%r9
addq %r8,%r9
movq %rbx,0(%r9)
movq %r12,8(%r9)
movq %r13,16(%r9)
movq %r14,24(%r9)
movq %r15,32(%r9)
2007-12-11 21:26:59 +00:00
// we use rbx to hold the thread pointer, by convention
2007-12-11 21:26:59 +00:00
mov %rdi,%rbx
2007-12-20 01:42:12 +00:00
// copy arguments into place
2007-12-11 21:26:59 +00:00
movq $0,%r9
2009-05-03 20:57:11 +00:00
jmp LOCAL(vmInvoke_argumentTest)
2009-05-03 20:57:11 +00:00
LOCAL(vmInvoke_argumentLoop):
movq (%rdx,%r9,1),%r8
movq %r8,(%rsp,%r9,1)
addq $8,%r9
2009-05-03 20:57:11 +00:00
LOCAL(vmInvoke_argumentTest):
2007-12-11 21:26:59 +00:00
cmpq %rcx,%r9
2009-05-03 20:57:11 +00:00
jb LOCAL(vmInvoke_argumentLoop)
// call function
2007-12-11 21:26:59 +00:00
call *%rsi
.globl GLOBAL(vmInvoke_returnAddress)
GLOBAL(vmInvoke_returnAddress):
// restore stack pointer
movq %rbp,%rsp
2009-05-03 20:57:11 +00:00
#ifdef AVIAN_CONTINUATIONS
2009-05-05 01:04:17 +00:00
// call the next continuation, if any
2009-05-03 20:57:11 +00:00
movq THREAD_CONTINUATION(%rbx),%rcx
cmpq $0,%rcx
je LOCAL(vmInvoke_exit)
2009-05-29 01:54:32 +00:00
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
// + CALLEE_SAVED_REGISTER_FOOTPRINT
2009-05-05 01:04:17 +00:00
movq CONTINUATION_LENGTH(%rcx),%rsi
shlq $3,%rsi
subq %rsi,%rsp
2009-05-29 01:54:32 +00:00
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
// copy the continuation body into the frame
leaq CONTINUATION_BODY(%rcx),%rdi
2009-05-03 20:57:11 +00:00
movq $0,%r9
jmp LOCAL(vmInvoke_continuationTest)
LOCAL(vmInvoke_continuationLoop):
movq (%rdi,%r9,1),%r8
movq %r8,(%rsp,%r9,1)
addq $8,%r9
LOCAL(vmInvoke_continuationTest):
cmpq %rsi,%r9
jb LOCAL(vmInvoke_continuationLoop)
2009-05-29 01:54:32 +00:00
// set the return address to vmInvoke_returnAddress
2009-05-03 20:57:11 +00:00
movq CONTINUATION_RETURN_ADDRESS_OFFSET(%rcx),%rdi
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
2009-05-05 01:04:17 +00:00
movq %r10,(%rsp,%rdi,1)
2009-05-29 01:54:32 +00:00
// save the current base pointer in the frame and update it
2009-05-03 20:57:11 +00:00
movq CONTINUATION_FRAME_POINTER_OFFSET(%rcx),%rdi
movq %rbp,(%rsp,%rdi,1)
addq %rsp,%rdi
movq %rdi,%rbp
2009-05-29 01:54:32 +00:00
// consume the continuation
2009-05-03 20:57:11 +00:00
movq CONTINUATION_NEXT(%rcx),%rdi
movq %rdi,THREAD_CONTINUATION(%rbx)
// call the continuation unless we're handling an exception
movq THREAD_EXCEPTION(%rbx),%rsi
cmpq $0,%rsi
2009-05-05 01:04:17 +00:00
jne LOCAL(vmInvoke_handleException)
jmp *CONTINUATION_ADDRESS(%rcx)
2009-05-03 20:57:11 +00:00
2009-05-05 01:04:17 +00:00
LOCAL(vmInvoke_handleException):
2009-05-03 20:57:11 +00:00
// we're handling an exception - call the exception handler instead
movq $0,THREAD_EXCEPTION(%rbx)
2009-05-25 04:27:50 +00:00
movq THREAD_EXCEPTION_STACK_ADJUSTMENT(%rbx),%rdi
subq %rdi,%rsp
2009-05-03 20:57:11 +00:00
movq THREAD_EXCEPTION_OFFSET(%rbx),%rdi
movq %rsi,(%rsp,%rdi,1)
jmp *THREAD_EXCEPTION_HANDLER(%rbx)
LOCAL(vmInvoke_exit):
#endif // AVIAN_CONTINUATIONS
2009-05-29 01:54:32 +00:00
// restore callee-saved registers (below the stack pointer, but in
// the red zone)
movq %rsp,%r9
2009-05-29 01:54:32 +00:00
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r9
movq 0(%r9),%rbx
movq 8(%r9),%r12
movq 16(%r9),%r13
movq 24(%r9),%r14
movq 32(%r9),%r15
// return
popq %rbp
ret
2009-05-03 20:57:11 +00:00
.globl GLOBAL(vmJumpAndInvoke)
GLOBAL(vmJumpAndInvoke):
#ifdef AVIAN_CONTINUATIONS
// %rdi: thread
// %rsi: address
// %rdx: base
2009-05-29 01:54:32 +00:00
// %rcx: (unused)
// %r8 : argumentFootprint
// %r9 : arguments
// 8(%rsp): frameSize
movq %rdx,%rbp
2009-05-29 01:54:32 +00:00
// restore (pseudo)-stack pointer (we don't want to touch the real
// stack pointer, since we haven't copied the arguments yet)
movq %rbp,%rcx
// allocate new frame, adding room for callee-saved registers
movl 8(%rsp),%eax
subq %rax,%rcx
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rcx
2009-05-03 20:57:11 +00:00
2009-05-29 01:54:32 +00:00
movq %rdi,%rbx
2009-05-23 22:15:06 +00:00
// set return address
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
2009-05-24 17:18:17 +00:00
movq %r10,(%rcx)
2009-05-23 22:15:06 +00:00
// copy arguments into place
movq $0,%r11
jmp LOCAL(vmJumpAndInvoke_argumentTest)
LOCAL(vmJumpAndInvoke_argumentLoop):
movq (%r9,%r11,1),%r10
2009-05-24 17:18:17 +00:00
movq %r10,8(%rcx,%r11,1)
2009-05-23 22:15:06 +00:00
addq $8,%r11
LOCAL(vmJumpAndInvoke_argumentTest):
cmpq %r8,%r11
jb LOCAL(vmJumpAndInvoke_argumentLoop)
2009-05-24 17:18:17 +00:00
2009-05-29 01:54:32 +00:00
// the arguments have been copied, so we can set the real stack
// pointer now
2009-05-24 17:18:17 +00:00
movq %rcx,%rsp
2009-05-23 22:15:06 +00:00
2009-05-03 20:57:11 +00:00
jmp *%rsi
#else // not AVIAN_CONTINUATIONS
// vmJumpAndInvoke should only be called when continuations are
// enabled
int3
#endif // not AVIAN_CONTINUATIONS
2009-05-03 20:57:11 +00:00
#elif defined __i386__
#define THREAD_CONTINUATION 96
#define THREAD_EXCEPTION 36
2009-05-25 04:27:50 +00:00
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 100
#define THREAD_EXCEPTION_OFFSET 104
#define THREAD_EXCEPTION_HANDLER 108
#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
2009-05-29 01:54:32 +00:00
#define CALLEE_SAVED_REGISTER_FOOTPRINT 16
.globl GLOBAL(vmInvoke)
GLOBAL(vmInvoke):
pushl %ebp
movl %esp,%ebp
2007-12-11 21:26:59 +00:00
// 8(%ebp): thread
// 12(%ebp): function
// 16(%ebp): arguments
// 20(%ebp): argumentFootprint
// 24(%ebp): frameSize
// 28(%ebp): returnType
// allocate stack space, adding room for callee-saved registers
subl 24(%ebp),%esp
2009-05-29 01:54:32 +00:00
subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp
// save callee-saved registers
movl %esp,%ecx
addl 24(%ebp),%ecx
movl %ebx,0(%ecx)
movl %esi,4(%ecx)
movl %edi,8(%ecx)
2007-12-11 21:26:59 +00:00
// we use ebx to hold the thread pointer, by convention
mov 8(%ebp),%ebx
// copy arguments into place
movl $0,%ecx
movl 16(%ebp),%edx
jmp LOCAL(vmInvoke_argumentTest)
LOCAL(vmInvoke_argumentLoop):
movl (%edx,%ecx,1),%eax
movl %eax,(%esp,%ecx,1)
addl $4,%ecx
LOCAL(vmInvoke_argumentTest):
2007-12-11 21:26:59 +00:00
cmpl 20(%ebp),%ecx
jb LOCAL(vmInvoke_argumentLoop)
// call function
2007-12-11 21:26:59 +00:00
call *12(%ebp)
.globl vmInvoke_returnAddress
vmInvoke_returnAddress:
2009-05-29 01:54:32 +00:00
// restore stack pointer, preserving the area containing saved
// registers
movl %ebp,%ecx
2009-05-29 01:54:32 +00:00
subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%ecx
movl %ecx,%esp
#ifdef AVIAN_CONTINUATIONS
// call the next continuation, if any
movl THREAD_CONTINUATION(%ebx),%ecx
cmpl $0,%ecx
je LOCAL(vmInvoke_exit)
2009-05-29 01:54:32 +00:00
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
movl CONTINUATION_LENGTH(%ecx),%esi
2009-05-25 00:22:36 +00:00
shll $2,%esi
subl %esi,%esp
2009-05-29 01:54:32 +00:00
// copy the continuation body into the frame
leal CONTINUATION_BODY(%ecx),%edi
push %eax
push %edx
movl $0,%edx
jmp LOCAL(vmInvoke_continuationTest)
LOCAL(vmInvoke_continuationLoop):
movl (%edi,%edx,1),%eax
2009-05-25 00:22:36 +00:00
movl %eax,8(%esp,%edx,1)
addl $4,%edx
LOCAL(vmInvoke_continuationTest):
cmpl %esi,%edx
jb LOCAL(vmInvoke_continuationLoop)
pop %edx
pop %eax
2009-05-29 01:54:32 +00:00
// set the return address to vmInvoke_returnAddress
movl CONTINUATION_RETURN_ADDRESS_OFFSET(%ecx),%edi
call LOCAL(getPC)
addl $_GLOBAL_OFFSET_TABLE_,%esi
movl vmInvoke_returnAddress@GOT(%esi),%esi
movl %esi,(%esp,%edi,1)
2009-05-29 01:54:32 +00:00
// save the current base pointer in the frame and update it
movl CONTINUATION_FRAME_POINTER_OFFSET(%ecx),%edi
movl %ebp,(%esp,%edi,1)
addl %esp,%edi
movl %edi,%ebp
2009-05-29 01:54:32 +00:00
// consume the continuation
movl CONTINUATION_NEXT(%ecx),%edi
movl %edi,THREAD_CONTINUATION(%ebx)
// call the continuation unless we're handling an exception
movl THREAD_EXCEPTION(%ebx),%esi
cmpl $0,%esi
jne LOCAL(vmInvoke_handleException)
jmp *CONTINUATION_ADDRESS(%ecx)
LOCAL(vmInvoke_handleException):
// we're handling an exception - call the exception handler instead
movl $0,THREAD_EXCEPTION(%ebx)
2009-05-25 04:27:50 +00:00
movl THREAD_EXCEPTION_STACK_ADJUSTMENT(%ebx),%edi
subl %edi,%esp
movl THREAD_EXCEPTION_OFFSET(%ebx),%edi
movl %esi,(%esp,%edi,1)
jmp *THREAD_EXCEPTION_HANDLER(%ebx)
LOCAL(vmInvoke_exit):
#endif // AVIAN_CONTINUATIONS
// restore callee-saved registers
movl 0(%esp),%ebx
movl 4(%esp),%esi
movl 8(%esp),%edi
// handle return value based on expected type
movl 28(%ebp),%ecx
2009-05-29 01:54:32 +00:00
addl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp
LOCAL(vmInvoke_void):
cmpl $VOID_TYPE,%ecx
jne LOCAL(vmInvoke_int64)
jmp LOCAL(vmInvoke_return)
LOCAL(vmInvoke_int64):
cmpl $INT64_TYPE,%ecx
jne LOCAL(vmInvoke_int32)
jmp LOCAL(vmInvoke_return)
LOCAL(vmInvoke_int32):
movl $0,%edx
LOCAL(vmInvoke_return):
popl %ebp
ret
LOCAL(getPC):
movl (%esp),%esi
ret
.globl GLOBAL(vmJumpAndInvoke)
GLOBAL(vmJumpAndInvoke):
#ifdef AVIAN_CONTINUATIONS
2009-05-24 17:18:17 +00:00
// 4(%esp): thread
// 8(%esp): address
// 12(%esp): base
2009-05-29 01:54:32 +00:00
// 16(%esp): (unused)
2009-05-24 17:18:17 +00:00
// 20(%esp): argumentFootprint
// 24(%esp): arguments
// 28(%esp): frameSize
movl 12(%esp),%ebp
2009-05-29 01:54:32 +00:00
// restore (pseudo)-stack pointer (we don't want to touch the real
// stack pointer, since we haven't copied the arguments yet)
movl %ebp,%ecx
// allocate new frame, adding room for callee-saved registers
subl 28(%esp),%ecx
2009-05-29 01:54:32 +00:00
subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%ecx
movl 4(%esp),%ebx
// set return address
call LOCAL(getPC)
addl $_GLOBAL_OFFSET_TABLE_,%esi
movl vmInvoke_returnAddress@GOT(%esi),%esi
2009-05-24 17:18:17 +00:00
movl %esi,(%ecx)
// copy arguments into place
2009-05-24 17:18:17 +00:00
movl $0,%esi
movl 20(%esp),%edx
movl 24(%esp),%eax
jmp LOCAL(vmJumpAndInvoke_argumentTest)
LOCAL(vmJumpAndInvoke_argumentLoop):
2009-05-24 17:18:17 +00:00
movl (%eax,%esi,1),%edi
movl %edi,4(%ecx,%esi,1)
addl $4,%esi
LOCAL(vmJumpAndInvoke_argumentTest):
2009-05-24 17:18:17 +00:00
cmpl %edx,%esi
jb LOCAL(vmJumpAndInvoke_argumentLoop)
2009-05-24 17:18:17 +00:00
movl 8(%esp),%esi
2009-05-29 01:54:32 +00:00
// the arguments have been copied, so we can set the real stack
// pointer now
2009-05-24 17:18:17 +00:00
movl %ecx,%esp
jmp *%esi
#else // not AVIAN_CONTINUATIONS
// vmJumpAndInvoke should only be called when continuations are
// enabled
int3
#endif // AVIAN_CONTINUATIONS
2007-10-04 00:41:54 +00:00
#else
# error unsupported platform
#endif