* src/vm/exceptions.c (exceptions_asm_new_abstractmethoderror): New
[cacao.git] / src / vm / jit / i386 / asmpart.S
1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    Changes: Joseph Wenninger
32             Edwin Steiner
33
34    $Id: asmpart.S 5054 2006-06-28 19:43:42Z twisti $
35
36 */
37
38
39 #include "config.h"
40
41 #include "vm/jit/i386/arch.h"
42 #include "vm/jit/i386/md-abi.h"
43 #include "vm/jit/i386/md-asm.h"
44 #include "vm/jit/i386/offsets.h"
45
46 #include "vm/jit/abi-asm.h"
47 #include "vm/jit/methodheader.h"
48
49
50         .text
51
52
53 /* export functions ***********************************************************/
54
55         .globl asm_md_init
56
57         .globl asm_vm_call_method
58         .globl asm_vm_call_method_int
59         .globl asm_vm_call_method_long
60         .globl asm_vm_call_method_float
61         .globl asm_vm_call_method_double
62         .globl asm_vm_call_method_exception_handler
63
64         .globl asm_call_jit_compiler
65         .globl asm_handle_nat_exception
66         .globl asm_handle_exception
67
68         .globl asm_abstractmethoderror
69
70         .globl asm_wrapper_patcher
71
72         .globl asm_replacement_out
73         .globl asm_replacement_in
74
75         .globl asm_builtin_f2i
76         .globl asm_builtin_f2l
77         .globl asm_builtin_d2i
78         .globl asm_builtin_d2l
79
80         .globl asm_criticalsections
81         .globl asm_getclassvalues_atomic
82
83         .globl asm_get_cycle_count
84
85
86 /* asm_md_init *****************************************************************
87
88    Initialize machine dependent stuff.
89
90    See: http://www.srware.com/linux_numerics.txt
91
92    This puts the X86 FPU in 64-bit precision mode.  The default under
93    Linux is to use 80-bit mode, which produces subtle differences from
94    FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
95    64-bit mode, 299 in 80-bit mode.
96
97    Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
98
99 *******************************************************************************/
100
101 asm_md_init:
102         sub     $4,sp                       /* allocate space for the FPU state   */
103         fnstcw  (sp)                        /* get the FPU state                  */
104         mov     (sp),%eax
105         and     $0xfcff,%ax                 /* remove the extended mode flag      */
106         or      $0x0200,%ax                 /* put the double mode flag           */
107         mov     %eax,(sp)                   /* store new FPU state                */
108         fldcw   (sp)                        /* setup new FPU state                */
109         add     $4,sp
110         ret
111
112
113 /********************* function asm_calljavafunction ***************************
114 *                                                                              *
115 *   This function calls a Java-method (which possibly needs compilation)       *
116 *   with up to 4 address parameters.                                           *
117 *                                                                              *
118 *   This functions calls the JIT-compiler which eventually translates the      *
119 *   method into machine code.                                                  *
120 *                                                                              *
121 *   C-prototype:                                                               *
122 *    javaobject_header *asm_vm_call_method(methodinfo *m,                      *
123 *         u4 count, u4 size, void *callblock);                                 *
124 *                                                                              *
125 *******************************************************************************/
126
127         .align  8
128
129         .long   0                           /* catch type all                     */
130         .long   0                           /* handler pc                         */
131         .long   0                           /* end pc                             */
132         .long   0                           /* start pc                           */
133         .long   1                           /* extable size                       */
134         .long   0                           /* line number table start            */
135         .long   0                           /* line number table size             */
136         .long   0                           /* fltsave                            */
137         .long   0                           /* intsave                            */
138         .long   0                           /* isleaf                             */
139         .long   0                           /* IsSync                             */
140         .long   0                           /* frame size                         */
141         .long   0                           /* codeinfo pointer                   */
142
143 asm_vm_call_method:
144 asm_vm_call_method_int:
145 asm_vm_call_method_long:
146 asm_vm_call_method_float:
147 asm_vm_call_method_double:
148         push    bp
149         mov     sp,bp                       /* save stackptr                      */
150         sub     $(4*4),sp                   /* create stackframe                  */
151         and     $0xfffffff0,sp              /* align stack to 16-byte             */
152
153         mov     t0,0*4(sp)                  /* save registers                     */
154         mov     s1,1*4(sp)
155         mov     s2,2*4(sp)
156
157         mov     4*4(bp),itmp1               /* pointer to arg block (4(push)+4(return)+4+4)*/
158         mov     3*4(bp),itmp2               /* arg count            (4(push)+4(return)+4 */
159
160         mov     sp,s1                       /* save the stackpointer              */
161
162         test    itmp2,itmp2                 /* maybe we have no args              */
163         jle     calljava_copydone
164
165         mov     itmp2,itmp3                 /* calculate stack size               */
166         mov     itmp1,%edi                  /* save pointer to arg block          */
167
168 calljava_calcstacksize:
169         mov     offvmargtype(itmp1),t0
170         test    $1,t0                       /* two word type?                     */
171         jz      calljava_onewordtype
172
173         sub     $4,sp                       /* add 1 slot to stackframe size      */
174
175 calljava_onewordtype:
176         sub     $4,sp                       /* add 1 slot to stackframe size      */
177         sub     $1,itmp3
178         test    itmp3,itmp3                 /* any args left?                     */
179         jz      calljava_setstack
180
181         add     $sizevmarg,itmp1            /* goto next argument block           */
182         jmp     calljava_calcstacksize
183                 
184 calljava_setstack:                              
185         mov     %edi,itmp1                  /* restore pointer to arg block       */
186         and     $0xfffffff0,sp              /* align stack to 16-byte             */
187         mov     sp,itmp3                    /* initialize pointer for copying     */
188
189 calljava_copyloop:
190         mov     offvmargdata(itmp1),t0      /* get 4-bytes of argument            */
191         mov     t0,(itmp3)                  /* and store them on the stack        */
192         add     $4,itmp3                    /* increase sp to next argument       */
193         mov     offvmargtype(itmp1),t0      /* get the argument type              */
194         test    $1,t0                       /* two word type?                     */
195         jz      calljava_copynext
196
197         mov     offvmargdata+4(itmp1),t0    /* get upper 4-bytes of 2 word type   */
198         mov     t0,(itmp3)                      
199         add     $4,itmp3                    /* increase sp to next argument       */
200
201 calljava_copynext:              
202         sub     $1,itmp2                    /* are there any args left?           */
203         test    itmp2,itmp2
204         jle     calljava_copydone
205
206         add     $sizevmarg,itmp1            /* goto next argument block           */
207         jmp     calljava_copyloop
208
209 calljava_copydone:
210         mov     2*4(bp),itmp1               /* move function pointer to itmp1     */
211
212         lea     L_asm_call_jit_compiler,itmp3
213         call    *itmp3                      /* call JIT compiler                  */
214
215 L_asm_vm_call_method_return:
216         mov     s1,sp                       /* restore stackpointer               */
217
218         mov     0*4(sp),t0                  /* restore registers                  */
219         mov     1*4(sp),s1
220         mov     2*4(sp),s2
221
222         leave
223         ret
224
225 asm_vm_call_method_exception_handler:
226         push    xptr                        /* pass exception pointer             */
227         call    builtin_throw_exception
228         add     $4,sp
229         jmp     L_asm_vm_call_method_return
230
231
232 /* asm_call_jit_compiler *******************************************************
233
234    Invokes the compiler for untranslated JavaVM methods.
235
236    Register R0 contains a pointer to the method info structure (prepared
237    by createcompilerstub). Using the return address in R26 and the
238    offset in the LDA instruction or using the value in methodptr R28 the
239    patching address for storing the method address can be computed:
240
241    Method address was either loaded using
242
243    i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special
244    i386_call_reg(REG_ITMP2)
245
246    or
247
248    i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface
249    i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
250    i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
251        sizeof(methodptr) * m->vftblindex, REG_ITMP1)
252    i386_call_reg(REG_ITMP1)
253
254    In the static case the method pointer can be computed using the
255    return address and the lda function following the jmp instruction.
256
257 *******************************************************************************/
258
259 asm_call_jit_compiler:
260 L_asm_call_jit_compiler:                /* required for PIC code              */
261         sub     $((4+2)*4+sizestackframeinfo),sp /* create stack frame            */
262         mov     itmp1,(4+0)*4(sp)           /* save method pointer                */
263                         
264         mov     (4+2)*4+sizestackframeinfo(sp),itmp3 /* get return address        */
265         mov     -1(itmp3),itmp1b            /* get function code                  */
266         cmp     $0xd1,itmp1b                /* called with `call *REG_ITMP2'?     */
267         jne             L_not_static_special
268
269         sub     $6,itmp3                    /* calculate address of immediate     */
270         jmp             L_call_jit_compile
271                 
272 L_not_static_special:
273         cmp     $0xd0,itmp1b                /* called with `call *REG_ITMP1'      */
274         jne             L_not_virtual_interface
275         
276         sub     $6,itmp3                    /* calculate address of offset        */
277         mov     (itmp3),itmp3               /* get offset                         */
278         add     itmp2,itmp3                 /* add base address to get method adr */
279         jmp             L_call_jit_compile
280
281 L_not_virtual_interface:
282         xor     itmp3,itmp3                 /* a call from asm_calljavafunction   */
283                 
284 L_call_jit_compile:
285         mov     itmp3,(4+1)*4(sp)           /* save address for method pointer    */
286
287         mov     sp,itmp1                    /* create stackframe info             */
288         add     $((4+2)*4),itmp1
289         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
290         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
291         mov     sp,itmp2
292         add     $((1+4+2)*4+sizestackframeinfo),itmp2 /* pass java sp             */
293         mov     itmp2,2*4(sp)
294         mov     ((0+4+2)*4+sizestackframeinfo)(sp),itmp3 /* pass java ra          */
295         mov     itmp3,3*4(sp)
296         call    stacktrace_create_inline_stackframeinfo
297
298         mov     (4+0)*4(sp),itmp1           /* pass method pointer                */
299         mov     itmp1,0*4(sp)
300         call    jit_compile
301         mov     v0,(4+0)*4(sp)              /* save return value                  */
302
303         mov     sp,itmp1                    /* remove stackframe info             */
304         add     $((4+2)*4),itmp1
305         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
306         call    stacktrace_remove_stackframeinfo
307
308         mov     (4+0)*4(sp),v0              /* restore return value               */
309         mov     (4+1)*4(sp),itmp3           /* restore address for method pointer */
310
311         add     $((4+2)*4+sizestackframeinfo),sp /* remove stack frame            */
312
313         test    v0,v0                       /* check for exception                */
314         je      L_asm_call_jit_compiler_exception
315
316         test    itmp3,itmp3                 /* was this a JIT call?               */
317         je              L_call_method
318         
319         mov     v0,(itmp3)                  /* save the new method pointer        */
320
321 L_call_method:
322         jmp             *v0                         /* ...and now call the new method     */
323
324 L_asm_call_jit_compiler_exception:
325 #if defined(ENABLE_THREADS)
326         call    builtin_asm_get_exceptionptrptr
327         mov     v0,itmp2                    /* v0 == itmp1                        */
328 #else
329         lea     _exceptionptr,itmp2
330 #endif
331         mov     (itmp2),xptr                /* get the exception pointer          */
332         movl    $0,(itmp2)                  /* clear the exception pointer        */
333
334         pop     xpc                         /* get return address                 */
335         sub     $2,xpc                      /* faulting address is ra - 2         */
336         jmp     L_asm_handle_exception
337
338
339 /* asm_handle_exception ********************************************************
340 *                                                                              *
341 *   This function handles an exception. It does not use the usual calling      *
342 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
343 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
344 *   the local exception table for a handler. If no one is found, it unwinds    *
345 *   stacks and continues searching the callers.                                *
346 *                                                                              *
347 *******************************************************************************/
348
349 asm_handle_nat_exception:
350         add     $4,sp                       /* clear return address of native stub*/
351                 
352 asm_handle_exception:
353 L_asm_handle_exception:                 /* required for PIC code              */
354         sub     $((ARG_CNT+TMP_CNT)*4),sp   /* create maybe-leaf stackframe       */
355
356         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
357         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
358
359         mov     $((ARG_CNT+TMP_CNT)*4),itmp3/* prepare a3 for handle_exception    */
360         mov     $1,t0                       /* set maybe-leaf flag                */
361
362 L_asm_handle_exception_stack_loop:
363         sub     $(10*4),sp                  /* create stackframe                  */
364         mov     xptr,4*4(sp)                /* save exception pointer             */
365         mov     xpc,5*4(sp)                 /* save exception pc                  */
366         add     sp,itmp3                    /* calculate Java sp into a3...       */
367         add     $(10*4),itmp3
368         mov     itmp3,7*4(sp)               /* ...and save it                     */
369         mov     t0,8*4(sp)                  /* save maybe-leaf flag               */
370
371         mov     xpc,0*4(sp)                 /* pass exception pc                  */
372         call    codegen_findmethod
373         mov     v0,6*4(sp)                  /* save data segment pointer          */
374
375         mov     4*4(sp),itmp3               /* pass exception pointer             */
376         mov     itmp3,0*4(sp)
377         mov     5*4(sp),itmp3               /* pass exception pc                  */
378         mov     itmp3,1*4(sp)
379         mov     v0,2*4(sp)                  /* pass data segment pointer          */
380         mov     7*4(sp),itmp3               /* pass Java stack pointer            */
381         mov     itmp3,3*4(sp)
382         call    exceptions_handle_exception
383
384         test    v0,v0
385         jz      L_asm_handle_exception_not_catched
386
387         mov     v0,xpc                      /* move handlerpc into xpc            */
388         mov     4*4(sp),xptr                /* restore exception pointer          */
389         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
390         add     $(10*4),sp                  /* free stackframe                    */
391
392         test    t0,t0                       /* test for maybe-leaf flag           */
393         jz      L_asm_handle_exception_no_leaf
394
395         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
396         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
397
398         add     $((ARG_CNT+TMP_CNT)*4),sp   /* remove maybe-leaf stackframe       */
399
400 L_asm_handle_exception_no_leaf:
401         jmp     *xpc                        /* jump to exception handler          */
402
403 L_asm_handle_exception_not_catched:
404         mov     4*4(sp),xptr                /* restore exception pointer          */
405         mov     6*4(sp),itmp3               /* restore data segment pointer       */
406         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
407         add     $(10*4),sp                  /* free stackframe                    */
408
409         test    t0,t0
410         jz      L_asm_handle_exception_no_leaf_stack
411
412         add     $((ARG_CNT+TMP_CNT)*4),sp   /* remove maybe-leaf stackframe       */
413         xor     t0,t0                       /* clear the maybe-leaf flag          */
414
415 L_asm_handle_exception_no_leaf_stack:
416         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
417         add     sp,itmp2                    /* pointer to save area               */
418
419         push    xptr                        /* we are out of registers            */
420
421         mov     IntSave(itmp3),itmp1        /* itmp1 = saved int register count   */
422         test    itmp1,itmp1
423         je      noint
424
425         cmp     $1,itmp1
426         je      int1
427         cmp     $2,itmp1
428         je      int2
429
430         mov     -3*4(itmp2),s0
431 int2:   
432         mov     -2*4(itmp2),s1
433 int1:   
434         mov     -1*4(itmp2),s2
435
436         shl     $2,itmp1                    /* multiply by 4 bytes                */
437         sub     itmp1,itmp2
438                 
439 noint:
440 #if 0
441         mov     FltSave(itmp3),itmp1        /* itmp1 = saved flt register count   */
442         test    itmp1,itmp1
443         je      noflt
444
445         cmp     $1,itmp1
446         je      flt1
447         cmp     $2,itmp1
448         je      flt2
449         cmp     $3,itmp1
450         je      flt3
451                 
452         fldl    -4*8(itmp2)
453         fstp    %st(1)
454 flt3:
455         fldl    -3*8(itmp2)
456         fstp    %st(2)
457 flt2:
458         fldl    -2*8(itmp2)
459         fstp    %st(3)
460 flt1:
461         fldl    -1*8(itmp2)
462         fstp    %st(4)
463                 
464 noflt:
465 #endif
466         pop     xptr                        /* restore exception pointer          */
467         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
468         add     itmp2,sp                    /* unwind stack                       */
469
470         pop     xpc                         /* the new xpc is return address      */
471         sub     $2,xpc                      /* subtract 2-bytes for call          */
472
473         xor     itmp3,itmp3                 /* prepare a3 for handle_exception    */
474
475         jmp     L_asm_handle_exception_stack_loop
476                 
477
478 /* asm_abstractmethoderror *****************************************************
479
480    Creates and throws an AbstractMethodError.
481
482 *******************************************************************************/
483
484 asm_abstractmethoderror:
485         sub     $(2*4),sp                   /* create stack frame                 */
486         mov     sp,itmp1                    /* pass java sp                       */
487         add     $((1+2)*4),itmp1
488         mov     itmp1,0*4(sp)
489         mov     2*4(sp),itmp2               /* pass exception address             */
490         sub     $2,itmp2
491         mov     itmp2,1*4(sp)
492         call    exceptions_asm_new_abstractmethoderror
493                                             /* exception pointer is return value  */
494         add     $(2*4),sp                   /* remove stack frame                 */
495
496         pop     xpc                         /* get exception address              */
497         sub     $2,xpc                      /* exception address is ra - 2        */
498         jmp     L_asm_handle_exception
499
500
501 /* asm_wrapper_patcher *********************************************************
502
503    XXX
504
505    Stack layout:
506      24   return address
507      20   REG_ITMP3
508      16   pointer to virtual java_objectheader
509      12   last byte of machine code (xmcode)
510       8   machine code (which is patched back later)
511       4   unresolved field reference
512       0   patcher function pointer to call
513
514 *******************************************************************************/
515
516 asm_wrapper_patcher:
517         sub     $((2+4)*4+sizestackframeinfo),sp /* create stack frame            */
518
519         mov     itmp1,(0+4)*4(sp)           /* save itmp1 and itmp2               */
520         mov     itmp2,(1+4)*4(sp)           /* may be used by some instructions   */
521
522         mov     sp,itmp1                    /* create stackframe info             */
523         add     $((2+4)*4),itmp1
524         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
525         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
526         mov     sp,itmp2
527         add     $((7+2+4)*4+sizestackframeinfo),itmp2
528         mov     itmp2,2*4(sp)               /* pass Java sp                       */
529         mov     ((6+2+4)*4+sizestackframeinfo)(sp),itmp3
530         mov     itmp3,3*4(sp)               /* pass ra to java function           */
531         call    stacktrace_create_inline_stackframeinfo
532
533         mov     sp,itmp1                    /* pass stack pointer                 */
534         add     $((1+2+4)*4+sizestackframeinfo),itmp1  /* skip function pointer   */
535         mov     itmp1,0*4(sp)
536         mov     (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer    */
537         call    *itmp1                      /* call the patcher function          */
538         mov     v0,1*4(sp)                  /* save return value                  */
539
540         mov     sp,itmp1                    /* remove stackframe info             */
541         add     $((2+4)*4),itmp1
542         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
543         call    stacktrace_remove_stackframeinfo
544
545         mov     1*4(sp),itmp3               /* restore return value               */
546         test    itmp3,itmp3                 /* exception thrown?                  */
547         jz      L_asm_wrapper_patcher_exception
548
549         mov     (0+4)*4(sp),itmp1           /* restore itmp1 and itmp2            */
550         mov     (1+4)*4(sp),itmp2           /* may be used by some instructions   */
551         mov     ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
552         add     $((6+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
553
554         ret                                 /* call new patched code              */
555
556 L_asm_wrapper_patcher_exception:
557         add     $((6+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
558
559 #if defined(ENABLE_THREADS)
560         call    builtin_asm_get_exceptionptrptr
561         mov     v0,itmp2
562 #else
563         lea     _exceptionptr,itmp2
564 #endif
565         mov     (itmp2),xptr                /* get the exception pointer          */
566         movl    $0,(itmp2)                  /* clear the exception pointer        */
567
568         pop     xpc                         /* get and remove return address      */
569         jmp     L_asm_handle_exception
570
571
572 /* asm_replacement_out *********************************************************
573
574    This code is jumped to from the replacement-out stubs that are executed
575    when a thread reaches an activated replacement point.
576
577    The purpose of asm_replacement_out is to read out the parts of the
578    execution state that cannot be accessed from C code, store this state,
579    and then call the C function replace_me.
580
581    Stack layout:
582       4                 start of stack inside method to replace
583       0   rplpoint *    info on the replacement point that was reached
584
585 *******************************************************************************/
586
587 /* some room to accomodate changes of the stack frame size during replacement */
588         /* XXX we should find a cleaner solution here */
589 #define REPLACEMENT_ROOM  512
590
591 asm_replacement_out:
592     /* create stack frame */
593         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
594
595         /* save registers in execution state */
596         mov     %eax,(EAX*8+offes_intregs)(sp)
597         mov     %ebx,(EBX*8+offes_intregs)(sp)
598         mov     %ecx,(ECX*8+offes_intregs)(sp)
599         mov     %edx,(EDX*8+offes_intregs)(sp)
600         mov     %esi,(ESI*8+offes_intregs)(sp)
601         mov     %edi,(EDI*8+offes_intregs)(sp)
602         mov     %ebp,(EBP*8+offes_intregs)(sp)
603         movl    $0  ,(ESP*8+offes_intregs)(sp) /* not used */
604
605 #ifndef NDEBUG
606         /* clear high 32bit */
607         movl    $0,(4+0*8+offes_intregs)(sp)
608         movl    $0,(4+1*8+offes_intregs)(sp)
609         movl    $0,(4+2*8+offes_intregs)(sp)
610         movl    $0,(4+3*8+offes_intregs)(sp)
611         movl    $0,(4+4*8+offes_intregs)(sp)
612         movl    $0,(4+5*8+offes_intregs)(sp)
613         movl    $0,(4+6*8+offes_intregs)(sp)
614         movl    $0,(4+7*8+offes_intregs)(sp)
615 #endif
616
617         /* calculate sp of method */
618         mov     sp,itmp1
619         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
620         mov     itmp1,(offes_sp)(sp)
621
622         /* pv must be looked up via AVL tree */
623         movl    $0,(offes_pv)(sp)
624
625         /* call replace_me */
626         mov     -4(itmp1),itmp1             /* rplpoint *                         */
627     push    sp                          /* arg1: execution state              */
628     push    itmp1                       /* arg0: replacement point            */
629     call    replace_me                  /* call C function replace_me         */
630     call    abort                       /* NEVER REACHED                      */
631
632 /* asm_replacement_in **********************************************************
633
634    This code writes the given execution state and jumps to the replacement
635    code.
636
637    This function never returns!
638
639    C prototype:
640       void asm_replacement_in(executionstate *es);
641
642 *******************************************************************************/
643
644 asm_replacement_in:
645         mov     4(sp),%ebp                  /* executionstate *es                 */
646
647         /* set new sp */
648         mov     (offes_sp)(%ebp),%esp
649         
650         /* store address of new code */
651         push    (offes_pc)(%ebp)
652         
653         /* copy registers from execution state */
654         mov     (EAX*8+offes_intregs)(%ebp),%eax
655         mov     (EBX*8+offes_intregs)(%ebp),%ebx
656         mov     (ECX*8+offes_intregs)(%ebp),%ecx
657         mov     (EDX*8+offes_intregs)(%ebp),%edx
658         mov     (ESI*8+offes_intregs)(%ebp),%esi
659         mov     (EDI*8+offes_intregs)(%ebp),%edi
660
661         mov     (EBP*8+offes_intregs)(%ebp),%ebp
662
663         /* jump to new code */
664         ret
665
666 /************************ function asm_builtin_x2x *****************************
667 *                                                                              *
668 *   Wrapper functions for corner cases                                         *
669 *                                                                              *
670 *******************************************************************************/
671
672 asm_builtin_f2i:
673         sub     $4,%esp
674         fsts    (%esp)
675         call    builtin_f2i
676         add     $4,%esp
677         ret
678
679 asm_builtin_d2i:
680         sub     $8,%esp
681         fstl    (%esp)
682         call    builtin_d2i
683         add     $8,%esp
684         ret
685
686 asm_builtin_f2l:
687         sub     $4,%esp
688         fsts    (%esp)
689         call    builtin_f2l
690         add     $4,%esp
691         ret
692
693 asm_builtin_d2l:
694         sub     $8,%esp
695         fstl    (%esp)
696         call    builtin_d2l
697         add     $8,%esp
698         ret
699
700
701 asm_getclassvalues_atomic:
702 _crit_restart2:
703         mov     4(%esp),%ecx        /* super */
704         mov     8(%esp),%edx        /* sub */
705 _crit_begin2:
706         mov     offbaseval(%ecx),%eax
707         mov     offdiffval(%ecx),%ecx
708         mov     offbaseval(%edx),%edx
709 _crit_end2:
710         push    %ebx
711         mov     16(%esp),%ebx      /* out */
712         mov     %eax,offcast_super_baseval(%ebx)
713         mov     %ecx,offcast_super_diffval(%ebx)
714         mov     %edx,offcast_sub_baseval(%ebx)
715         pop     %ebx
716         ret
717
718         .data
719
720 asm_criticalsections:
721 #if defined(ENABLE_THREADS)
722 #if 0
723         .long   _crit_begin1
724         .long   _crit_end1
725         .long   _crit_restart1
726 #endif
727         .long   _crit_begin2
728         .long   _crit_end2
729         .long   _crit_restart2
730 #endif
731         .long 0
732
733
734 /* Disable exec-stacks, required for Gentoo ***********************************/
735
736 #if defined(__GCC__) && defined(__ELF__)
737         .section .note.GNU-stack,"",@progbits
738 #endif
739
740
741 /* asm_get_cycle_count *********************************************************
742
743    Get the current time-stamp counter from the CPU.
744
745 *******************************************************************************/
746
747 asm_get_cycle_count:
748         rdtsc
749         ret
750
751
752 /*
753  * These are local overrides for various environment variables in Emacs.
754  * Please do not remove this and leave it at the end of the file, where
755  * Emacs will automagically detect them.
756  * ---------------------------------------------------------------------
757  * Local variables:
758  * mode: asm
759  * indent-tabs-mode: t
760  * c-basic-offset: 4
761  * tab-width: 4
762  * End:
763  * vim:noexpandtab:sw=4:ts=4:
764  */