ad9e089d413afa519339c9c01e3ce903c372ea7d
[sbcl.git] / src / runtime / x86-assem.S
1 /*
2  * very-low-level utilities for runtime support
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15 \f
16 #define LANGUAGE_ASSEMBLY
17 #include "sbcl.h"
18 #include "validate.h"
19 #include "genesis/closure.h"
20 #include "genesis/fdefn.h"
21 #include "genesis/static-symbols.h"
22 #include "genesis/symbol.h"
23 #include "genesis/thread.h"
24         
25 /* Minimize conditionalization for different OS naming schemes. 
26  *
27  * (As of sbcl-0.8.10, this seems no longer to be much of an issue, 
28  * since everyone has converged on ELF. If this generality really 
29  * turns out not to matter, perhaps it's just clutter we could get
30  * rid of? -- WHN 2004-04-18)
31  */
32 #if defined __linux__  || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __sun
33 #define GNAME(var) var
34 #else
35 #define GNAME(var) _##var
36 #endif
37
38 /* Get the right type of alignment. Linux, FreeBSD and NetBSD (but not OpenBSD)
39  * want alignment in bytes. 
40  *
41  * (As in the GNAME() definitions above, as of sbcl-0.8.10, this seems 
42  * no longer to be much of an issue, since everyone has converged on
43  * the same value. If this generality really turns out not to 
44  * matter any more, perhaps it's just clutter we could get
45  * rid of? -- WHN 2004-04-18)
46  */
47 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun)
48 #define align_4byte     4
49 #define align_8byte     8
50 #define align_16byte    16
51 #else
52 #define align_4byte     2
53 #define align_8byte     3
54 #define align_16byte    4       
55 #endif                  
56
57         .text
58         .global GNAME(foreign_function_call_active)
59         .global GNAME(all_threads)
60 \f
61 /*
62  * A call to call_into_c preserves esi, edi, and ebp.   
63  * (The C function will preserve ebx, esi, edi, and ebp across its
64  * function call, but we trash ebx ourselves by using it to save the
65  * return Lisp address.)
66  *
67  * Return values are in eax and maybe edx for quads, or st(0) for
68  * floats.
69  *
70  * This should work for Lisp calls C calls Lisp calls C..
71  */
72         .text
73         .align  align_16byte,0x90
74         .global GNAME(call_into_c)
75         .type   GNAME(call_into_c),@function
76 GNAME(call_into_c):
77         movl    $1,GNAME(foreign_function_call_active)
78
79 /* Save the return Lisp address in ebx. */
80         popl    %ebx
81
82 /* Setup the NPX for C */
83         fstp    %st(0)
84         fstp    %st(0)
85         fstp    %st(0)
86         fstp    %st(0)
87         fstp    %st(0)
88         fstp    %st(0)
89         fstp    %st(0)
90         fstp    %st(0)
91
92         call    *%eax           # normal callout using Lisp stack
93
94         movl    %eax,%ecx       # remember integer return value
95
96 /* Check for a return FP value. */
97         fxam
98         fnstsw  %eax
99         andl    $0x4500,%eax
100         cmpl    $0x4100,%eax
101         jne     Lfp_rtn_value
102
103 /* The return value is in eax, or eax,edx? */
104 /* Set up the NPX stack for Lisp. */
105         fldz                    # Ensure no regs are empty.
106         fldz
107         fldz
108         fldz
109         fldz
110         fldz
111         fldz
112         fldz
113
114 /* Restore the return value. */
115         movl    %ecx,%eax       # maybe return value
116
117         movl    $0,GNAME(foreign_function_call_active)
118 /* Return. */
119         jmp     *%ebx
120
121 Lfp_rtn_value:
122 /* The return result is in st(0). */
123 /* Set up the NPX stack for Lisp, placing the result in st(0). */
124         fldz                    # Ensure no regs are empty.
125         fldz
126         fldz
127         fldz
128         fldz
129         fldz
130         fldz
131         fxch    %st(7)          # Move the result back to st(0).
132
133 /* We don't need to restore eax, because the result is in st(0). */
134
135         movl    $0,GNAME(foreign_function_call_active)
136 /* Return. */   
137         jmp     *%ebx
138
139         .size   GNAME(call_into_c), . - GNAME(call_into_c)
140
141 \f
142         .text   
143         .global GNAME(call_into_lisp_first_time)
144         .type  GNAME(call_into_lisp_first_time),@function
145                 
146 /* The *ALIEN-STACK* pointer is set up on the first call_into_lisp when
147  * the stack changes.  We don't worry too much about saving registers 
148  * here, because we never expect to return from the initial call to lisp 
149  * anyway */
150         
151         .align  align_16byte,0x90
152 GNAME(call_into_lisp_first_time):
153         pushl   %ebp            # Save old frame pointer.
154         movl    %esp,%ebp       # Establish new frame.
155         movl    %esp,ALIEN_STACK + SYMBOL_VALUE_OFFSET
156         movl    GNAME(all_threads),%eax
157         movl    THREAD_CONTROL_STACK_START_OFFSET(%eax) ,%esp
158         /* don't think too hard about what happens if we get interrupted
159         * here */
160         addl    $THREAD_CONTROL_STACK_SIZE-4,%esp
161         jmp     Lstack
162 \f
163         .text   
164         .global GNAME(call_into_lisp)
165         .type  GNAME(call_into_lisp),@function
166                 
167 /* The C conventions require that ebx, esi, edi, and ebp be preserved
168  * across function calls. */
169         
170         .align  align_16byte,0x90
171 GNAME(call_into_lisp):
172         pushl   %ebp            # Save old frame pointer.
173         movl    %esp,%ebp       # Establish new frame.
174 Lstack:
175 /* Save the NPX state */
176         fwait                   # Catch any pending NPX exceptions.
177         subl    $108,%esp       # Make room for the NPX state.
178         fnsave  (%esp)          # save and reset NPX
179
180         movl    (%esp),%eax     # Load NPX control word.
181         andl    $0xfffff2ff,%eax        # Set rounding mode to nearest.
182         orl     $0x00000200,%eax        # Set precision to 64 bits.  (53-bit mantissa)
183         pushl   %eax
184         fldcw   (%esp)          # Recover modes.
185         popl    %eax
186
187         fldz                    # Ensure no FP regs are empty.
188         fldz
189         fldz
190         fldz
191         fldz
192         fldz
193         fldz
194         fldz
195         
196 /* Save C regs: ebx esi edi. */
197         pushl   %ebx
198         pushl   %esi
199         pushl   %edi
200         
201 /* Clear descriptor regs. */
202         xorl    %eax,%eax       # lexenv
203         xorl    %ebx,%ebx       # available
204         xorl    %ecx,%ecx       # arg count
205         xorl    %edx,%edx       # first arg
206         xorl    %edi,%edi       # second arg
207         xorl    %esi,%esi       # third arg
208
209 /* no longer in function call */
210         movl    %eax, GNAME(foreign_function_call_active)
211
212         movl    %esp,%ebx       # remember current stack
213         pushl   %ebx            # Save entry stack on (maybe) new stack.
214
215         /* Establish Lisp args. */
216         movl     8(%ebp),%eax   # lexenv?
217         movl    12(%ebp),%ebx   # address of arg vec
218         movl    16(%ebp),%ecx   # num args
219         shll    $2,%ecx         # Make num args into fixnum.
220         cmpl    $0,%ecx
221         je      Ldone
222         movl    (%ebx),%edx     # arg0
223         cmpl    $4,%ecx
224         je      Ldone
225         movl    4(%ebx),%edi    # arg1
226         cmpl    $8,%ecx
227         je      Ldone
228         movl    8(%ebx),%esi    # arg2
229 Ldone:  
230         /* Registers eax, ecx, edx, edi, and esi are now live. */
231
232         /* Alloc new frame. */
233         mov     %esp,%ebx       # The current sp marks start of new frame.
234         push    %ebp            # fp in save location S0
235         sub     $8,%esp         # Ensure 3 slots are allocated, one above.
236         mov     %ebx,%ebp       # Switch to new frame.
237
238         call    *CLOSURE_FUN_OFFSET(%eax)
239         
240         /* If the function returned multiple values, it will return to
241            this point.  Lose them */
242         mov     %ebx, %esp
243         /* A singled value function returns here */
244
245 /* Restore the stack, in case there was a stack change. */
246         popl    %esp            # c-sp
247
248 /* Restore C regs: ebx esi edi. */
249         popl    %edi
250         popl    %esi
251         popl    %ebx
252
253 /* Restore the NPX state. */
254         frstor  (%esp)
255         addl    $108, %esp
256         
257         popl    %ebp            # c-sp
258         movl    %edx,%eax       # c-val
259         ret
260         .size   GNAME(call_into_lisp), . - GNAME(call_into_lisp)
261 \f
262 /* support for saving and restoring the NPX state from C */
263         .text
264         .global GNAME(fpu_save)
265         .type   GNAME(fpu_save),@function
266         .align  2,0x90
267 GNAME(fpu_save):
268         movl    4(%esp),%eax
269         fnsave  (%eax)          # Save the NPX state. (resets NPX)
270         ret
271         .size   GNAME(fpu_save),.-GNAME(fpu_save)
272
273         .global GNAME(fpu_restore)
274         .type   GNAME(fpu_restore),@function
275         .align  2,0x90
276 GNAME(fpu_restore):
277         movl    4(%esp),%eax
278         frstor  (%eax)          # Restore the NPX state.
279         ret
280         .size   GNAME(fpu_restore),.-GNAME(fpu_restore)
281 \f
282 /*
283  * the undefined-function trampoline
284  */
285         .text
286         .align  align_4byte,0x90
287         .global GNAME(undefined_tramp)
288         .type   GNAME(undefined_tramp),@function
289         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
290 GNAME(undefined_tramp):
291         int3
292         .byte   trap_Error
293         .byte   2
294         .byte   UNDEFINED_FUN_ERROR
295         .byte   sc_DescriptorReg # eax in the Descriptor-reg SC
296         ret
297         .size   GNAME(undefined_tramp), .-GNAME(undefined_tramp)
298
299 /*
300  * the closure trampoline
301  */
302         .text
303         .align  align_4byte,0x90
304         .global GNAME(closure_tramp)
305         .type   GNAME(closure_tramp),@function
306         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
307 GNAME(closure_tramp):
308         movl    FDEFN_FUN_OFFSET(%eax),%eax
309         /* FIXME: The '*' after "jmp" in the next line is from PVE's
310          * patch posted to the CMU CL mailing list Oct 6, 1999. It looks
311          * reasonable, and it certainly seems as though if CMU CL needs it,
312          * SBCL needs it too, but I haven't actually verified that it's
313          * right. It would be good to find a way to force the flow of
314          * control through here to test it. */
315         jmp     *CLOSURE_FUN_OFFSET(%eax)
316         .size   GNAME(closure_tramp), .-GNAME(closure_tramp)
317
318 /*
319  * fun-end breakpoint magic
320  */
321         .text
322         .global GNAME(fun_end_breakpoint_guts)
323         .align  align_4byte
324 GNAME(fun_end_breakpoint_guts):
325         /* Multiple Value return */
326         jmp     multiple_value_return
327         /* Single value return: The eventual return will now use the
328            multiple values return convention but with a return values
329            count of one. */
330         movl    %esp,%ebx       # Setup ebx - the ofp.
331         subl    $4,%esp         # Allocate one stack slot for the return value
332         movl    $4,%ecx         # Setup ecx for one return value.
333         movl    $NIL,%edi       # default second value
334         movl    $NIL,%esi       # default third value
335                 
336 multiple_value_return:
337         
338         .global GNAME(fun_end_breakpoint_trap)
339 GNAME(fun_end_breakpoint_trap):
340         int3
341         .byte   trap_FunEndBreakpoint
342         hlt                     # We should never return here.
343
344         .global GNAME(fun_end_breakpoint_end)
345 GNAME(fun_end_breakpoint_end):
346
347 \f
348         .global GNAME(do_pending_interrupt)
349         .type   GNAME(do_pending_interrupt),@function
350         .align  align_4byte,0x90
351 GNAME(do_pending_interrupt):
352         int3
353         .byte   trap_PendingInterrupt
354         ret
355         .size   GNAME(do_pending_interrupt),.-GNAME(do_pending_interrupt)
356 \f
357
358 /*
359  * Allocate bytes and return the start of the allocated space
360  * in the specified destination register.
361  *
362  * In the general case the size will be in the destination register.
363  *
364  * All registers must be preserved except the destination.
365  * The C conventions will preserve ebx, esi, edi, and ebp.
366  * So only eax, ecx, and edx need special care here.
367  */
368         
369         .globl  GNAME(alloc_to_eax)
370         .type   GNAME(alloc_to_eax),@function
371         .align  align_4byte,0x90
372 GNAME(alloc_to_eax):
373         pushl   %ecx    # Save ecx and edx as C could destroy them.
374         pushl   %edx
375         pushl   %eax    # Push the size.
376         call    GNAME(alloc)
377         addl    $4,%esp # Pop the size arg.
378         popl    %edx    # Restore ecx and edx.
379         popl    %ecx
380         ret
381         .size   GNAME(alloc_to_eax),.-GNAME(alloc_to_eax)
382
383         .globl  GNAME(alloc_8_to_eax)
384         .type   GNAME(alloc_8_to_eax),@function
385         .align  align_4byte,0x90
386 GNAME(alloc_8_to_eax):
387         pushl   %ecx    # Save ecx and edx as C could destroy them.
388         pushl   %edx
389         pushl   $8      # Push the size.
390         call    GNAME(alloc)
391         addl    $4,%esp # Pop the size arg.
392         popl    %edx    # Restore ecx and edx.
393         popl    %ecx
394         ret
395         .size   GNAME(alloc_8_to_eax),.-GNAME(alloc_8_to_eax)
396
397         .globl  GNAME(alloc_8_to_eax)
398         .type   GNAME(alloc_8_to_eax),@function
399         .align  align_4byte,0x90
400
401         .globl  GNAME(alloc_16_to_eax)
402         .type   GNAME(alloc_16_to_eax),@function
403         .align  align_4byte,0x90
404 GNAME(alloc_16_to_eax):
405         pushl   %ecx    # Save ecx and edx as C could destroy them.
406         pushl   %edx
407         pushl   $16     # Push the size.
408         call    GNAME(alloc)
409         addl    $4,%esp # Pop the size arg.
410         popl    %edx    # Restore ecx and edx.
411         popl    %ecx
412         ret
413         .size   GNAME(alloc_16_to_eax),.-GNAME(alloc_16_to_eax)
414
415         .globl  GNAME(alloc_to_ecx)
416         .type   GNAME(alloc_to_ecx),@function
417         .align  align_4byte,0x90
418 GNAME(alloc_to_ecx):
419         pushl   %eax    # Save eax and edx as C could destroy them.
420         pushl   %edx
421         pushl   %ecx    # Push the size.
422         call    GNAME(alloc)
423         addl    $4,%esp # Pop the size arg.
424         movl    %eax,%ecx       # Set up the destination.
425         popl    %edx    # Restore eax and edx.
426         popl    %eax
427         ret
428         .size   GNAME(alloc_to_ecx),.-GNAME(alloc_to_ecx)
429
430         .globl  GNAME(alloc_8_to_ecx)
431         .type   GNAME(alloc_8_to_ecx),@function
432         .align  align_4byte,0x90
433 GNAME(alloc_8_to_ecx):
434         pushl   %eax    # Save eax and edx as C could destroy them.
435         pushl   %edx
436         pushl   $8      # Push the size.
437         call    GNAME(alloc)
438         addl    $4,%esp # Pop the size arg.
439         movl    %eax,%ecx       # Set up the destination.
440         popl    %edx    # Restore eax and edx.
441         popl    %eax
442         ret
443         .size   GNAME(alloc_8_to_ecx),.-GNAME(alloc_8_to_ecx)
444
445         .globl  GNAME(alloc_16_to_ecx)
446         .type   GNAME(alloc_16_to_ecx),@function
447         .align  align_4byte,0x90
448 GNAME(alloc_16_to_ecx):
449         pushl   %eax    # Save eax and edx as C could destroy them.
450         pushl   %edx
451         pushl   $16     # Push the size.
452         call    GNAME(alloc)
453         addl    $4,%esp # Pop the size arg.
454         movl    %eax,%ecx       # Set up the destination.
455         popl    %edx    # Restore eax and edx.
456         popl    %eax
457         ret
458         .size   GNAME(alloc_16_to_ecx),.-GNAME(alloc_16_to_ecx)
459
460
461         .globl  GNAME(alloc_to_edx)
462         .type   GNAME(alloc_to_edx),@function
463         .align  align_4byte,0x90
464 GNAME(alloc_to_edx):
465         pushl   %eax    # Save eax and ecx as C could destroy them.
466         pushl   %ecx
467         pushl   %edx    # Push the size.
468         call    GNAME(alloc)
469         addl    $4,%esp # Pop the size arg.
470         movl    %eax,%edx       # Set up the destination.
471         popl    %ecx    # Restore eax and ecx.
472         popl    %eax
473         ret
474         .size   GNAME(alloc_to_edx),.-GNAME(alloc_to_edx)
475
476         .globl  GNAME(alloc_8_to_edx)
477         .type   GNAME(alloc_8_to_edx),@function
478         .align  align_4byte,0x90
479 GNAME(alloc_8_to_edx):
480         pushl   %eax    # Save eax and ecx as C could destroy them.
481         pushl   %ecx
482         pushl   $8      # Push the size.
483         call    GNAME(alloc)
484         addl    $4,%esp # Pop the size arg.
485         movl    %eax,%edx       # Set up the destination.
486         popl    %ecx    # Restore eax and ecx.
487         popl    %eax
488         ret
489         .size   GNAME(alloc_8_to_edx),.-GNAME(alloc_8_to_edx)
490
491         .globl  GNAME(alloc_16_to_edx)
492         .type   GNAME(alloc_16_to_edx),@function
493         .align  align_4byte,0x90
494 GNAME(alloc_16_to_edx):
495         pushl   %eax    # Save eax and ecx as C could destroy them.
496         pushl   %ecx
497         pushl   $16     # Push the size.
498         call    GNAME(alloc)
499         addl    $4,%esp # Pop the size arg.
500         movl    %eax,%edx       # Set up the destination.
501         popl    %ecx    # Restore eax and ecx.
502         popl    %eax
503         ret
504         .size   GNAME(alloc_16_to_edx),.-GNAME(alloc_16_to_edx)
505
506
507
508         .globl  GNAME(alloc_to_ebx)
509         .type   GNAME(alloc_to_ebx),@function
510         .align  align_4byte,0x90
511 GNAME(alloc_to_ebx):
512         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
513         pushl   %ecx
514         pushl   %edx
515         pushl   %ebx    # Push the size.
516         call    GNAME(alloc)
517         addl    $4,%esp # Pop the size arg.
518         movl    %eax,%ebx       # Set up the destination.
519         popl    %edx    # Restore eax, ecx and edx.
520         popl    %ecx
521         popl    %eax
522         ret
523         .size   GNAME(alloc_to_ebx),.-GNAME(alloc_to_ebx)
524
525         .globl  GNAME(alloc_8_to_ebx)
526         .type   GNAME(alloc_8_to_ebx),@function
527         .align  align_4byte,0x90
528 GNAME(alloc_8_to_ebx):
529         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
530         pushl   %ecx
531         pushl   %edx
532         pushl   $8      # Push the size.
533         call    GNAME(alloc)
534         addl    $4,%esp # Pop the size arg.
535         movl    %eax,%ebx       # Set up the destination.
536         popl    %edx    # Restore eax, ecx and edx.
537         popl    %ecx
538         popl    %eax
539         ret
540         .size   GNAME(alloc_8_to_ebx),.-GNAME(alloc_8_to_ebx)
541
542         .globl  GNAME(alloc_16_to_ebx)
543         .type   GNAME(alloc_16_to_ebx),@function
544         .align  align_4byte,0x90
545 GNAME(alloc_16_to_ebx):
546         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
547         pushl   %ecx
548         pushl   %edx
549         pushl   $16     # Push the size
550         call    GNAME(alloc)
551         addl    $4,%esp # pop the size arg.
552         movl    %eax,%ebx       # setup the destination.
553         popl    %edx    # Restore eax, ecx and edx.
554         popl    %ecx
555         popl    %eax
556         ret
557         .size   GNAME(alloc_16_to_ebx),.-GNAME(alloc_16_to_ebx)
558
559
560
561         .globl  GNAME(alloc_to_esi)
562         .type   GNAME(alloc_to_esi),@function
563         .align  align_4byte,0x90
564 GNAME(alloc_to_esi):
565         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
566         pushl   %ecx
567         pushl   %edx
568         pushl   %esi    # Push the size
569         call    GNAME(alloc)
570         addl    $4,%esp # pop the size arg.
571         movl    %eax,%esi       # setup the destination.
572         popl    %edx    # Restore eax, ecx and edx.
573         popl    %ecx
574         popl    %eax
575         ret
576         .size   GNAME(alloc_to_esi),.-GNAME(alloc_to_esi)
577
578         .globl  GNAME(alloc_8_to_esi)
579         .type   GNAME(alloc_8_to_esi),@function
580         .align  align_4byte,0x90
581 GNAME(alloc_8_to_esi):
582         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
583         pushl   %ecx
584         pushl   %edx
585         pushl   $8      # Push the size
586         call    GNAME(alloc)
587         addl    $4,%esp # pop the size arg.
588         movl    %eax,%esi       # setup the destination.
589         popl    %edx    # Restore eax, ecx and edx.
590         popl    %ecx
591         popl    %eax
592         ret
593         .size   GNAME(alloc_8_to_esi),.-GNAME(alloc_8_to_esi)
594
595         .globl  GNAME(alloc_16_to_esi)
596         .type   GNAME(alloc_16_to_esi),@function
597         .align  align_4byte,0x90
598 GNAME(alloc_16_to_esi):
599         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
600         pushl   %ecx
601         pushl   %edx
602         pushl   $16     # Push the size
603         call    GNAME(alloc)
604         addl    $4,%esp # pop the size arg.
605         movl    %eax,%esi       # setup the destination.
606         popl    %edx    # Restore eax, ecx and edx.
607         popl    %ecx
608         popl    %eax
609         ret
610         .size   GNAME(alloc_16_to_esi),.-GNAME(alloc_16_to_esi)
611
612
613         .globl  GNAME(alloc_to_edi)
614         .type   GNAME(alloc_to_edi),@function
615         .align  align_4byte,0x90
616 GNAME(alloc_to_edi):
617         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
618         pushl   %ecx
619         pushl   %edx
620         pushl   %edi    # Push the size
621         call    GNAME(alloc)
622         addl    $4,%esp # pop the size arg.
623         movl    %eax,%edi       # setup the destination.
624         popl    %edx    # Restore eax, ecx and edx.
625         popl    %ecx
626         popl    %eax
627         ret
628         .size   GNAME(alloc_to_edi),.-GNAME(alloc_to_edi)
629
630         .globl  GNAME(alloc_8_to_edi)
631         .type   GNAME(alloc_8_to_edi),@function
632         .align  align_4byte,0x90
633 GNAME(alloc_8_to_edi):
634         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
635         pushl   %ecx
636         pushl   %edx
637         pushl   $8      # Push the size
638         call    GNAME(alloc)
639         addl    $4,%esp # pop the size arg.
640         movl    %eax,%edi       # setup the destination.
641         popl    %edx    # Restore eax, ecx and edx.
642         popl    %ecx
643         popl    %eax
644         ret
645         .size   GNAME(alloc_8_to_edi),.-GNAME(alloc_8_to_edi)
646
647         .globl  GNAME(alloc_16_to_edi)
648         .type   GNAME(alloc_16_to_edi),@function
649         .align  align_4byte,0x90
650 GNAME(alloc_16_to_edi):
651         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
652         pushl   %ecx
653         pushl   %edx
654         pushl   $16     # Push the size
655         call    GNAME(alloc)
656         addl    $4,%esp # pop the size arg.
657         movl    %eax,%edi       # setup the destination.
658         popl    %edx    # Restore eax, ecx and edx.
659         popl    %ecx
660         popl    %eax
661         ret
662         .size   GNAME(alloc_16_to_edi),.-GNAME(alloc_16_to_edi)
663
664         
665 /* Called from lisp when an inline allocation overflows.
666    Every register except the result needs to be preserved.
667    We depend on C to preserve ebx, esi, edi, and ebp.
668    But where necessary must save eax, ecx, edx. */
669
670 #ifdef LISP_FEATURE_SB_THREAD
671 #define START_REGION %fs:THREAD_ALLOC_REGION_OFFSET
672 #else
673 #define START_REGION boxed_region
674 #endif
675                 
676 /* This routine handles an overflow with eax=crfp+size. So the
677    size=eax-crfp. */
678         .align  align_4byte
679         .globl  GNAME(alloc_overflow_eax)
680         .type   GNAME(alloc_overflow_eax),@function
681 GNAME(alloc_overflow_eax):
682         pushl   %ecx            # Save ecx
683         pushl   %edx            # Save edx
684         /* Calculate the size for the allocation. */
685         subl    START_REGION,%eax
686         pushl   %eax            # Push the size
687         call    GNAME(alloc)
688         addl    $4,%esp # pop the size arg.
689         popl    %edx    # Restore edx.
690         popl    %ecx    # Restore ecx.
691         ret
692         .size    GNAME(alloc_overflow_eax),.-GNAME(alloc_overflow_eax)
693
694         .align  align_4byte
695         .globl  GNAME(alloc_overflow_ecx)
696         .type   GNAME(alloc_overflow_ecx),@function
697 GNAME(alloc_overflow_ecx):
698         pushl   %eax            # Save eax
699         pushl   %edx            # Save edx
700         /* Calculate the size for the allocation. */
701         subl    START_REGION,%ecx
702         pushl   %ecx            # Push the size
703         call    GNAME(alloc)
704         addl    $4,%esp # pop the size arg.
705         movl    %eax,%ecx       # setup the destination.
706         popl    %edx    # Restore edx.
707         popl    %eax    # Restore eax.
708         ret
709         .size    GNAME(alloc_overflow_ecx),.-GNAME(alloc_overflow_ecx)
710
711         .align  align_4byte
712         .globl  GNAME(alloc_overflow_edx)
713         .type   GNAME(alloc_overflow_edx),@function
714 GNAME(alloc_overflow_edx):
715         pushl   %eax            # Save eax
716         pushl   %ecx            # Save ecx
717         /* Calculate the size for the allocation. */
718         subl    START_REGION,%edx
719         pushl   %edx            # Push the size
720         call    GNAME(alloc)
721         addl    $4,%esp # pop the size arg.
722         movl    %eax,%edx       # setup the destination.
723         popl    %ecx    # Restore ecx.
724         popl    %eax    # Restore eax.
725         ret
726         .size    GNAME(alloc_overflow_edx),.-GNAME(alloc_overflow_edx)
727
728 /* This routine handles an overflow with ebx=crfp+size. So the
729    size=ebx-crfp. */
730         .align  align_4byte
731         .globl  GNAME(alloc_overflow_ebx)
732         .type   GNAME(alloc_overflow_ebx),@function
733 GNAME(alloc_overflow_ebx):
734         pushl   %eax            # Save eax
735         pushl   %ecx            # Save ecx
736         pushl   %edx            # Save edx
737         /* Calculate the size for the allocation. */
738         subl    START_REGION,%ebx
739         pushl   %ebx            # Push the size
740         call    GNAME(alloc)
741         addl    $4,%esp # pop the size arg.
742         movl    %eax,%ebx       # setup the destination.
743         popl    %edx    # Restore edx.
744         popl    %ecx    # Restore ecx.
745         popl    %eax    # Restore eax.
746         ret
747         .size    GNAME(alloc_overflow_ebx),.-GNAME(alloc_overflow_ebx)
748
749 /* This routine handles an overflow with esi=crfp+size. So the
750    size=esi-crfp. */
751         .align  align_4byte
752         .globl  GNAME(alloc_overflow_esi)
753         .type   GNAME(alloc_overflow_esi),@function
754 GNAME(alloc_overflow_esi):
755         pushl   %eax            # Save eax
756         pushl   %ecx            # Save ecx
757         pushl   %edx            # Save edx
758         /* Calculate the size for the allocation. */
759         subl    START_REGION,%esi
760         pushl   %esi            # Push the size
761         call    GNAME(alloc)
762         addl    $4,%esp # pop the size arg.
763         movl    %eax,%esi       # setup the destination.
764         popl    %edx    # Restore edx.
765         popl    %ecx    # Restore ecx.
766         popl    %eax    # Restore eax.
767         ret
768         .size    GNAME(alloc_overflow_esi),.-GNAME(alloc_overflow_esi)
769
770         .align  align_4byte
771         .globl  GNAME(alloc_overflow_edi)
772         .type   GNAME(alloc_overflow_edi),@function
773 GNAME(alloc_overflow_edi):
774         pushl   %eax            # Save eax
775         pushl   %ecx            # Save ecx
776         pushl   %edx            # Save edx
777         /* Calculate the size for the allocation. */
778         subl    START_REGION,%edi
779         pushl   %edi            # Push the size
780         call    GNAME(alloc)
781         addl    $4,%esp # pop the size arg.
782         movl    %eax,%edi       # setup the destination.
783         popl    %edx    # Restore edx.
784         popl    %ecx    # Restore ecx.
785         popl    %eax    # Restore eax.
786         ret
787         .size    GNAME(alloc_overflow_edi),.-GNAME(alloc_overflow_edi)
788
789         .align  align_4byte,0x90
790         .globl  GNAME(post_signal_tramp)
791         .type   GNAME(post_signal_tramp),@function
792 GNAME(post_signal_tramp):
793         /* this is notionally the second half of a function whose first half
794          * doesn't exist.  This is where call_into_lisp returns when called 
795          * using return_to_lisp_function */
796         addl $12,%esp   /* clear call_into_lisp args from stack */
797         popal           /* restore registers */
798         popfl
799         leave
800         ret
801         .size GNAME(post_signal_tramp),.-GNAME(post_signal_tramp)
802
803         
804         .end