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