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