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