diff --git a/makefile b/makefile index ddaa378425..29465173c1 100755 --- a/makefile +++ b/makefile @@ -1217,7 +1217,9 @@ clean: @echo "removing build" rm -rf build +ifeq ($(continuations),true) $(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) +endif gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') $(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) diff --git a/src/arm.masm b/src/arm.masm index 2af5048ec7..e7bd2d864c 100644 --- a/src/arm.masm +++ b/src/arm.masm @@ -12,7 +12,7 @@ AREA text, CODE, ARM - EXPORT vmNativeCall [FUNC] + EXPORT vmNativeCall vmNativeCall ; arguments: ; r0 -> r4 : function @@ -48,7 +48,7 @@ loop ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return - EXPORT vmJump [FUNC] + EXPORT vmJump vmJump mov lr, r0 ldr r0, [sp] @@ -60,7 +60,7 @@ vmJump CHECKPOINT_THREAD EQU 4 CHECKPOINT_STACK EQU 24 - EXPORT vmRun [FUNC] + EXPORT vmRun vmRun ; r0: function ; r1: arguments @@ -76,13 +76,13 @@ vmRun blx r12 - EXPORT vmRun_returnAddress [FUNC] + EXPORT vmRun_returnAddress vmRun_returnAddress add sp, sp, #12 ldmfd sp!, {r4-r11, lr} bx lr - EXPORT vmTrap [FUNC] + EXPORT vmTrap vmTrap bkpt 3 diff --git a/src/compile-arm.masm b/src/compile-arm.masm new file mode 100644 index 0000000000..a9c1e59cef --- /dev/null +++ b/src/compile-arm.masm @@ -0,0 +1,252 @@ +; Copyright (c) 2008-2011, 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. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + +; types.inc +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +; target-fields.inc +;TARGET_BYTES_PER_WORD = 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + AREA text, CODE, ARM + +BYTES_PER_WORD equ 4 + +CONTINUATION_NEXT equ 4 +CONTINUATION_ADDRESS equ 16 +CONTINUATION_RETURN_ADDRESS_OFFSET equ 20 +CONTINUATION_FRAME_POINTER_OFFSET equ 24 +CONTINUATION_LENGTH equ 28 +CONTINUATION_BODY equ 32 + + EXPORT vmInvoke +vmInvoke + + ; arguments + ; r0 : thread + ; r1 : function + ; r2 : arguments + ; r3 : argumentFootprint + ; [sp, #0] : frameSize (not used) + ; [sp, #4] : returnType + + + ; save all non-volatile registers + stmfd sp!, {r4-r11, lr} + + ; save return type + ldr r4, [sp, #4] + str r4, [sp, #-4]! + + str sp, [r0, #TARGET_THREAD_SCRATCH] + + ; align stack, if necessary + eor r4, sp, r3 + tst r4, #4 + subne sp, sp, #4 + + ; copy arguments into place + sub sp, sp, r3 + mov r4, #0 + b vmInvoke_argumentTest + +vmInvoke_argumentLoop + ldr r5, [r2, r4] + str r5, [sp, r4] + add r4, r4, #BYTES_PER_WORD + +vmInvoke_argumentTest + cmp r4, r3 + blt vmInvoke_argumentLoop + + ; we use r8 to hold the thread pointer, by convention + mov r8, r0 + + ; load and call function address + blx r1 + + EXPORT vmInvoke_returnAddress +vmInvoke_returnAddress + ; restore stack pointer + ldr sp, [r8, #TARGET_THREAD_SCRATCH] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov r5, #0 + str r5, [r8, #TARGET_THREAD_STACK] + + EXPORT vmInvoke_safeStack +vmInvoke_safeStack + +;if AVIAN_CONTINUATIONS +; ; call the next continuation, if any +; ldr r5,[r8,#TARGET_THREAD_CONTINUATION] +; cmp r5,#0 +; beq 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 +; b vmInvoke_continuationTest +; +;vmInvoke_continuationLoop +; ldr r9,[r7,r11] +; str r9,[sp,r11] +; add r11,r11,#4 +; +;vmInvoke_continuationTest +; cmp r11,r6 +; ble vmInvoke_continuationLoop) +; +; ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] +; ldr r10,vmInvoke_returnAddress_word +; ldr r11,vmInvoke_getAddress_word +;vmInvoke_getAddress +; add r11,pc,r11 +; ldr r11,[r11,r10] +; str r11,[sp,r7] +; +; ldr r7,[r5,#CONTINUATION_NEXT] +; str r7,[r8,#TARGET_THREAD_CONTINUATION] +; +; ; call the continuation unless we're handling an exception +; ldr r7,[r8,#TARGET_THREAD_EXCEPTION] +; cmp r7,#0 +; bne vmInvoke_handleException) +; ldr r7,[r5,#CONTINUATION_ADDRESS] +; bx r7 +; +;vmInvoke_handleException +; ; we're handling an exception - call the exception handler instead +; mov r11,#0 +; str r11,[r8,#TARGET_THREAD_EXCEPTION] +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] +; ldr r9,[sp] +; neg r11,r11 +; str r9,[sp,r11]! +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] +; str r7,[sp,r11] +; +; ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] +; bx r7 +; +;vmInvoke_exit +;endif ; AVIAN_CONTINUATIONS + + mov ip, #0 + str ip, [r8, #TARGET_THREAD_STACK] + + ; restore return type + ldr ip, [sp], #4 + + ; restore callee-saved registers + ldmfd sp!, {r4-r11, lr} + +vmInvoke_return + bx lr + + EXPORT vmJumpAndInvoke +vmJumpAndInvoke +;if :DEF:AVIAN_CONTINUATIONS +; ; r0: thread +; ; r1: address +; ; r2: stack +; ; r3: argumentFootprint +; ; [sp,#0]: arguments +; ; [sp,#4]: frameSize +; +; ldr r5,[sp,#0] +; ldr r6,[sp,#4] +; +; ; allocate new frame, adding room for callee-saved registers, plus +; ; 4 bytes of padding since the calculation of frameSize assumes 4 +; ; bytes have already been allocated to save the return address, +; ; which is not true in this case +; sub r2,r2,r6 +; sub r2,r2,#84 +; +; mov r8,r0 +; +; ; copy arguments into place +; mov r6,#0 +; b vmJumpAndInvoke_argumentTest +; +;vmJumpAndInvoke_argumentLoop +; ldr r12,[r5,r6] +; str r12,[r2,r6] +; add r6,r6,#4 +; +;vmJumpAndInvoke_argumentTest +; cmp r6,r3 +; ble vmJumpAndInvoke_argumentLoop +; +; ; the arguments have been copied, so we can set the real stack +; ; pointer now +; mov sp,r2 +; +; ; set return address to vmInvoke_returnAddress +; ldr r10,vmInvoke_returnAddress_word) +; ldr r11,vmJumpAndInvoke_getAddress_word) +;vmJumpAndInvoke_getAddress +; add r11,pc,r11 +; ldr lr,[r11,r10] +; +; bx r1 +; +;vmInvoke_returnAddress_word +; .word GLOBAL(vmInvoke_returnAddress)(GOT) +;vmInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmInvoke_getAddress)+8) +;vmJumpAndInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmJumpAndInvoke_getAddress)+8) +; +;else ; not AVIAN_CONTINUATIONS + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + bkpt 0 +;endif ; not AVIAN_CONTINUATIONS + + END \ No newline at end of file diff --git a/src/compile-x86.masm b/src/compile-x86.masm new file mode 100644 index 0000000000..f07d799faf --- /dev/null +++ b/src/compile-x86.masm @@ -0,0 +1,173 @@ +comment # + Copyright (c) 2008-2011, 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. + + ORIGIN: https://github.com/gkvas/avian/tree/wince +# + +.586 +.MODEL FLAT, C + +comment # types.h # +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +comment # target-fields.h # +ifdef TARGET_BYTES_PER_WORD + if TARGET_BYTES_PER_WORD eq 8 + +TARGET_THREAD_EXCEPTION equ 80 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2256 +TARGET_THREAD_EXCEPTIONOFFSET equ 2264 +TARGET_THREAD_EXCEPTIONHANDLER equ 2272 + +TARGET_THREAD_IP equ 2216 +TARGET_THREAD_STACK equ 2224 +TARGET_THREAD_NEWSTACK equ 2232 +TARGET_THREAD_SCRATCH equ 2240 +TARGET_THREAD_CONTINUATION equ 2248 +TARGET_THREAD_TAILADDRESS equ 2280 +TARGET_THREAD_VIRTUALCALLTARGET equ 2288 +TARGET_THREAD_VIRTUALCALLINDEX equ 2296 +TARGET_THREAD_HEAPIMAGE equ 2304 +TARGET_THREAD_CODEIMAGE equ 2312 +TARGET_THREAD_THUNKTABLE equ 2320 +TARGET_THREAD_STACKLIMIT equ 2368 + + elseif TARGET_BYTES_PER_WORD eq 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + else + error + endif +else + error +endif + +ifdef AVIAN_USE_FRAME_POINTER + ALIGNMENT_ADJUSTMENT equ 0 +else + ALIGNMENT_ADJUSTMENT equ 12 +endif + +CALLEE_SAVED_REGISTER_FOOTPRINT equ 16 + ALIGNMENT_ADJUSTMENT + +_TEXT SEGMENT + +public C vmInvoke +vmInvoke: + push ebp + mov ebp,esp + + ; 8(%ebp): thread + ; 12(%ebp): function + ; 16(%ebp): arguments + ; 20(%ebp): argumentFootprint + ; 24(%ebp): frameSize + ; 28(%ebp): returnType + + ; allocate stack space for callee-saved registers + sub esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + ; remember this stack position, since we won't be able to rely on + ; %rbp being restored when the call returns + mov eax,ds:dword ptr[8+ebp] + mov ds:dword ptr[TARGET_THREAD_SCRATCH+eax],esp + + mov ds:dword ptr[0+esp],ebx + mov ds:dword ptr[4+esp],esi + mov ds:dword ptr[8+esp],edi + + ; allocate stack space for arguments + sub esp,ds:dword ptr[24+ebp] + + ; we use ebx to hold the thread pointer, by convention + mov ebx,eax + + ; copy arguments into place + mov ecx,0 + mov edx,ds:dword ptr[16+ebp] + jmp LvmInvoke_argumentTest + +LvmInvoke_argumentLoop: + mov eax,ds:dword ptr[edx+ecx*1] + mov ds:dword ptr[esp+ecx*1],eax + add ecx,4 + +LvmInvoke_argumentTest: + cmp ecx,ds:dword ptr[20+ebp] + jb LvmInvoke_argumentLoop + + ; call function + call dword ptr[12+ebp] + +public vmInvoke_returnAddress +vmInvoke_returnAddress: + ; restore stack pointer + mov esp,ds:dword ptr[TARGET_THREAD_SCRATCH+ebx] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov ds:dword ptr[TARGET_THREAD_STACK+ebx],0 + +public vmInvoke_safeStack +vmInvoke_safeStack: + + ; restore callee-saved registers + mov ebx,ds:dword ptr[0+esp] + mov esi,ds:dword ptr[4+esp] + mov edi,ds:dword ptr[8+esp] + + add esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + mov ecx,ds:dword ptr[28+esp] + + pop ebp + ret + +LgetPC: + mov esi,ds:dword ptr[esp] + ret + +public vmJumpAndInvoke +vmJumpAndInvoke: + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + int 3 + +_TEXT ENDS + +END