X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fx86-assem.S;h=315643b0130538992c5f987a6ec800362537e40d;hb=4b585c19dcd87dc3410094a2d2d7385d49200a44;hp=d1c2f49d92d57e5517be65a975a45a3ca946bd25;hpb=6e6670a5c26b3594a0eaa8da59db75b48e0db878;p=sbcl.git diff --git a/src/runtime/x86-assem.S b/src/runtime/x86-assem.S index d1c2f49..315643b 100644 --- a/src/runtime/x86-assem.S +++ b/src/runtime/x86-assem.S @@ -17,6 +17,7 @@ #include "sbcl.h" #include "validate.h" #include "genesis/closure.h" +#include "genesis/funcallable-instance.h" #include "genesis/fdefn.h" #include "genesis/static-symbols.h" #include "genesis/symbol.h" @@ -62,7 +63,7 @@ * that are defined to be no-ops on win32. Hopefully this still works on * other platforms. */ -#ifndef LISP_FEATURE_WIN32 +#if !defined(LISP_FEATURE_WIN32) && !defined(LISP_FEATURE_DARWIN) #define TYPE(name) .type name,@function #define SIZE(name) .size name,.-name #else @@ -70,9 +71,24 @@ #define SIZE(name) #endif +/* + * x86/darwin (as of MacOS X 10.4.5) doesn't reliably file signal + * handlers (SIGTRAP or Mach exception handlers) for 0xCC, wo we have + * to use ud2 instead. ud2 is an undefined opcode, #x0b0f, or + * 0F 0B in low-endian notation, that causes SIGILL to fire. We check + * for this instruction in the SIGILL handler and if we see it, we + * advance the EIP by two bytes to skip over ud2 instruction and + * call sigtrap_handler. */ +#if defined(LISP_FEATURE_DARWIN) +#define END() +#define TRAP ud2 +#else +#define END() .end +#define TRAP int3 +#endif + .text - .global GNAME(foreign_function_call_active) - .global GNAME(all_threads) + .globl GNAME(all_threads) /* * A call to call_into_c preserves esi, edi, and ebp. @@ -84,14 +100,15 @@ * floats. * * This should work for Lisp calls C calls Lisp calls C.. + * + * FIXME & OAOOM: This duplicates call-out in src/compiler/x86/c-call.lisp, + * so if you tweak this, change that too! */ .text .align align_16byte,0x90 - .global GNAME(call_into_c) + .globl GNAME(call_into_c) TYPE(GNAME(call_into_c)) GNAME(call_into_c): - movl $1,GNAME(foreign_function_call_active) - /* Save the return Lisp address in ebx. */ popl %ebx @@ -105,17 +122,12 @@ GNAME(call_into_c): fstp %st(0) fstp %st(0) -#ifdef LISP_FEATURE_WIN32 - cld -#endif - - call *%eax # normal callout using Lisp stack - - movl %eax,%ecx # remember integer return value + call *%eax # normal callout using Lisp stack + movl %eax,%ecx # remember integer return value /* Check for a return FP value. */ fxam - fnstsw %eax + fnstsw %ax andl $0x4500,%eax cmpl $0x4100,%eax jne Lfp_rtn_value @@ -134,7 +146,6 @@ GNAME(call_into_c): /* Restore the return value. */ movl %ecx,%eax # maybe return value - movl $0,GNAME(foreign_function_call_active) /* Return. */ jmp *%ebx @@ -152,15 +163,14 @@ Lfp_rtn_value: /* We don't need to restore eax, because the result is in st(0). */ - movl $0,GNAME(foreign_function_call_active) -/* Return. */ +/* Return. FIXME: It would be nice to restructure this to use RET. */ jmp *%ebx SIZE(GNAME(call_into_c)) .text - .global GNAME(call_into_lisp_first_time) + .globl GNAME(call_into_lisp_first_time) TYPE(GNAME(call_into_lisp_first_time)) /* The *ALIEN-STACK* pointer is set up on the first call_into_lisp when @@ -175,10 +185,8 @@ GNAME(call_into_lisp_first_time): #ifndef LISP_FEATURE_WIN32 movl %esp,ALIEN_STACK + SYMBOL_VALUE_OFFSET movl GNAME(all_threads),%eax - movl THREAD_CONTROL_STACK_START_OFFSET(%eax) ,%esp - /* don't think too hard about what happens if we get interrupted - * here */ - addl $THREAD_CONTROL_STACK_SIZE-4,%esp + /* pthread machinery takes care of this for other threads */ + movl THREAD_CONTROL_STACK_END_OFFSET(%eax) ,%esp #else /* Win32 -really- doesn't like you switching stacks out from under it. */ movl GNAME(all_threads),%eax @@ -186,7 +194,7 @@ GNAME(call_into_lisp_first_time): jmp Lstack .text - .global GNAME(call_into_lisp) + .globl GNAME(call_into_lisp) TYPE(GNAME(call_into_lisp)) /* The C conventions require that ebx, esi, edi, and ebp be preserved @@ -232,8 +240,6 @@ Lstack: xorl %esi,%esi # third arg /* no longer in function call */ - movl %eax, GNAME(foreign_function_call_active) - movl %esp,%ebx # remember current stack pushl %ebx # Save entry stack on (maybe) new stack. @@ -254,6 +260,19 @@ Lstack: Ldone: /* Registers eax, ecx, edx, edi, and esi are now live. */ +#ifdef LISP_FEATURE_WIN32 + /* Establish an SEH frame. */ +#ifdef LISP_FEATURE_SB_THREAD + /* FIXME: need to save BSP here. */ +#error "need to save BSP here, but don't know how yet." +#else + pushl BINDING_STACK_POINTER + SYMBOL_VALUE_OFFSET +#endif + pushl $GNAME(exception_handler_wrapper) + pushl %fs:0 + movl %esp, %fs:0 +#endif + /* Alloc new frame. */ mov %esp,%ebx # The current sp marks start of new frame. push %ebp # fp in save location S0 @@ -264,9 +283,17 @@ Ldone: /* If the function returned multiple values, it will return to this point. Lose them */ + jnc LsingleValue mov %ebx, %esp +LsingleValue: /* A singled value function returns here */ +#ifdef LISP_FEATURE_WIN32 + /* Remove our SEH frame. */ + popl %fs:0 + add $8, %esp +#endif + /* Restore the stack, in case there was a stack change. */ popl %esp # c-sp @@ -286,7 +313,7 @@ Ldone: /* support for saving and restoring the NPX state from C */ .text - .global GNAME(fpu_save) + .globl GNAME(fpu_save) TYPE(GNAME(fpu_save)) .align 2,0x90 GNAME(fpu_save): @@ -295,7 +322,7 @@ GNAME(fpu_save): ret SIZE(GNAME(fpu_save)) - .global GNAME(fpu_restore) + .globl GNAME(fpu_restore) TYPE(GNAME(fpu_restore)) .align 2,0x90 GNAME(fpu_restore): @@ -308,12 +335,12 @@ GNAME(fpu_restore): * the undefined-function trampoline */ .text - .align align_4byte,0x90 - .global GNAME(undefined_tramp) + .align align_16byte,0x90 + .globl GNAME(undefined_tramp) TYPE(GNAME(undefined_tramp)) .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG GNAME(undefined_tramp): - int3 + TRAP .byte trap_Error .byte 2 .byte UNDEFINED_FUN_ERROR @@ -325,8 +352,8 @@ GNAME(undefined_tramp): * the closure trampoline */ .text - .align align_4byte,0x90 - .global GNAME(closure_tramp) + .align align_16byte,0x90 + .globl GNAME(closure_tramp) TYPE(GNAME(closure_tramp)) .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG GNAME(closure_tramp): @@ -340,48 +367,57 @@ GNAME(closure_tramp): jmp *CLOSURE_FUN_OFFSET(%eax) SIZE(GNAME(closure_tramp)) + .text + .align align_16byte,0x90 + .globl GNAME(funcallable_instance_tramp) + TYPE(GNAME(funcallable_instance_tramp)) +GNAME(funcallable_instance_tramp): + movl FUNCALLABLE_INSTANCE_FUNCTION_OFFSET(%eax),%eax + /* KLUDGE: on this platform, whatever kind of function is in %rax + * now, the first word of it contains the address to jump to. */ + jmp *CLOSURE_FUN_OFFSET(%eax) + SIZE(GNAME(funcallable_instance_tramp)) + /* * fun-end breakpoint magic */ .text - .global GNAME(fun_end_breakpoint_guts) - .align align_4byte + .globl GNAME(fun_end_breakpoint_guts) + .align align_16byte GNAME(fun_end_breakpoint_guts): /* Multiple Value return */ - jmp multiple_value_return + jc multiple_value_return /* Single value return: The eventual return will now use the multiple values return convention but with a return values count of one. */ movl %esp,%ebx # Setup ebx - the ofp. subl $4,%esp # Allocate one stack slot for the return value movl $4,%ecx # Setup ecx for one return value. - movl $NIL,%edi # default second value - movl $NIL,%esi # default third value + movl $(NIL),%edi # default second value + movl $(NIL),%esi # default third value multiple_value_return: - .global GNAME(fun_end_breakpoint_trap) + .globl GNAME(fun_end_breakpoint_trap) GNAME(fun_end_breakpoint_trap): - int3 + TRAP .byte trap_FunEndBreakpoint hlt # We should never return here. - .global GNAME(fun_end_breakpoint_end) + .globl GNAME(fun_end_breakpoint_end) GNAME(fun_end_breakpoint_end): - .global GNAME(do_pending_interrupt) + .globl GNAME(do_pending_interrupt) TYPE(GNAME(do_pending_interrupt)) - .align align_4byte,0x90 + .align align_16byte,0x90 GNAME(do_pending_interrupt): - int3 + TRAP .byte trap_PendingInterrupt ret SIZE(GNAME(do_pending_interrupt)) - -/* - * Allocate bytes and return the start of the allocated space +/* Allocate bytes and return the start of the allocated space * in the specified destination register. * * In the general case the size will be in the destination register. @@ -389,361 +425,160 @@ GNAME(do_pending_interrupt): * All registers must be preserved except the destination. * The C conventions will preserve ebx, esi, edi, and ebp. * So only eax, ecx, and edx need special care here. + * + * ALLOC factors out the logic of calling alloc(): stack alignment, etc. + * + * DEFINE_ALLOC_TO_FOO defines an alloction routine. */ - - .globl GNAME(alloc_to_eax) - TYPE(GNAME(alloc_to_eax)) - .align align_4byte,0x90 -GNAME(alloc_to_eax): - pushl %ecx # Save ecx and edx as C could destroy them. - pushl %edx - pushl %eax # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - popl %edx # Restore ecx and edx. - popl %ecx - ret - SIZE(GNAME(alloc_to_eax)) - - .globl GNAME(alloc_8_to_eax) - TYPE(GNAME(alloc_8_to_eax)) - .align align_4byte,0x90 -GNAME(alloc_8_to_eax): - pushl %ecx # Save ecx and edx as C could destroy them. - pushl %edx - pushl $8 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - popl %edx # Restore ecx and edx. - popl %ecx - ret - SIZE(GNAME(alloc_8_to_eax)) - - .globl GNAME(alloc_8_to_eax) - TYPE(GNAME(alloc_8_to_eax)) - .align align_4byte,0x90 - - .globl GNAME(alloc_16_to_eax) - TYPE(GNAME(alloc_16_to_eax)) - .align align_4byte,0x90 -GNAME(alloc_16_to_eax): - pushl %ecx # Save ecx and edx as C could destroy them. - pushl %edx - pushl $16 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - popl %edx # Restore ecx and edx. - popl %ecx - ret - SIZE(GNAME(alloc_16_to_eax)) - - .globl GNAME(alloc_to_ecx) - TYPE(GNAME(alloc_to_ecx)) - .align align_4byte,0x90 -GNAME(alloc_to_ecx): - pushl %eax # Save eax and edx as C could destroy them. - pushl %edx - pushl %ecx # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%ecx # Set up the destination. - popl %edx # Restore eax and edx. - popl %eax - ret - SIZE(GNAME(alloc_to_ecx)) - - .globl GNAME(alloc_8_to_ecx) - TYPE(GNAME(alloc_8_to_ecx)) - .align align_4byte,0x90 -GNAME(alloc_8_to_ecx): - pushl %eax # Save eax and edx as C could destroy them. - pushl %edx - pushl $8 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%ecx # Set up the destination. - popl %edx # Restore eax and edx. - popl %eax - ret - SIZE(GNAME(alloc_8_to_ecx)) - - .globl GNAME(alloc_16_to_ecx) - TYPE(GNAME(alloc_16_to_ecx)) - .align align_4byte,0x90 -GNAME(alloc_16_to_ecx): - pushl %eax # Save eax and edx as C could destroy them. - pushl %edx - pushl $16 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%ecx # Set up the destination. - popl %edx # Restore eax and edx. - popl %eax - ret - SIZE(GNAME(alloc_16_to_ecx)) - - - .globl GNAME(alloc_to_edx) - TYPE(GNAME(alloc_to_edx)) - .align align_4byte,0x90 -GNAME(alloc_to_edx): - pushl %eax # Save eax and ecx as C could destroy them. - pushl %ecx - pushl %edx # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%edx # Set up the destination. - popl %ecx # Restore eax and ecx. - popl %eax - ret - SIZE(GNAME(alloc_to_edx)) - - .globl GNAME(alloc_8_to_edx) - TYPE(GNAME(alloc_8_to_edx)) - .align align_4byte,0x90 -GNAME(alloc_8_to_edx): - pushl %eax # Save eax and ecx as C could destroy them. - pushl %ecx - pushl $8 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%edx # Set up the destination. - popl %ecx # Restore eax and ecx. - popl %eax - ret - SIZE(GNAME(alloc_8_to_edx)) - - .globl GNAME(alloc_16_to_edx) - TYPE(GNAME(alloc_16_to_edx)) - .align align_4byte,0x90 -GNAME(alloc_16_to_edx): - pushl %eax # Save eax and ecx as C could destroy them. - pushl %ecx - pushl $16 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%edx # Set up the destination. - popl %ecx # Restore eax and ecx. - popl %eax - ret - SIZE(GNAME(alloc_16_to_edx)) - - - - .globl GNAME(alloc_to_ebx) - TYPE(GNAME(alloc_to_ebx)) - .align align_4byte,0x90 -GNAME(alloc_to_ebx): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl %ebx # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%ebx # Set up the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_to_ebx)) - - .globl GNAME(alloc_8_to_ebx) - TYPE(GNAME(alloc_8_to_ebx)) - .align align_4byte,0x90 -GNAME(alloc_8_to_ebx): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl $8 # Push the size. - call GNAME(alloc) - addl $4,%esp # Pop the size arg. - movl %eax,%ebx # Set up the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_8_to_ebx)) - - .globl GNAME(alloc_16_to_ebx) - TYPE(GNAME(alloc_16_to_ebx)) - .align align_4byte,0x90 -GNAME(alloc_16_to_ebx): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl $16 # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%ebx # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_16_to_ebx)) - - - - .globl GNAME(alloc_to_esi) - TYPE(GNAME(alloc_to_esi)) - .align align_4byte,0x90 -GNAME(alloc_to_esi): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl %esi # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%esi # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_to_esi)) - - .globl GNAME(alloc_8_to_esi) - TYPE(GNAME(alloc_8_to_esi)) - .align align_4byte,0x90 -GNAME(alloc_8_to_esi): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl $8 # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%esi # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_8_to_esi)) - - .globl GNAME(alloc_16_to_esi) - TYPE(GNAME(alloc_16_to_esi)) - .align align_4byte,0x90 -GNAME(alloc_16_to_esi): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl $16 # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%esi # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_16_to_esi)) - - - .globl GNAME(alloc_to_edi) - TYPE(GNAME(alloc_to_edi)) - .align align_4byte,0x90 -GNAME(alloc_to_edi): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl %edi # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%edi # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_to_edi)) - - .globl GNAME(alloc_8_to_edi) - TYPE(GNAME(alloc_8_to_edi)) - .align align_4byte,0x90 -GNAME(alloc_8_to_edi): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl $8 # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%edi # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_8_to_edi)) - - .globl GNAME(alloc_16_to_edi) - TYPE(GNAME(alloc_16_to_edi)) - .align align_4byte,0x90 -GNAME(alloc_16_to_edi): - pushl %eax # Save eax, ecx, and edx as C could destroy them. - pushl %ecx - pushl %edx - pushl $16 # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. - movl %eax,%edi # setup the destination. - popl %edx # Restore eax, ecx and edx. - popl %ecx - popl %eax - ret - SIZE(GNAME(alloc_16_to_edi)) - +#ifdef LISP_FEATURE_DARWIN +#define ALLOC(size) \ + pushl %ebp; /* Save EBP */ \ + movl %esp,%ebp; /* Save ESP to EBP */ \ + pushl $0; /* Reserve space for arg */ \ + andl $0xfffffff0,%esp; /* Align stack to 16bytes */ \ + movl size, (%esp); /* Argument to alloc */ \ + call GNAME(alloc); \ + movl %ebp,%esp; /* Restore ESP from EBP */ \ + popl %ebp; /* Restore EBP */ +#else +#define ALLOC(size) \ + pushl size; /* Argument to alloc */ \ + call GNAME(alloc); \ + addl $4,%esp; /* Pop argument */ +#endif + +#define DEFINE_ALLOC_TO_EAX(name,size) \ + .globl GNAME(name); \ + TYPE(GNAME(name)); \ + .align align_16byte,0x90; \ +GNAME(name): \ + pushl %ecx; /* Save ECX and EDX */ \ + pushl %edx; \ + ALLOC(size) \ + popl %edx; /* Restore ECX and EDX */ \ + popl %ecx; \ + ret; \ + SIZE(GNAME(name)) + +#define DEFINE_ALLOC_TO_ECX(name,size) \ + .globl GNAME(name); \ + TYPE(GNAME(name)); \ + .align align_16byte,0x90; \ +GNAME(name): \ + pushl %eax; /* Save EAX and EDX */ \ + pushl %edx; \ + ALLOC(size) \ + movl %eax,%ecx; /* Result to destination */ \ + popl %edx; \ + popl %eax; \ + ret; \ + SIZE(GNAME(name)) + +#define DEFINE_ALLOC_TO_EDX(name,size) \ + .globl GNAME(name); \ + TYPE(GNAME(name)); \ + .align align_16byte,0x90; \ +GNAME(name): \ + pushl %eax; /* Save EAX and ECX */ \ + pushl %ecx; \ + ALLOC(size) \ + movl %eax,%edx; /* Restore EAX and ECX */ \ + popl %ecx; \ + popl %eax; \ + ret; \ + SIZE(GNAME(name)) + +#define DEFINE_ALLOC_TO_REG(name,reg,size) \ + .globl GNAME(name); \ + TYPE(GNAME(name)); \ + .align align_16byte,0x90; \ +GNAME(name): \ + pushl %eax; /* Save EAX, ECX, and EDX */ \ + pushl %ecx; \ + pushl %edx; \ + ALLOC(size) \ + movl %eax,reg; /* Restore them */ \ + popl %edx; \ + popl %ecx; \ + popl %eax; \ + ret; \ + SIZE(GNAME(name)) + +DEFINE_ALLOC_TO_EAX(alloc_to_eax,%eax) +DEFINE_ALLOC_TO_EAX(alloc_8_to_eax,$8) +DEFINE_ALLOC_TO_EAX(alloc_16_to_eax,$16) + +DEFINE_ALLOC_TO_ECX(alloc_to_ecx,%ecx) +DEFINE_ALLOC_TO_ECX(alloc_8_to_ecx,$8) +DEFINE_ALLOC_TO_ECX(alloc_16_to_ecx,$16) + +DEFINE_ALLOC_TO_EDX(alloc_to_edx,%edx) +DEFINE_ALLOC_TO_EDX(alloc_8_to_edx,$8) +DEFINE_ALLOC_TO_EDX(alloc_16_to_edx,$16) + +DEFINE_ALLOC_TO_REG(alloc_to_ebx,%ebx,%ebx) +DEFINE_ALLOC_TO_REG(alloc_8_to_ebx,%ebx,$8) +DEFINE_ALLOC_TO_REG(alloc_16_to_ebx,%ebx,$16) + +DEFINE_ALLOC_TO_REG(alloc_to_esi,%esi,%esi) +DEFINE_ALLOC_TO_REG(alloc_8_to_esi,%esi,$8) +DEFINE_ALLOC_TO_REG(alloc_16_to_esi,%esi,$16) + +DEFINE_ALLOC_TO_REG(alloc_to_edi,%edi,%edi) +DEFINE_ALLOC_TO_REG(alloc_8_to_edi,%edi,$8) +DEFINE_ALLOC_TO_REG(alloc_16_to_edi,%edi,$16) + /* Called from lisp when an inline allocation overflows. - Every register except the result needs to be preserved. - We depend on C to preserve ebx, esi, edi, and ebp. - But where necessary must save eax, ecx, edx. */ + * Every register except the result needs to be preserved. + * We depend on C to preserve ebx, esi, edi, and ebp. + * But where necessary must save eax, ecx, edx. */ #ifdef LISP_FEATURE_SB_THREAD #define START_REGION %fs:THREAD_ALLOC_REGION_OFFSET #else #define START_REGION GNAME(boxed_region) #endif - + +#define ALLOC_OVERFLOW(size) \ + /* Calculate the size for the allocation. */ \ + subl START_REGION,size; \ + ALLOC(size) + /* This routine handles an overflow with eax=crfp+size. So the size=eax-crfp. */ - .align align_4byte + .align align_16byte .globl GNAME(alloc_overflow_eax) TYPE(GNAME(alloc_overflow_eax)) GNAME(alloc_overflow_eax): pushl %ecx # Save ecx pushl %edx # Save edx - /* Calculate the size for the allocation. */ - subl START_REGION,%eax - pushl %eax # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. + ALLOC_OVERFLOW(%eax) popl %edx # Restore edx. popl %ecx # Restore ecx. ret SIZE(GNAME(alloc_overflow_eax)) - .align align_4byte + .align align_16byte .globl GNAME(alloc_overflow_ecx) TYPE(GNAME(alloc_overflow_ecx)) GNAME(alloc_overflow_ecx): pushl %eax # Save eax pushl %edx # Save edx - /* Calculate the size for the allocation. */ - subl START_REGION,%ecx - pushl %ecx # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. + ALLOC_OVERFLOW(%ecx) movl %eax,%ecx # setup the destination. popl %edx # Restore edx. popl %eax # Restore eax. ret SIZE(GNAME(alloc_overflow_ecx)) - .align align_4byte + .align align_16byte .globl GNAME(alloc_overflow_edx) TYPE(GNAME(alloc_overflow_edx)) GNAME(alloc_overflow_edx): pushl %eax # Save eax pushl %ecx # Save ecx - /* Calculate the size for the allocation. */ - subl START_REGION,%edx - pushl %edx # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. + ALLOC_OVERFLOW(%edx) movl %eax,%edx # setup the destination. popl %ecx # Restore ecx. popl %eax # Restore eax. @@ -752,18 +587,14 @@ GNAME(alloc_overflow_edx): /* This routine handles an overflow with ebx=crfp+size. So the size=ebx-crfp. */ - .align align_4byte + .align align_16byte .globl GNAME(alloc_overflow_ebx) TYPE(GNAME(alloc_overflow_ebx)) GNAME(alloc_overflow_ebx): pushl %eax # Save eax pushl %ecx # Save ecx pushl %edx # Save edx - /* Calculate the size for the allocation. */ - subl START_REGION,%ebx - pushl %ebx # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. + ALLOC_OVERFLOW(%ebx) movl %eax,%ebx # setup the destination. popl %edx # Restore edx. popl %ecx # Restore ecx. @@ -773,18 +604,14 @@ GNAME(alloc_overflow_ebx): /* This routine handles an overflow with esi=crfp+size. So the size=esi-crfp. */ - .align align_4byte + .align align_16byte .globl GNAME(alloc_overflow_esi) TYPE(GNAME(alloc_overflow_esi)) GNAME(alloc_overflow_esi): pushl %eax # Save eax pushl %ecx # Save ecx pushl %edx # Save edx - /* Calculate the size for the allocation. */ - subl START_REGION,%esi - pushl %esi # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. + ALLOC_OVERFLOW(%esi) movl %eax,%esi # setup the destination. popl %edx # Restore edx. popl %ecx # Restore ecx. @@ -792,18 +619,14 @@ GNAME(alloc_overflow_esi): ret SIZE(GNAME(alloc_overflow_esi)) - .align align_4byte + .align align_16byte .globl GNAME(alloc_overflow_edi) TYPE(GNAME(alloc_overflow_edi)) GNAME(alloc_overflow_edi): pushl %eax # Save eax pushl %ecx # Save ecx pushl %edx # Save edx - /* Calculate the size for the allocation. */ - subl START_REGION,%edi - pushl %edi # Push the size - call GNAME(alloc) - addl $4,%esp # pop the size arg. + ALLOC_OVERFLOW(%edi) movl %eax,%edi # setup the destination. popl %edx # Restore edx. popl %ecx # Restore ecx. @@ -811,7 +634,95 @@ GNAME(alloc_overflow_edi): ret SIZE(GNAME(alloc_overflow_edi)) - .align align_4byte,0x90 + +#ifdef LISP_FEATURE_WIN32 + /* The guts of the exception-handling system doesn't use + * frame pointers, which manages to throw off backtraces + * rather badly. So here we grab the (known-good) EBP + * and EIP from the exception context and use it to fake + * up a stack frame which will skip over the system SEH + * code. */ + .align align_16byte + .globl GNAME(exception_handler_wrapper) + TYPE(GNAME(exception_handler_wrapper)) +GNAME(exception_handler_wrapper): + /* Context layout is: */ + /* 7 dwords before FSA. (0x1c) */ + /* 8 dwords and 0x50 bytes in the FSA. (0x70/0x8c) */ + /* 4 dwords segregs. (0x10/0x9c) */ + /* 6 dwords non-stack GPRs. (0x18/0xb4) */ + /* EBP (at 0xb4) */ + /* EIP (at 0xb8) */ +#define CONTEXT_EBP_OFFSET 0xb4 +#define CONTEXT_EIP_OFFSET 0xb8 + /* some other stuff we don't care about. */ + pushl %ebp + movl 0x10(%esp), %ebp /* context */ + pushl CONTEXT_EIP_OFFSET(%ebp) + pushl CONTEXT_EBP_OFFSET(%ebp) + movl %esp, %ebp + pushl 0x1c(%esp) + pushl 0x1c(%esp) + pushl 0x1c(%esp) + pushl 0x1c(%esp) + call GNAME(handle_exception) + lea 8(%ebp), %esp + popl %ebp + ret + SIZE(GNAME(exception_handler_wrapper)) +#endif + +#ifdef LISP_FEATURE_DARWIN + .align align_16byte + .globl GNAME(call_into_lisp_tramp) + TYPE(GNAME(call_into_lisp_tramp)) +GNAME(call_into_lisp_tramp): + /* 1. build the stack frame from the block that's pointed to by ECX + 2. free the block + 3. set ECX to 0 + 4. call the function via call_into_lisp + */ + pushl 0(%ecx) /* return address */ + + pushl %ebp + movl %esp, %ebp + + pushl 32(%ecx) /* eflags */ + pushl 28(%ecx) /* EAX */ + pushl 20(%ecx) /* ECX */ + pushl 16(%ecx) /* EDX */ + pushl 24(%ecx) /* EBX */ + pushl $0 /* popal is going to ignore esp */ + pushl %ebp /* is this right?? */ + pushl 12(%ecx) /* ESI */ + pushl 8(%ecx) /* EDI */ + pushl $0 /* args for call_into_lisp */ + pushl $0 + pushl 4(%ecx) /* function to call */ + + /* free our save block */ + pushl %ecx /* reserve sufficient space on stack for args */ + pushl %ecx + andl $0xfffffff0, %esp /* align stack */ + movl $0x40, 4(%esp) + movl %ecx, (%esp) + call GNAME(os_invalidate) + + /* call call_into_lisp */ + leal -48(%ebp), %esp + call GNAME(call_into_lisp) + + /* Clean up our mess */ + leal -36(%ebp), %esp + popal + popfl + leave + ret + + SIZE(call_into_lisp_tramp) +#endif + + .align align_16byte,0x90 .globl GNAME(post_signal_tramp) TYPE(GNAME(post_signal_tramp)) GNAME(post_signal_tramp): @@ -821,70 +732,41 @@ GNAME(post_signal_tramp): addl $12,%esp /* clear call_into_lisp args from stack */ popal /* restore registers */ popfl +#ifdef LISP_FEATURE_DARWIN + /* skip two padding words */ + addl $8,%esp +#endif leave ret SIZE(GNAME(post_signal_tramp)) -#ifdef LISP_FEATURE_WIN32 - /* - * This is part of the funky magic for exception handling on win32. - * see sigtrap_emulator() in win32-os.c for details. - */ - .global GNAME(sigtrap_trampoline) -GNAME(sigtrap_trampoline): - pushl %eax - pushl %ebp - movl %esp, %ebp - call GNAME(sigtrap_wrapper) - pop %eax - pop %eax - int3 - .byte trap_ContextRestore - hlt # We should never return here. - - /* - * This is part of the funky magic for exception handling on win32. - * see handle_exception() in win32-os.c for details. - */ - .global GNAME(exception_trampoline) -GNAME(exception_trampoline): - pushl %eax - pushl %ebp - movl %esp, %ebp - call GNAME(handle_win32_exception_wrapper) - pop %eax - pop %eax - int3 - .byte trap_ContextRestore - hlt # We should never return here. -#endif /* fast_bzero implementations and code to detect which implementation * to use. */ - .global GNAME(fast_bzero_pointer) + .globl GNAME(fast_bzero_pointer) .data - .align 4 + .align align_16byte GNAME(fast_bzero_pointer): /* Variable containing a pointer to the bzero function to use. - * Initially points to a function that detects which implementation - * should be used, and then updates the variable. */ - .long fast_bzero_detect + * Initially points to a basic function. Change this variable + * to fast_bzero_detect if OS supports SSE. */ + .long GNAME(fast_bzero_base) .text - .align align_8byte,0x90 - .global GNAME(fast_bzero) + .align align_16byte,0x90 + .globl GNAME(fast_bzero) TYPE(GNAME(fast_bzero)) GNAME(fast_bzero): /* Indirect function call */ - jmp *fast_bzero_pointer + jmp *GNAME(fast_bzero_pointer) SIZE(GNAME(fast_bzero)) .text - .align align_8byte,0x90 - .global GNAME(fast_bzero_detect) + .align align_16byte,0x90 + .globl GNAME(fast_bzero_detect) TYPE(GNAME(fast_bzero_detect)) GNAME(fast_bzero_detect): /* Decide whether to use SSE, MMX or REP version */ @@ -904,10 +786,10 @@ GNAME(fast_bzero_detect): * for all non-SSE2 processors. */ Lbase: - movl $fast_bzero_base, fast_bzero_pointer + movl $(GNAME(fast_bzero_base)), GNAME(fast_bzero_pointer) jmp Lrestore Lsse2: - movl $fast_bzero_sse, fast_bzero_pointer + movl $(GNAME(fast_bzero_sse)), GNAME(fast_bzero_pointer) jmp Lrestore Lrestore: @@ -915,14 +797,14 @@ Lrestore: pop %ecx pop %ebx pop %eax - jmp *fast_bzero_pointer + jmp *GNAME(fast_bzero_pointer) SIZE(GNAME(fast_bzero_detect)) .text - .align align_8byte,0x90 - .global GNAME(fast_bzero_sse) + .align align_16byte,0x90 + .globl GNAME(fast_bzero_sse) TYPE(GNAME(fast_bzero_sse)) GNAME(fast_bzero_sse): @@ -938,7 +820,7 @@ GNAME(fast_bzero_sse): movups %xmm7, -16(%esp) /* Save XMM register */ xorps %xmm7, %xmm7 /* Zero the XMM register */ jmp Lloop_sse - .align 16 + .align align_16byte Lloop_sse: /* Copy the 16 zeroes from xmm7 to memory, 4 times. MOVNTDQ is the @@ -967,8 +849,8 @@ Lend_sse: .text - .align align_8byte,0x90 - .global GNAME(fast_bzero_base) + .align align_16byte,0x90 + .globl GNAME(fast_bzero_base) TYPE(GNAME(fast_bzero_base)) GNAME(fast_bzero_base): @@ -983,9 +865,11 @@ GNAME(fast_bzero_base): xor %eax, %eax /* Zero EAX */ shr $2, %ecx /* Amount of 4-byte blocks to copy */ jz Lend_base - cld /* Set direction of STOSL to increment */ - rep stosl /* Store EAX to *EDI, ECX times, incrementing + + rep + stosl /* Store EAX to *EDI, ECX times, incrementing * EDI by 4 after each store */ + Lend_base: pop %edi /* Restore temp registers */ pop %ecx @@ -994,4 +878,4 @@ Lend_base: SIZE(GNAME(fast_bzero_base)) - .end + END()