X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fx86-assem.S;h=9470533fbb24860fae70a5b79dc6df2ec40ad0c5;hb=57d7dd0f59b9df89feb1175b0efc449bb0b8d400;hp=c4d2f5e19ebff30947b2ad3c5c31619717a3b1cf;hpb=3be1ab042ab74e008e40626cc6bd5190b27da033;p=sbcl.git diff --git a/src/runtime/x86-assem.S b/src/runtime/x86-assem.S index c4d2f5e..9470533 100644 --- a/src/runtime/x86-assem.S +++ b/src/runtime/x86-assem.S @@ -100,6 +100,9 @@ * 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 @@ -119,16 +122,11 @@ GNAME(call_into_c): fstp %st(0) fstp %st(0) -#ifdef LISP_FEATURE_WIN32 - cld -#endif - -#ifdef LISP_FEATURE_DARWIN - andl $0xfffffff0,%esp # align stack to 16-byte boundary before calling C -#endif - call *%eax # normal callout using Lisp stack + cld # clear out DF: Darwin, Solaris and Win32 at + # least need this, and it should not hurt others - 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 @@ -168,7 +166,7 @@ Lfp_rtn_value: /* We don't need to restore eax, because the result is in st(0). */ -/* Return. */ +/* Return. FIXME: It would be nice to restructure this to use RET. */ jmp *%ebx SIZE(GNAME(call_into_c)) @@ -424,9 +422,7 @@ GNAME(do_pending_interrupt): 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. @@ -434,315 +430,128 @@ 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)) - +#ifdef LISP_FEATURE_DARWIN +#define ALLOC(size) \ + pushl %ebp; /* Save EBP */ \ + movl %esp,%ebp; /* Save ESP to EBP */ \ + andl $0xfffffff0,%esp; /* Align stack */ \ + pushl $0; /* Padding */ \ + pushl size; /* Argument to alloc */ \ + cld; /* Clear DF */ \ + call GNAME(alloc); \ + movl %ebp,%esp; /* Restore ESP from EBP */ \ + popl %ebp; /* Restore EBP */ +#else +#define ALLOC(size) \ + pushl size; /* Argument to alloc */ \ + cld; /* Clear DF */ \ + call GNAME(alloc); \ + addl $4,%esp; /* Pop argument */ +#endif - .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)) +#define DEFINE_ALLOC_TO_EAX(name,size) \ + .globl GNAME(name); \ + TYPE(GNAME(name)); \ + .align align_4byte,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_4byte,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_4byte,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_4byte,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 @@ -751,11 +560,7 @@ GNAME(alloc_16_to_edi): 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 @@ -767,11 +572,7 @@ GNAME(alloc_overflow_eax): 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. @@ -784,11 +585,7 @@ GNAME(alloc_overflow_ecx): 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. @@ -804,11 +601,7 @@ 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. @@ -825,11 +618,7 @@ 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. @@ -844,11 +633,7 @@ 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.