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