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