be588391bcf36d3fe187bf0fc09e62d5139ef3d8
[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_FUN_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         .byte   UNDEFINED_FUN_ERROR
266         .byte   sc_DescriptorReg # eax in the Descriptor-reg SC
267         ret
268         .size   GNAME(undefined_tramp), .-GNAME(undefined_tramp)
269
270 /*
271  * the closure trampoline
272  */
273         .text
274         .align  align_4byte,0x90
275         .global GNAME(closure_tramp)
276         .type   GNAME(closure_tramp),@function
277 GNAME(closure_tramp):
278         movl    FDEFN_FUN_OFFSET(%eax),%eax
279         /* FIXME: The '*' after "jmp" in the next line is from PVE's
280          * patch posted to the CMU CL mailing list Oct 6, 1999. It looks
281          * reasonable, and it certainly seems as though if CMU CL needs it,
282          * SBCL needs it too, but I haven't actually verified that it's
283          * right. It would be good to find a way to force the flow of
284          * control through here to test it. */
285         jmp     *CLOSURE_FUN_OFFSET(%eax)
286         .size   GNAME(closure_tramp), .-GNAME(closure_tramp)
287
288 /*
289  * fun-end breakpoint magic
290  */
291         .text
292         .global GNAME(fun_end_breakpoint_guts)
293         .align  align_4byte
294 GNAME(fun_end_breakpoint_guts):
295         /* Multiple Value return */
296         jmp     multiple_value_return
297         /* Single value return: The eventual return will now use the
298            multiple values return convention but with a return values
299            count of one. */
300         movl    %esp,%ebx       # Setup ebx - the ofp.
301         subl    $4,%esp         # Allocate one stack slot for the return value
302         movl    $4,%ecx         # Setup ecx for one return value.
303         movl    $NIL,%edi       # default second value
304         movl    $NIL,%esi       # default third value
305                 
306 multiple_value_return:
307         
308         .global GNAME(fun_end_breakpoint_trap)
309 GNAME(fun_end_breakpoint_trap):
310         int3
311         .byte   trap_FunEndBreakpoint
312         hlt                     # We should never return here.
313
314         .global GNAME(fun_end_breakpoint_end)
315 GNAME(fun_end_breakpoint_end):
316
317 \f
318         .global GNAME(do_pending_interrupt)
319         .type   GNAME(do_pending_interrupt),@function
320         .align  align_4byte,0x90
321 GNAME(do_pending_interrupt):
322         int3
323         .byte   trap_PendingInterrupt
324         ret
325         .size   GNAME(do_pending_interrupt),.-GNAME(do_pending_interrupt)
326 \f
327 #ifdef GENCGC
328 /* This is a fast bzero using the FPU. The first argument is the start
329  * address which needs to be aligned on an 8 byte boundary, the second
330  * argument is the number of bytes, which must be a nonzero multiple
331  * of 8 bytes. */
332         .text
333         .globl  GNAME(i586_bzero)
334         .type   GNAME(i586_bzero),@function
335         .align  align_4byte,0x90
336 GNAME(i586_bzero):
337         movl    4(%esp),%edx    # Load the start address.
338         movl    8(%esp),%eax    # Load the number of bytes.
339         fldz
340 l1:     fstl    0(%edx)
341         addl    $8,%edx
342         subl    $8,%eax
343         jnz     l1
344         fstp    %st(0)
345         ret
346         .size   GNAME(i586_bzero),.-GNAME(i586_bzero)
347 #endif  
348 \f
349
350 /*
351  * Allocate bytes and return the start of the allocated space
352  * in the specified destination register.
353  *
354  * In the general case the size will be in the destination register.
355  *
356  * All registers must be preserved except the destination.
357  * The C conventions will preserve ebx, esi, edi, and ebp.
358  * So only eax, ecx, and edx need special care here.
359  */
360         
361         .globl  GNAME(alloc_to_eax)
362         .type   GNAME(alloc_to_eax),@function
363         .align  align_4byte,0x90
364 GNAME(alloc_to_eax):
365         pushl   %ecx    # Save ecx and edx as C could destroy them.
366         pushl   %edx
367         pushl   %eax    # Push the size.
368         call    GNAME(alloc)
369         addl    $4,%esp # Pop the size arg.
370         popl    %edx    # Restore ecx and edx.
371         popl    %ecx
372         ret
373         .size   GNAME(alloc_to_eax),.-GNAME(alloc_to_eax)
374
375         .globl  GNAME(alloc_8_to_eax)
376         .type   GNAME(alloc_8_to_eax),@function
377         .align  align_4byte,0x90
378 GNAME(alloc_8_to_eax):
379         pushl   %ecx    # Save ecx and edx as C could destroy them.
380         pushl   %edx
381         pushl   $8      # Push the size.
382         call    GNAME(alloc)
383         addl    $4,%esp # Pop the size arg.
384         popl    %edx    # Restore ecx and edx.
385         popl    %ecx
386         ret
387         .size   GNAME(alloc_8_to_eax),.-GNAME(alloc_8_to_eax)
388
389         .globl  GNAME(alloc_8_to_eax)
390         .type   GNAME(alloc_8_to_eax),@function
391         .align  align_4byte,0x90
392
393         .globl  GNAME(alloc_16_to_eax)
394         .type   GNAME(alloc_16_to_eax),@function
395         .align  align_4byte,0x90
396 GNAME(alloc_16_to_eax):
397         pushl   %ecx    # Save ecx and edx as C could destroy them.
398         pushl   %edx
399         pushl   $16     # Push the size.
400         call    GNAME(alloc)
401         addl    $4,%esp # Pop the size arg.
402         popl    %edx    # Restore ecx and edx.
403         popl    %ecx
404         ret
405         .size   GNAME(alloc_16_to_eax),.-GNAME(alloc_16_to_eax)
406
407         .globl  GNAME(alloc_to_ecx)
408         .type   GNAME(alloc_to_ecx),@function
409         .align  align_4byte,0x90
410 GNAME(alloc_to_ecx):
411         pushl   %eax    # Save eax and edx as C could destroy them.
412         pushl   %edx
413         pushl   %ecx    # Push the size.
414         call    GNAME(alloc)
415         addl    $4,%esp # Pop the size arg.
416         movl    %eax,%ecx       # Set up the destination.
417         popl    %edx    # Restore eax and edx.
418         popl    %eax
419         ret
420         .size   GNAME(alloc_to_ecx),.-GNAME(alloc_to_ecx)
421
422         .globl  GNAME(alloc_8_to_ecx)
423         .type   GNAME(alloc_8_to_ecx),@function
424         .align  align_4byte,0x90
425 GNAME(alloc_8_to_ecx):
426         pushl   %eax    # Save eax and edx as C could destroy them.
427         pushl   %edx
428         pushl   $8      # Push the size.
429         call    GNAME(alloc)
430         addl    $4,%esp # Pop the size arg.
431         movl    %eax,%ecx       # Set up the destination.
432         popl    %edx    # Restore eax and edx.
433         popl    %eax
434         ret
435         .size   GNAME(alloc_8_to_ecx),.-GNAME(alloc_8_to_ecx)
436
437         .globl  GNAME(alloc_16_to_ecx)
438         .type   GNAME(alloc_16_to_ecx),@function
439         .align  align_4byte,0x90
440 GNAME(alloc_16_to_ecx):
441         pushl   %eax    # Save eax and edx as C could destroy them.
442         pushl   %edx
443         pushl   $16     # Push the size.
444         call    GNAME(alloc)
445         addl    $4,%esp # Pop the size arg.
446         movl    %eax,%ecx       # Set up the destination.
447         popl    %edx    # Restore eax and edx.
448         popl    %eax
449         ret
450         .size   GNAME(alloc_16_to_ecx),.-GNAME(alloc_16_to_ecx)
451
452
453         .globl  GNAME(alloc_to_edx)
454         .type   GNAME(alloc_to_edx),@function
455         .align  align_4byte,0x90
456 GNAME(alloc_to_edx):
457         pushl   %eax    # Save eax and ecx as C could destroy them.
458         pushl   %ecx
459         pushl   %edx    # Push the size.
460         call    GNAME(alloc)
461         addl    $4,%esp # Pop the size arg.
462         movl    %eax,%edx       # Set up the destination.
463         popl    %ecx    # Restore eax and ecx.
464         popl    %eax
465         ret
466         .size   GNAME(alloc_to_edx),.-GNAME(alloc_to_edx)
467
468         .globl  GNAME(alloc_8_to_edx)
469         .type   GNAME(alloc_8_to_edx),@function
470         .align  align_4byte,0x90
471 GNAME(alloc_8_to_edx):
472         pushl   %eax    # Save eax and ecx as C could destroy them.
473         pushl   %ecx
474         pushl   $8      # Push the size.
475         call    GNAME(alloc)
476         addl    $4,%esp # Pop the size arg.
477         movl    %eax,%edx       # Set up the destination.
478         popl    %ecx    # Restore eax and ecx.
479         popl    %eax
480         ret
481         .size   GNAME(alloc_8_to_edx),.-GNAME(alloc_8_to_edx)
482
483         .globl  GNAME(alloc_16_to_edx)
484         .type   GNAME(alloc_16_to_edx),@function
485         .align  align_4byte,0x90
486 GNAME(alloc_16_to_edx):
487         pushl   %eax    # Save eax and ecx as C could destroy them.
488         pushl   %ecx
489         pushl   $16     # Push the size.
490         call    GNAME(alloc)
491         addl    $4,%esp # Pop the size arg.
492         movl    %eax,%edx       # Set up the destination.
493         popl    %ecx    # Restore eax and ecx.
494         popl    %eax
495         ret
496         .size   GNAME(alloc_16_to_edx),.-GNAME(alloc_16_to_edx)
497
498
499
500         .globl  GNAME(alloc_to_ebx)
501         .type   GNAME(alloc_to_ebx),@function
502         .align  align_4byte,0x90
503 GNAME(alloc_to_ebx):
504         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
505         pushl   %ecx
506         pushl   %edx
507         pushl   %ebx    # Push the size.
508         call    GNAME(alloc)
509         addl    $4,%esp # Pop the size arg.
510         movl    %eax,%ebx       # Set up the destination.
511         popl    %edx    # Restore eax, ecx and edx.
512         popl    %ecx
513         popl    %eax
514         ret
515         .size   GNAME(alloc_to_ebx),.-GNAME(alloc_to_ebx)
516
517         .globl  GNAME(alloc_8_to_ebx)
518         .type   GNAME(alloc_8_to_ebx),@function
519         .align  align_4byte,0x90
520 GNAME(alloc_8_to_ebx):
521         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
522         pushl   %ecx
523         pushl   %edx
524         pushl   $8      # Push the size.
525         call    GNAME(alloc)
526         addl    $4,%esp # Pop the size arg.
527         movl    %eax,%ebx       # Set up the destination.
528         popl    %edx    # Restore eax, ecx and edx.
529         popl    %ecx
530         popl    %eax
531         ret
532         .size   GNAME(alloc_8_to_ebx),.-GNAME(alloc_8_to_ebx)
533
534         .globl  GNAME(alloc_16_to_ebx)
535         .type   GNAME(alloc_16_to_ebx),@function
536         .align  align_4byte,0x90
537 GNAME(alloc_16_to_ebx):
538         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
539         pushl   %ecx
540         pushl   %edx
541         pushl   $16     # Push the size
542         call    GNAME(alloc)
543         addl    $4,%esp # pop the size arg.
544         movl    %eax,%ebx       # setup the destination.
545         popl    %edx    # Restore eax, ecx and edx.
546         popl    %ecx
547         popl    %eax
548         ret
549         .size   GNAME(alloc_16_to_ebx),.-GNAME(alloc_16_to_ebx)
550
551
552
553         .globl  GNAME(alloc_to_esi)
554         .type   GNAME(alloc_to_esi),@function
555         .align  align_4byte,0x90
556 GNAME(alloc_to_esi):
557         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
558         pushl   %ecx
559         pushl   %edx
560         pushl   %esi    # Push the size
561         call    GNAME(alloc)
562         addl    $4,%esp # pop the size arg.
563         movl    %eax,%esi       # setup the destination.
564         popl    %edx    # Restore eax, ecx and edx.
565         popl    %ecx
566         popl    %eax
567         ret
568         .size   GNAME(alloc_to_esi),.-GNAME(alloc_to_esi)
569
570         .globl  GNAME(alloc_8_to_esi)
571         .type   GNAME(alloc_8_to_esi),@function
572         .align  align_4byte,0x90
573 GNAME(alloc_8_to_esi):
574         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
575         pushl   %ecx
576         pushl   %edx
577         pushl   $8      # Push the size
578         call    GNAME(alloc)
579         addl    $4,%esp # pop the size arg.
580         movl    %eax,%esi       # setup the destination.
581         popl    %edx    # Restore eax, ecx and edx.
582         popl    %ecx
583         popl    %eax
584         ret
585         .size   GNAME(alloc_8_to_esi),.-GNAME(alloc_8_to_esi)
586
587         .globl  GNAME(alloc_16_to_esi)
588         .type   GNAME(alloc_16_to_esi),@function
589         .align  align_4byte,0x90
590 GNAME(alloc_16_to_esi):
591         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
592         pushl   %ecx
593         pushl   %edx
594         pushl   $16     # Push the size
595         call    GNAME(alloc)
596         addl    $4,%esp # pop the size arg.
597         movl    %eax,%esi       # setup the destination.
598         popl    %edx    # Restore eax, ecx and edx.
599         popl    %ecx
600         popl    %eax
601         ret
602         .size   GNAME(alloc_16_to_esi),.-GNAME(alloc_16_to_esi)
603
604
605         .globl  GNAME(alloc_to_edi)
606         .type   GNAME(alloc_to_edi),@function
607         .align  align_4byte,0x90
608 GNAME(alloc_to_edi):
609         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
610         pushl   %ecx
611         pushl   %edx
612         pushl   %edi    # Push the size
613         call    GNAME(alloc)
614         addl    $4,%esp # pop the size arg.
615         movl    %eax,%edi       # setup the destination.
616         popl    %edx    # Restore eax, ecx and edx.
617         popl    %ecx
618         popl    %eax
619         ret
620         .size   GNAME(alloc_to_edi),.-GNAME(alloc_to_edi)
621
622         .globl  GNAME(alloc_8_to_edi)
623         .type   GNAME(alloc_8_to_edi),@function
624         .align  align_4byte,0x90
625 GNAME(alloc_8_to_edi):
626         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
627         pushl   %ecx
628         pushl   %edx
629         pushl   $8      # Push the size
630         call    GNAME(alloc)
631         addl    $4,%esp # pop the size arg.
632         movl    %eax,%edi       # setup the destination.
633         popl    %edx    # Restore eax, ecx and edx.
634         popl    %ecx
635         popl    %eax
636         ret
637         .size   GNAME(alloc_8_to_edi),.-GNAME(alloc_8_to_edi)
638
639         .globl  GNAME(alloc_16_to_edi)
640         .type   GNAME(alloc_16_to_edi),@function
641         .align  align_4byte,0x90
642 GNAME(alloc_16_to_edi):
643         pushl   %eax    # Save eax, ecx, and edx as C could destroy them.
644         pushl   %ecx
645         pushl   %edx
646         pushl   $16     # Push the size
647         call    GNAME(alloc)
648         addl    $4,%esp # pop the size arg.
649         movl    %eax,%edi       # setup the destination.
650         popl    %edx    # Restore eax, ecx and edx.
651         popl    %ecx
652         popl    %eax
653         ret
654         .size   GNAME(alloc_16_to_edi),.-GNAME(alloc_16_to_edi)
655                 
656
657 \f
658 #ifdef GENCGC
659
660 /* These routines are called from Lisp when an inline allocation 
661  * overflows. Every register except the result needs to be preserved.
662  * We depend on C to preserve ebx, esi, edi, and ebp.
663  * But where necessary must save eax, ecx, edx. */
664
665 /* This routine handles an overflow with eax=crfp+size. So the
666  * size=eax-crfp. */
667         .align  align_4byte
668         .globl  GNAME(alloc_overflow_eax)
669         .type   GNAME(alloc_overflow_eax),@function
670 GNAME(alloc_overflow_eax):
671         pushl   %ecx            # Save ecx
672         pushl   %edx            # Save edx
673         /* Calculate the size for the allocation. */
674         subl    GNAME(current_region_free_pointer),%eax
675         pushl   %eax            # Push the size
676         call    GNAME(alloc)
677         addl    $4,%esp # pop the size arg.
678         popl    %edx    # Restore edx.
679         popl    %ecx    # Restore ecx.
680         addl    $6,(%esp) # Adjust the return address to skip the next inst.
681         ret
682         .size    GNAME(alloc_overflow_eax),.-GNAME(alloc_overflow_eax)
683
684 /* This routine handles an overflow with ecx=crfp+size. So the
685  * size=ecx-crfp. */
686         .align  align_4byte
687         .globl  GNAME(alloc_overflow_ecx)
688         .type   GNAME(alloc_overflow_ecx),@function
689 GNAME(alloc_overflow_ecx):
690         pushl   %eax            # Save eax
691         pushl   %edx            # Save edx
692         /* Calculate the size for the allocation. */
693         subl    GNAME(current_region_free_pointer),%ecx
694         pushl   %ecx            # Push the size
695         call    GNAME(alloc)
696         addl    $4,%esp # pop the size arg.
697         movl    %eax,%ecx       # setup the destination.
698         popl    %edx    # Restore edx.
699         popl    %eax    # Restore eax.
700         addl    $6,(%esp) # Adjust the return address to skip the next inst.
701         ret
702         .size    GNAME(alloc_overflow_ecx),.-GNAME(alloc_overflow_ecx)
703
704 /* This routine handles an overflow with edx=crfp+size. So the
705  * size=edx-crfp. */
706         .align  align_4byte
707         .globl  GNAME(alloc_overflow_edx)
708         .type   GNAME(alloc_overflow_edx),@function
709 GNAME(alloc_overflow_edx):
710         pushl   %eax            # Save eax
711         pushl   %ecx            # Save ecx
712         /* Calculate the size for the allocation. */
713         subl    GNAME(current_region_free_pointer),%edx
714         pushl   %edx            # Push the size
715         call    GNAME(alloc)
716         addl    $4,%esp # pop the size arg.
717         movl    %eax,%edx       # setup the destination.
718         popl    %ecx    # Restore ecx.
719         popl    %eax    # Restore eax.
720         addl    $6,(%esp) # Adjust the return address to skip the next inst.
721         ret
722         .size    GNAME(alloc_overflow_edx),.-GNAME(alloc_overflow_edx)
723
724 /* This routine handles an overflow with ebx=crfp+size. So the
725  * size=ebx-crfp. */
726         .align  align_4byte
727         .globl  GNAME(alloc_overflow_ebx)
728         .type   GNAME(alloc_overflow_ebx),@function
729 GNAME(alloc_overflow_ebx):
730         pushl   %eax            # Save eax
731         pushl   %ecx            # Save ecx
732         pushl   %edx            # Save edx
733         /* Calculate the size for the allocation. */
734         subl    GNAME(current_region_free_pointer),%ebx
735         pushl   %ebx            # Push the size
736         call    GNAME(alloc)
737         addl    $4,%esp # pop the size arg.
738         movl    %eax,%ebx       # setup the destination.
739         popl    %edx    # Restore edx.
740         popl    %ecx    # Restore ecx.
741         popl    %eax    # Restore eax.
742         addl    $6,(%esp) # Adjust the return address to skip the next inst.
743         ret
744         .size    GNAME(alloc_overflow_ebx),.-GNAME(alloc_overflow_ebx)
745
746 /* This routine handles an overflow with esi=crfp+size. So the
747  * size=esi-crfp. */
748         .align  align_4byte
749         .globl  GNAME(alloc_overflow_esi)
750         .type   GNAME(alloc_overflow_esi),@function
751 GNAME(alloc_overflow_esi):
752         pushl   %eax            # Save eax
753         pushl   %ecx            # Save ecx
754         pushl   %edx            # Save edx
755         /* Calculate the size for the allocation. */
756         subl    GNAME(current_region_free_pointer),%esi
757         pushl   %esi            # Push the size
758         call    GNAME(alloc)
759         addl    $4,%esp # pop the size arg.
760         movl    %eax,%esi       # setup the destination.
761         popl    %edx    # Restore edx.
762         popl    %ecx    # Restore ecx.
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_esi),.-GNAME(alloc_overflow_esi)
767
768 /* This routine handles an overflow with edi=crfp+size. So the
769  * size=edi-crfp. */
770         .align  align_4byte
771         .globl  GNAME(alloc_overflow_edi)
772         .type   GNAME(alloc_overflow_edi),@function
773 GNAME(alloc_overflow_edi):
774         pushl   %eax            # Save eax
775         pushl   %ecx            # Save ecx
776         pushl   %edx            # Save edx
777         /* Calculate the size for the allocation. */
778         subl    GNAME(current_region_free_pointer),%edi
779         pushl   %edi            # Push the size
780         call    GNAME(alloc)
781         addl    $4,%esp # pop the size arg.
782         movl    %eax,%edi       # setup the destination.
783         popl    %edx    # Restore edx.
784         popl    %ecx    # Restore ecx.
785         popl    %eax    # Restore eax.
786         addl    $6,(%esp) # Adjust the return address to skip the next inst.
787         ret
788         .size    GNAME(alloc_overflow_edi),.-GNAME(alloc_overflow_edi)
789
790 #endif
791
792         .end