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