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