* src/vm/jit/i386/asmpart.S (asm_replacement_in, asm_replacement_out): Removed
[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, 2007 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 */
26
27
28 #include "config.h"
29
30 #include "md-asm.h"
31
32 #include "vm/jit/i386/arch.h"
33 #include "vm/jit/i386/md-abi.h"
34
35 #include "vm/jit/abi-asm.h"
36 #include "vm/jit/methodheader.h"
37
38
39         .text
40
41
42 /* export functions ***********************************************************/
43
44         .globl asm_md_init
45
46         .globl asm_vm_call_method
47         .globl asm_vm_call_method_int
48         .globl asm_vm_call_method_long
49         .globl asm_vm_call_method_float
50         .globl asm_vm_call_method_double
51         .globl asm_vm_call_method_exception_handler
52         .globl asm_vm_call_method_end
53
54         .globl asm_call_jit_compiler
55         .globl asm_handle_nat_exception
56         .globl asm_handle_exception
57
58         .globl asm_abstractmethoderror
59
60         .globl asm_builtin_f2i
61         .globl asm_builtin_f2l
62         .globl asm_builtin_d2i
63         .globl asm_builtin_d2l
64
65         .globl asm_compare_and_swap
66         .globl asm_memory_barrier
67
68         .globl asm_get_cycle_count
69
70
71 /* asm_md_init *****************************************************************
72
73    Initialize machine dependent stuff.
74
75    See: http://www.srware.com/linux_numerics.txt
76
77    This puts the X86 FPU in 64-bit precision mode.  The default under
78    Linux is to use 80-bit mode, which produces subtle differences from
79    FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
80    64-bit mode, 299 in 80-bit mode.
81
82    Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
83
84 *******************************************************************************/
85
86 asm_md_init:
87         sub     $4,sp                       /* allocate space for the FPU state   */
88         fnstcw  (sp)                        /* get the FPU state                  */
89         mov     (sp),%eax
90         and     $0xfcff,%ax                 /* remove the extended mode flag      */
91         or      $0x0200,%ax                 /* put the double mode flag           */
92         mov     %eax,(sp)                   /* store new FPU state                */
93         fldcw   (sp)                        /* setup new FPU state                */
94         add     $4,sp
95         ret
96
97
98 /********************* function asm_calljavafunction ***************************
99 *                                                                              *
100 *   This function calls a Java-method (which possibly needs compilation)       *
101 *   with up to 4 address parameters.                                           *
102 *                                                                              *
103 *   This functions calls the JIT-compiler which eventually translates the      *
104 *   method into machine code.                                                  *
105 *                                                                              *
106 *   C-prototype:                                                               *
107 *    javaobject_header *asm_vm_call_method(methodinfo *m,                      *
108 *         u4 count, u4 size, void *callblock);                                 *
109 *                                                                              *
110 *******************************************************************************/
111
112         .align  8
113
114         .long   0                           /* catch type all                     */
115         .long   0                           /* handler pc                         */
116         .long   0                           /* end pc                             */
117         .long   0                           /* start pc                           */
118         .long   1                           /* extable size                       */
119         .long   0                           /* line number table start            */
120         .long   0                           /* line number table size             */
121         .long   0                           /* fltsave                            */
122         .long   0                           /* intsave                            */
123         .long   0                           /* isleaf                             */
124         .long   0                           /* IsSync                             */
125         .long   0                           /* frame size                         */
126         .long   0                           /* codeinfo pointer                   */
127
128 asm_vm_call_method:
129 asm_vm_call_method_int:
130 asm_vm_call_method_long:
131 asm_vm_call_method_float:
132 asm_vm_call_method_double:
133         push    bp
134         mov     sp,bp                       /* save stackptr                      */
135         sub     $(4*4),sp                   /* create stackframe                  */
136         and     $0xfffffff0,sp              /* align stack to 16-byte             */
137
138         mov     t0,0*4(sp)                  /* save registers                     */
139         mov     s1,1*4(sp)
140         mov     s2,2*4(sp)
141
142         mov     sp,s1                       /* save stack pointer                 */
143
144         mov     3*4(bp),t0                  /* address of data structure          */
145         mov     4*4(bp),itmp1               /* number of stack arguments          */
146
147         cmp     $0,itmp1
148         je      L_asm_vm_call_method_stack_copy_done
149
150         mov     itmp1,itmp2
151         add     $1,itmp2                    /* keep stack 16-byte aligned         */
152         and     $0xfffffffe,itmp2
153         shl     $3,itmp2                    /* calculate stack size               */
154         sub     itmp2,sp                    /* create stack frame                 */
155         mov     sp,itmp2                    /* temporary stack pointer            */
156
157 L_asm_vm_call_method_stack_copy_loop:
158         mov     0(t0),itmp3                 /* load argument                      */
159         mov     itmp3,0(itmp2)              /* store argument on stack            */
160         mov     4(t0),itmp3
161         mov     itmp3,4(itmp2)
162
163         sub     $1,itmp1                    /* subtract 1 argument                */
164         add     $8,t0                       /* set address of next argument       */
165         add     $8,itmp2                    /* increase SP                        */
166
167         cmp     $0,itmp1
168         jg      L_asm_vm_call_method_stack_copy_loop
169
170 L_asm_vm_call_method_stack_copy_done:
171         lea     (2*4-256)(bp),mptr          /* We subtract 256 to force the next  */
172                                             /* move instruction to have a 32-bit  */
173                                             /* offset.                            */
174
175         mov     (0*4+256)(mptr),itmp3       /* method call as in Java             */
176         call    *itmp3                      /* call JIT compiler                  */
177
178 L_asm_vm_call_method_return:
179         mov     s1,sp                       /* restore stackpointer               */
180
181         mov     0*4(sp),t0                  /* restore registers                  */
182         mov     1*4(sp),s1
183         mov     2*4(sp),s2
184
185         leave
186         ret
187
188 asm_vm_call_method_exception_handler:
189         push    xptr                        /* pass exception pointer             */
190         call    builtin_throw_exception
191         add     $4,sp
192 asm_vm_call_method_end:
193         jmp     L_asm_vm_call_method_return
194
195
196 /* asm_call_jit_compiler *******************************************************
197
198    Invokes the compiler for untranslated JavaVM methods.
199
200    Register R0 contains a pointer to the method info structure (prepared
201    by createcompilerstub). Using the return address in R26 and the
202    offset in the LDA instruction or using the value in methodptr R28 the
203    patching address for storing the method address can be computed:
204
205    Method address was either loaded using
206
207    i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special
208    i386_call_reg(REG_ITMP2)
209
210    or
211
212    i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface
213    i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
214    i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
215        sizeof(methodptr) * m->vftblindex, REG_ITMP1)
216    i386_call_reg(REG_ITMP1)
217
218    In the static case the method pointer can be computed using the
219    return address and the lda function following the jmp instruction.
220
221 *******************************************************************************/
222
223 asm_call_jit_compiler:
224 L_asm_call_jit_compiler:                /* required for PIC code              */
225         sub     $(4*4),sp                   /* keep stack 16-byte aligned         */
226
227         mov     itmp1,0*4(sp)               /* pass methodinfo pointer            */
228         mov     mptr,1*4(sp)                /* pass method pointer                */
229         mov     sp,itmp2                    /* pass java sp                       */
230         add     $((1+4)*4),itmp2
231         mov     itmp2,2*4(sp)
232         mov     4*4(sp),itmp3               /* pass java ra                       */
233         mov     itmp3,3*4(sp)
234         call    jit_asm_compile
235
236         add     $(4*4),sp                   /* remove stack frame                 */
237
238         test    v0,v0                       /* check for exception                */
239         je      L_asm_call_jit_compiler_exception
240
241         jmp             *v0                         /* ...and now call the new method     */
242
243 L_asm_call_jit_compiler_exception:
244         call    exceptions_get_and_clear_exception
245                                             /* v0 == xptr                         */
246         pop     xpc                         /* get return address                 */
247         sub     $2,xpc                      /* faulting address is ra - 2         */
248         jmp     L_asm_handle_exception
249
250
251 /* asm_handle_exception ********************************************************
252 *                                                                              *
253 *   This function handles an exception. It does not use the usual calling      *
254 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
255 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
256 *   the local exception table for a handler. If no one is found, it unwinds    *
257 *   stacks and continues searching the callers.                                *
258 *                                                                              *
259 *******************************************************************************/
260
261 asm_handle_nat_exception:
262         add     $4,sp                       /* clear return address of native stub*/
263                 
264 asm_handle_exception:
265 L_asm_handle_exception:                 /* required for PIC code              */
266         sub     $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned         */
267
268         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
269         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
270
271         mov     $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
272         mov     $1,t0                       /* set maybe-leaf flag                */
273
274 L_asm_handle_exception_stack_loop:
275         sub     $(12*4),sp                  /* keep stack 16-byte aligned         */
276         mov     xptr,4*4(sp)                /* save exception pointer             */
277         mov     xpc,5*4(sp)                 /* save exception pc                  */
278         add     sp,itmp3                    /* calculate Java sp into a3...       */
279         add     $(12*4),itmp3
280         mov     itmp3,7*4(sp)               /* ...and save it                     */
281         mov     t0,8*4(sp)                  /* save maybe-leaf flag               */
282
283         mov     xpc,0*4(sp)                 /* pass exception pc                  */
284         call    codegen_get_pv_from_pc
285         mov     v0,6*4(sp)                  /* save data segment pointer          */
286
287         mov     4*4(sp),itmp3               /* pass exception pointer             */
288         mov     itmp3,0*4(sp)
289         mov     5*4(sp),itmp3               /* pass exception pc                  */
290         mov     itmp3,1*4(sp)
291         mov     v0,2*4(sp)                  /* pass data segment pointer          */
292         mov     7*4(sp),itmp3               /* pass Java stack pointer            */
293         mov     itmp3,3*4(sp)
294         call    exceptions_handle_exception
295
296         test    v0,v0
297         jz      L_asm_handle_exception_not_catched
298
299         mov     v0,xpc                      /* move handlerpc into xpc            */
300         mov     4*4(sp),xptr                /* restore exception pointer          */
301         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
302         add     $(12*4),sp                  /* free stackframe                    */
303
304         test    t0,t0                       /* test for maybe-leaf flag           */
305         jz      L_asm_handle_exception_no_leaf
306
307         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
308         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
309
310         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
311
312 L_asm_handle_exception_no_leaf:
313         jmp     *xpc                        /* jump to exception handler          */
314
315 L_asm_handle_exception_not_catched:
316         mov     4*4(sp),xptr                /* restore exception pointer          */
317         mov     6*4(sp),itmp3               /* restore data segment pointer       */
318         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
319         add     $(12*4),sp                  /* free stackframe                    */
320
321         test    t0,t0
322         jz      L_asm_handle_exception_no_leaf_stack
323
324         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
325         xor     t0,t0                       /* clear the maybe-leaf flag          */
326
327 L_asm_handle_exception_no_leaf_stack:
328         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
329         add     sp,itmp2                    /* pointer to save area               */
330
331         push    xptr                        /* we are out of registers            */
332
333         mov     IntSave(itmp3),itmp1        /* itmp1 = saved int register count   */
334         test    itmp1,itmp1
335         je      noint
336
337         cmp     $1,itmp1
338         je      int1
339         cmp     $2,itmp1
340         je      int2
341
342         mov     -3*8(itmp2),s0
343 int2:   
344         mov     -2*8(itmp2),s1
345 int1:   
346         mov     -1*8(itmp2),s2
347
348         shl     $2,itmp1                    /* multiply by 4 bytes                */
349         sub     itmp1,itmp2
350                 
351 noint:
352 #if 0
353         mov     FltSave(itmp3),itmp1        /* itmp1 = saved flt register count   */
354         test    itmp1,itmp1
355         je      noflt
356
357         cmp     $1,itmp1
358         je      flt1
359         cmp     $2,itmp1
360         je      flt2
361         cmp     $3,itmp1
362         je      flt3
363                 
364         fldl    -4*8(itmp2)
365         fstp    %st(1)
366 flt3:
367         fldl    -3*8(itmp2)
368         fstp    %st(2)
369 flt2:
370         fldl    -2*8(itmp2)
371         fstp    %st(3)
372 flt1:
373         fldl    -1*8(itmp2)
374         fstp    %st(4)
375                 
376 noflt:
377 #endif
378         pop     xptr                        /* restore exception pointer          */
379         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
380         add     itmp2,sp                    /* unwind stack                       */
381
382         pop     xpc                         /* the new xpc is return address      */
383         sub     $2,xpc                      /* subtract 2-bytes for call          */
384
385         xor     itmp3,itmp3                 /* prepare a3 for handle_exception    */
386
387         jmp     L_asm_handle_exception_stack_loop
388                 
389
390 /* asm_abstractmethoderror *****************************************************
391
392    Creates and throws an AbstractMethodError.
393
394 *******************************************************************************/
395
396 asm_abstractmethoderror:
397         sub     $(3*4),sp                   /* keep stack 16-byte aligned         */
398         mov     sp,itmp1                    /* pass java sp                       */
399         add     $((1+3)*4),itmp1
400         mov     itmp1,0*4(sp)
401         mov     3*4(sp),itmp2               /* pass exception address             */
402         sub     $2,itmp2
403         mov     itmp2,1*4(sp)
404         call    exceptions_asm_new_abstractmethoderror
405                                             /* exception pointer is return value  */
406         add     $(3*4),sp                   /* remove stack frame                 */
407
408         pop     xpc                         /* get exception address              */
409         sub     $2,xpc                      /* exception address is ra - 2        */
410         jmp     L_asm_handle_exception
411
412
413 /************************ function asm_builtin_x2x *****************************
414 *                                                                              *
415 *   Wrapper functions for corner cases                                         *
416 *                                                                              *
417 *******************************************************************************/
418
419 asm_builtin_f2i:
420         sub     $(3*4),%esp
421         fsts    (%esp)
422         call    builtin_f2i
423         add     $(3*4),%esp
424         ret
425
426 asm_builtin_d2i:
427         sub     $(3*4),%esp
428         fstl    (%esp)
429         call    builtin_d2i
430         add     $(3*4),%esp
431         ret
432
433 asm_builtin_f2l:
434         sub     $(3*4),%esp
435         fsts    (%esp)
436         call    builtin_f2l
437         add     $(3*4),%esp
438         ret
439
440 asm_builtin_d2l:
441         sub     $(3*4),%esp
442         fstl    (%esp)
443         call    builtin_d2l
444         add     $(3*4),%esp
445         ret
446
447
448 /* asm_compare_and_swap ********************************************************
449
450    Does an atomic compare and swap.  Required for the lock
451    implementation.
452
453    Atomically do the following: Check if the location still contains
454    `oldval`. If so, replace it by `newval` and return `oldval`.
455
456    RETURN VALUE:
457        the old value at *p
458
459    long compare_and_swap(volatile long *p, long oldval, long newval);
460
461 *******************************************************************************/
462
463 asm_compare_and_swap:
464         mov     1*4(sp),%ecx            /* load p into a register                 */
465         mov     2*4(sp),%eax            /* load oldval into return register       */
466         mov     3*4(sp),%edx            /* load newval into a register            */
467         lock; cmpxchgl %edx,0(%ecx)
468         ret
469
470
471 /* asm_memory_barrier **********************************************************
472
473    A memory barrier for the Java Memory Model.
474
475 *******************************************************************************/
476
477 asm_memory_barrier:
478         lock; add $0,0(sp)
479         ret
480
481                 
482 /* asm_get_cycle_count *********************************************************
483
484    Get the current time-stamp counter from the CPU.
485
486 *******************************************************************************/
487
488 asm_get_cycle_count:
489         rdtsc
490         ret
491
492
493 /* disable exec-stacks ********************************************************/
494
495 #if defined(__linux__) && defined(__ELF__)
496         .section .note.GNU-stack,"",%progbits
497 #endif
498
499
500 /*
501  * These are local overrides for various environment variables in Emacs.
502  * Please do not remove this and leave it at the end of the file, where
503  * Emacs will automagically detect them.
504  * ---------------------------------------------------------------------
505  * Local variables:
506  * mode: asm
507  * indent-tabs-mode: t
508  * c-basic-offset: 4
509  * tab-width: 4
510  * End:
511  * vim:noexpandtab:sw=4:ts=4:
512  */