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