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