* src/vm/utf8.c (utf_java_lang_AbstractMethodError): Added.
[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 5053 2006-06-28 19:11:20Z 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         call    exceptions_new_abstractmethoderror
486                                             /* exception pointer is return value  */
487         pop     xpc                         /* get exception address              */
488         sub     $2,xpc                      /* exception address is ra - 2        */
489         jmp     L_asm_handle_exception
490
491
492 /* asm_wrapper_patcher *********************************************************
493
494    XXX
495
496    Stack layout:
497      24   return address
498      20   REG_ITMP3
499      16   pointer to virtual java_objectheader
500      12   last byte of machine code (xmcode)
501       8   machine code (which is patched back later)
502       4   unresolved field reference
503       0   patcher function pointer to call
504
505 *******************************************************************************/
506
507 asm_wrapper_patcher:
508         sub     $((2+4)*4+sizestackframeinfo),sp /* create stack frame            */
509
510         mov     itmp1,(0+4)*4(sp)           /* save itmp1 and itmp2               */
511         mov     itmp2,(1+4)*4(sp)           /* may be used by some instructions   */
512
513         mov     sp,itmp1                    /* create stackframe info             */
514         add     $((2+4)*4),itmp1
515         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
516         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
517         mov     sp,itmp2
518         add     $((7+2+4)*4+sizestackframeinfo),itmp2
519         mov     itmp2,2*4(sp)               /* pass Java sp                       */
520         mov     ((6+2+4)*4+sizestackframeinfo)(sp),itmp3
521         mov     itmp3,3*4(sp)               /* pass ra to java function           */
522         call    stacktrace_create_inline_stackframeinfo
523
524         mov     sp,itmp1                    /* pass stack pointer                 */
525         add     $((1+2+4)*4+sizestackframeinfo),itmp1  /* skip function pointer   */
526         mov     itmp1,0*4(sp)
527         mov     (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer    */
528         call    *itmp1                      /* call the patcher function          */
529         mov     v0,1*4(sp)                  /* save return value                  */
530
531         mov     sp,itmp1                    /* remove stackframe info             */
532         add     $((2+4)*4),itmp1
533         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
534         call    stacktrace_remove_stackframeinfo
535
536         mov     1*4(sp),itmp3               /* restore return value               */
537         test    itmp3,itmp3                 /* exception thrown?                  */
538         jz      L_asm_wrapper_patcher_exception
539
540         mov     (0+4)*4(sp),itmp1           /* restore itmp1 and itmp2            */
541         mov     (1+4)*4(sp),itmp2           /* may be used by some instructions   */
542         mov     ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
543         add     $((6+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
544
545         ret                                 /* call new patched code              */
546
547 L_asm_wrapper_patcher_exception:
548         add     $((6+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
549
550 #if defined(ENABLE_THREADS)
551         call    builtin_asm_get_exceptionptrptr
552         mov     v0,itmp2
553 #else
554         lea     _exceptionptr,itmp2
555 #endif
556         mov     (itmp2),xptr                /* get the exception pointer          */
557         movl    $0,(itmp2)                  /* clear the exception pointer        */
558
559         pop     xpc                         /* get and remove return address      */
560         jmp     L_asm_handle_exception
561
562
563 /* asm_replacement_out *********************************************************
564
565    This code is jumped to from the replacement-out stubs that are executed
566    when a thread reaches an activated replacement point.
567
568    The purpose of asm_replacement_out is to read out the parts of the
569    execution state that cannot be accessed from C code, store this state,
570    and then call the C function replace_me.
571
572    Stack layout:
573       4                 start of stack inside method to replace
574       0   rplpoint *    info on the replacement point that was reached
575
576 *******************************************************************************/
577
578 /* some room to accomodate changes of the stack frame size during replacement */
579         /* XXX we should find a cleaner solution here */
580 #define REPLACEMENT_ROOM  512
581
582 asm_replacement_out:
583     /* create stack frame */
584         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
585
586         /* save registers in execution state */
587         mov     %eax,(EAX*8+offes_intregs)(sp)
588         mov     %ebx,(EBX*8+offes_intregs)(sp)
589         mov     %ecx,(ECX*8+offes_intregs)(sp)
590         mov     %edx,(EDX*8+offes_intregs)(sp)
591         mov     %esi,(ESI*8+offes_intregs)(sp)
592         mov     %edi,(EDI*8+offes_intregs)(sp)
593         mov     %ebp,(EBP*8+offes_intregs)(sp)
594         movl    $0  ,(ESP*8+offes_intregs)(sp) /* not used */
595
596 #ifndef NDEBUG
597         /* clear high 32bit */
598         movl    $0,(4+0*8+offes_intregs)(sp)
599         movl    $0,(4+1*8+offes_intregs)(sp)
600         movl    $0,(4+2*8+offes_intregs)(sp)
601         movl    $0,(4+3*8+offes_intregs)(sp)
602         movl    $0,(4+4*8+offes_intregs)(sp)
603         movl    $0,(4+5*8+offes_intregs)(sp)
604         movl    $0,(4+6*8+offes_intregs)(sp)
605         movl    $0,(4+7*8+offes_intregs)(sp)
606 #endif
607
608         /* calculate sp of method */
609         mov     sp,itmp1
610         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
611         mov     itmp1,(offes_sp)(sp)
612
613         /* pv must be looked up via AVL tree */
614         movl    $0,(offes_pv)(sp)
615
616         /* call replace_me */
617         mov     -4(itmp1),itmp1             /* rplpoint *                         */
618     push    sp                          /* arg1: execution state              */
619     push    itmp1                       /* arg0: replacement point            */
620     call    replace_me                  /* call C function replace_me         */
621     call    abort                       /* NEVER REACHED                      */
622
623 /* asm_replacement_in **********************************************************
624
625    This code writes the given execution state and jumps to the replacement
626    code.
627
628    This function never returns!
629
630    C prototype:
631       void asm_replacement_in(executionstate *es);
632
633 *******************************************************************************/
634
635 asm_replacement_in:
636         mov     4(sp),%ebp                  /* executionstate *es                 */
637
638         /* set new sp */
639         mov     (offes_sp)(%ebp),%esp
640         
641         /* store address of new code */
642         push    (offes_pc)(%ebp)
643         
644         /* copy registers from execution state */
645         mov     (EAX*8+offes_intregs)(%ebp),%eax
646         mov     (EBX*8+offes_intregs)(%ebp),%ebx
647         mov     (ECX*8+offes_intregs)(%ebp),%ecx
648         mov     (EDX*8+offes_intregs)(%ebp),%edx
649         mov     (ESI*8+offes_intregs)(%ebp),%esi
650         mov     (EDI*8+offes_intregs)(%ebp),%edi
651
652         mov     (EBP*8+offes_intregs)(%ebp),%ebp
653
654         /* jump to new code */
655         ret
656
657 /************************ function asm_builtin_x2x *****************************
658 *                                                                              *
659 *   Wrapper functions for corner cases                                         *
660 *                                                                              *
661 *******************************************************************************/
662
663 asm_builtin_f2i:
664         sub     $4,%esp
665         fsts    (%esp)
666         call    builtin_f2i
667         add     $4,%esp
668         ret
669
670 asm_builtin_d2i:
671         sub     $8,%esp
672         fstl    (%esp)
673         call    builtin_d2i
674         add     $8,%esp
675         ret
676
677 asm_builtin_f2l:
678         sub     $4,%esp
679         fsts    (%esp)
680         call    builtin_f2l
681         add     $4,%esp
682         ret
683
684 asm_builtin_d2l:
685         sub     $8,%esp
686         fstl    (%esp)
687         call    builtin_d2l
688         add     $8,%esp
689         ret
690
691
692 asm_getclassvalues_atomic:
693 _crit_restart2:
694         mov     4(%esp),%ecx        /* super */
695         mov     8(%esp),%edx        /* sub */
696 _crit_begin2:
697         mov     offbaseval(%ecx),%eax
698         mov     offdiffval(%ecx),%ecx
699         mov     offbaseval(%edx),%edx
700 _crit_end2:
701         push    %ebx
702         mov     16(%esp),%ebx      /* out */
703         mov     %eax,offcast_super_baseval(%ebx)
704         mov     %ecx,offcast_super_diffval(%ebx)
705         mov     %edx,offcast_sub_baseval(%ebx)
706         pop     %ebx
707         ret
708
709         .data
710
711 asm_criticalsections:
712 #if defined(ENABLE_THREADS)
713 #if 0
714         .long   _crit_begin1
715         .long   _crit_end1
716         .long   _crit_restart1
717 #endif
718         .long   _crit_begin2
719         .long   _crit_end2
720         .long   _crit_restart2
721 #endif
722         .long 0
723
724
725 /* Disable exec-stacks, required for Gentoo ***********************************/
726
727 #if defined(__GCC__) && defined(__ELF__)
728         .section .note.GNU-stack,"",@progbits
729 #endif
730
731
732 /* asm_get_cycle_count *********************************************************
733
734    Get the current time-stamp counter from the CPU.
735
736 *******************************************************************************/
737
738 asm_get_cycle_count:
739         rdtsc
740         ret
741
742
743 /*
744  * These are local overrides for various environment variables in Emacs.
745  * Please do not remove this and leave it at the end of the file, where
746  * Emacs will automagically detect them.
747  * ---------------------------------------------------------------------
748  * Local variables:
749  * mode: asm
750  * indent-tabs-mode: t
751  * c-basic-offset: 4
752  * tab-width: 4
753  * End:
754  * vim:noexpandtab:sw=4:ts=4:
755  */