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