src/vm/cycles-stats.h: Switched from asm_get_cycle_count to md_get_cycle_count.
[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, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include "md-asm.h"
29
30 #include "vm/jit/i386/arch.h"
31 #include "vm/jit/i386/md-abi.h"
32
33 #include "vm/jit/abi-asm.h"
34 #include "vm/jit/methodheader.h"
35
36
37         .text
38
39
40 /* export functions ***********************************************************/
41
42         .globl asm_md_init
43
44         .globl asm_vm_call_method
45         .globl asm_vm_call_method_int
46         .globl asm_vm_call_method_long
47         .globl asm_vm_call_method_float
48         .globl asm_vm_call_method_double
49         .globl asm_vm_call_method_exception_handler
50         .globl asm_vm_call_method_end
51
52         .globl asm_handle_nat_exception
53         .globl asm_handle_exception
54
55         .globl asm_abstractmethoderror
56
57         .globl asm_builtin_f2i
58         .globl asm_builtin_f2l
59         .globl asm_builtin_d2i
60         .globl asm_builtin_d2l
61
62         .globl asm_compare_and_swap
63         .globl asm_memory_barrier
64
65 #if defined(ENABLE_ESCAPE_CHECK)
66         .globl asm_escape_check
67 #endif
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                           /* fltsave                            */
114         .long   0                           /* intsave                            */
115         .long   0                           /* isleaf                             */
116         .long   0                           /* frame size                         */
117         .long   0                           /* codeinfo pointer                   */
118
119 asm_vm_call_method:
120 asm_vm_call_method_int:
121 asm_vm_call_method_long:
122 asm_vm_call_method_float:
123 asm_vm_call_method_double:
124         push    bp
125         mov     sp,bp                       /* save stack pointer                 */
126         sub     $(4*4),sp                   /* create stackframe                  */
127         and     $0xfffffff0,sp              /* align stack to 16-byte             */
128
129         mov     t0,0*4(sp)                  /* save registers                     */
130         mov     s1,1*4(sp)
131         mov     s2,2*4(sp)
132
133         mov     sp,s1                       /* save stack pointer                 */
134
135         mov     3*4(bp),t0                  /* address of data structure          */
136         mov     4*4(bp),itmp1               /* number of stack arguments          */
137
138         cmp     $0,itmp1
139         je      L_asm_vm_call_method_stack_copy_done
140
141         mov     itmp1,itmp2
142         add     $1,itmp2                    /* keep stack 16-byte aligned         */
143         and     $0xfffffffe,itmp2
144         shl     $3,itmp2                    /* calculate stack size               */
145         sub     itmp2,sp                    /* create stack frame                 */
146         mov     sp,itmp2                    /* temporary stack pointer            */
147
148 L_asm_vm_call_method_stack_copy_loop:
149         mov     0(t0),itmp3                 /* load argument                      */
150         mov     itmp3,0(itmp2)              /* store argument on stack            */
151         mov     4(t0),itmp3
152         mov     itmp3,4(itmp2)
153
154         sub     $1,itmp1                    /* subtract 1 argument                */
155         add     $8,t0                       /* set address of next argument       */
156         add     $8,itmp2                    /* increase SP                        */
157
158         cmp     $0,itmp1
159         jg      L_asm_vm_call_method_stack_copy_loop
160
161 L_asm_vm_call_method_stack_copy_done:
162         lea     (2*4-256)(bp),mptr          /* We subtract 256 to force the next  */
163                                             /* move instruction to have a 32-bit  */
164                                             /* offset.                            */
165
166         mov     (0*4+256)(mptr),itmp3       /* method call as in Java             */
167         call    *itmp3                      /* call JIT compiler                  */
168
169 L_asm_vm_call_method_return:
170         mov     s1,sp                       /* restore stackpointer               */
171
172         mov     0*4(sp),t0                  /* restore registers                  */
173         mov     1*4(sp),s1
174         mov     2*4(sp),s2
175
176         leave
177         ret
178
179 asm_vm_call_method_exception_handler:
180         push    xptr                        /* pass exception pointer             */
181         call    builtin_throw_exception
182         add     $4,sp
183 asm_vm_call_method_end:
184         jmp     L_asm_vm_call_method_return
185
186
187 /* asm_handle_exception ********************************************************
188 *                                                                              *
189 *   This function handles an exception. It does not use the usual calling      *
190 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
191 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
192 *   the local exception table for a handler. If no one is found, it unwinds    *
193 *   stacks and continues searching the callers.                                *
194 *                                                                              *
195 *******************************************************************************/
196
197 asm_handle_nat_exception:
198         add     $4,sp                       /* clear return address of native stub*/
199                 
200 asm_handle_exception:
201 L_asm_handle_exception:                 /* required for PIC code              */
202         sub     $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned         */
203
204         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
205         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
206
207         mov     $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
208         mov     $1,t0                       /* set maybe-leaf flag                */
209
210 L_asm_handle_exception_stack_loop:
211         sub     $(12*4),sp                  /* keep stack 16-byte aligned         */
212         mov     xptr,4*4(sp)                /* save exception pointer             */
213         mov     xpc,5*4(sp)                 /* save exception pc                  */
214         add     sp,itmp3                    /* calculate Java sp into a3...       */
215         add     $(12*4),itmp3
216         mov     itmp3,7*4(sp)               /* ...and save it                     */
217         mov     t0,8*4(sp)                  /* save maybe-leaf flag               */
218
219         mov     xpc,0*4(sp)                 /* pass exception pc                  */
220         call    methodtree_find
221         mov     v0,6*4(sp)                  /* save data segment pointer          */
222
223         mov     4*4(sp),itmp3               /* pass exception pointer             */
224         mov     itmp3,0*4(sp)
225         mov     5*4(sp),itmp3               /* pass exception pc                  */
226         mov     itmp3,1*4(sp)
227         mov     v0,2*4(sp)                  /* pass data segment pointer          */
228         mov     7*4(sp),itmp3               /* pass Java stack pointer            */
229         mov     itmp3,3*4(sp)
230         call    exceptions_handle_exception
231
232         test    v0,v0
233         jz      L_asm_handle_exception_not_catched
234
235         mov     v0,xpc                      /* move handlerpc into xpc            */
236         mov     4*4(sp),xptr                /* restore exception pointer          */
237         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
238         add     $(12*4),sp                  /* free stackframe                    */
239
240         test    t0,t0                       /* test for maybe-leaf flag           */
241         jz      L_asm_handle_exception_no_leaf
242
243         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
244         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
245
246         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
247
248 L_asm_handle_exception_no_leaf:
249         jmp     *xpc                        /* jump to exception handler          */
250
251 L_asm_handle_exception_not_catched:
252         mov     4*4(sp),xptr                /* restore exception pointer          */
253         mov     6*4(sp),itmp3               /* restore data segment pointer       */
254         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
255         add     $(12*4),sp                  /* free stackframe                    */
256
257         test    t0,t0
258         jz      L_asm_handle_exception_no_leaf_stack
259
260         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
261         xor     t0,t0                       /* clear the maybe-leaf flag          */
262
263 L_asm_handle_exception_no_leaf_stack:
264         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
265         add     sp,itmp2                    /* pointer to save area               */
266
267         push    xptr                        /* we are out of registers            */
268
269         mov     IntSave(itmp3),itmp1        /* itmp1 = saved int register count   */
270         test    itmp1,itmp1
271         je      noint
272
273         cmp     $1,itmp1
274         je      int1
275         cmp     $2,itmp1
276         je      int2
277
278         mov     -4-3*8(itmp2),s0
279 int2:   
280         mov     -4-2*8(itmp2),s1
281 int1:   
282         mov     -4-1*8(itmp2),s2
283
284         shl     $2,itmp1                    /* multiply by 4 bytes                */
285         sub     itmp1,itmp2
286                 
287 noint:
288 #if 0
289         mov     FltSave(itmp3),itmp1        /* itmp1 = saved flt register count   */
290         test    itmp1,itmp1
291         je      noflt
292
293         cmp     $1,itmp1
294         je      flt1
295         cmp     $2,itmp1
296         je      flt2
297         cmp     $3,itmp1
298         je      flt3
299                 
300         fldl    -4*8(itmp2)
301         fstp    %st(1)
302 flt3:
303         fldl    -3*8(itmp2)
304         fstp    %st(2)
305 flt2:
306         fldl    -2*8(itmp2)
307         fstp    %st(3)
308 flt1:
309         fldl    -1*8(itmp2)
310         fstp    %st(4)
311                 
312 noflt:
313 #endif
314         pop     xptr                        /* restore exception pointer          */
315         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
316         add     itmp2,sp                    /* unwind stack                       */
317
318         pop     xpc                         /* the new xpc is return address      */
319         sub     $2,xpc                      /* subtract 2-bytes for call          */
320
321         xor     itmp3,itmp3                 /* prepare a3 for handle_exception    */
322
323         jmp     L_asm_handle_exception_stack_loop
324                 
325
326 /* asm_abstractmethoderror *****************************************************
327
328    Creates and throws an AbstractMethodError.
329
330 *******************************************************************************/
331
332 asm_abstractmethoderror:
333         sub     $(3*4),sp                   /* keep stack 16-byte aligned         */
334         mov     sp,itmp1                    /* pass java sp                       */
335         add     $((1+3)*4),itmp1
336         mov     itmp1,0*4(sp)
337         mov     3*4(sp),itmp2               /* pass exception address             */
338         sub     $2,itmp2
339         mov     itmp2,1*4(sp)
340         call    exceptions_asm_new_abstractmethoderror
341                                             /* exception pointer is return value  */
342         add     $(3*4),sp                   /* remove stack frame                 */
343
344         pop     xpc                         /* get exception address              */
345         sub     $2,xpc                      /* exception address is ra - 2        */
346         jmp     L_asm_handle_exception
347
348
349 /************************ function asm_builtin_x2x *****************************
350 *                                                                              *
351 *   Wrapper functions for corner cases                                         *
352 *                                                                              *
353 *******************************************************************************/
354
355 asm_builtin_f2i:
356         sub     $(3*4),%esp
357         fsts    (%esp)
358         call    builtin_f2i
359         add     $(3*4),%esp
360         ret
361
362 asm_builtin_d2i:
363         sub     $(3*4),%esp
364         fstl    (%esp)
365         call    builtin_d2i
366         add     $(3*4),%esp
367         ret
368
369 asm_builtin_f2l:
370         sub     $(3*4),%esp
371         fsts    (%esp)
372         call    builtin_f2l
373         add     $(3*4),%esp
374         ret
375
376 asm_builtin_d2l:
377         sub     $(3*4),%esp
378         fstl    (%esp)
379         call    builtin_d2l
380         add     $(3*4),%esp
381         ret
382
383
384 /* asm_compare_and_swap ********************************************************
385
386    Does an atomic compare and swap.  Required for the lock
387    implementation.
388
389    Atomically do the following: Check if the location still contains
390    `oldval`. If so, replace it by `newval` and return `oldval`.
391
392    RETURN VALUE:
393        the old value at *p
394
395    long compare_and_swap(volatile long *p, long oldval, long newval);
396
397 *******************************************************************************/
398
399 asm_compare_and_swap:
400         mov     1*4(sp),%ecx            /* load p into a register                 */
401         mov     2*4(sp),%eax            /* load oldval into return register       */
402         mov     3*4(sp),%edx            /* load newval into a register            */
403         lock; cmpxchgl %edx,0(%ecx)
404         ret
405
406
407 /* asm_memory_barrier **********************************************************
408
409    A memory barrier for the Java Memory Model.
410
411 *******************************************************************************/
412
413 asm_memory_barrier:
414         lock; add $0,0(sp)
415         ret
416
417
418 #if defined(ENABLE_ESCAPE_CHECK)
419 asm_escape_check:
420         sub     $24,%esp
421
422         mov     t0, 4(%esp)
423         mov     itmp1, 8(%esp)
424         mov     itmp2, 12(%esp)
425         mov     itmp3, 16(%esp)
426
427         mov     28(%esp), itmp1
428         mov     itmp1, (%esp)
429
430         call    escape_analysis_escape_check
431
432         mov     4(%esp), t0
433         mov     8(%esp), itmp1
434         mov     12(%esp), itmp2
435         mov     16(%esp), itmp3
436
437         add     $24,sp
438         ret
439 #endif
440
441
442 /* disable exec-stacks ********************************************************/
443
444 #if defined(__linux__) && defined(__ELF__)
445         .section .note.GNU-stack,"",%progbits
446 #endif
447
448 /*
449  * These are local overrides for various environment variables in Emacs.
450  * Please do not remove this and leave it at the end of the file, where
451  * Emacs will automagically detect them.
452  * ---------------------------------------------------------------------
453  * Local variables:
454  * mode: asm
455  * indent-tabs-mode: t
456  * c-basic-offset: 4
457  * tab-width: 4
458  * End:
459  * vim:noexpandtab:sw=4:ts=4:
460  */