* src/vm/jit/i386/asmpart.S: Made position independent.
[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 #if defined(ENABLE_PIC_ASM)
181         sub     $12, %esp
182         push    %ebx
183 #endif
184         push    xptr                        /* pass exception pointer             */
185 #if defined(ENABLE_PIC_ASM)
186         call    .GETPC
187         add     $_GLOBAL_OFFSET_TABLE_, %ebx
188         call    builtin_throw_exception@PLT
189         pop     %ebx
190         add     $12, %esp
191 #else
192         call    builtin_throw_exception
193 #endif
194         add     $4,sp
195 asm_vm_call_method_end:
196         jmp     L_asm_vm_call_method_return
197
198
199 /* asm_handle_exception ********************************************************
200 *                                                                              *
201 *   This function handles an exception. It does not use the usual calling      *
202 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
203 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
204 *   the local exception table for a handler. If no one is found, it unwinds    *
205 *   stacks and continues searching the callers.                                *
206 *                                                                              *
207 *******************************************************************************/
208
209 asm_handle_nat_exception:
210         add     $4,sp                       /* clear return address of native stub*/
211                 
212 asm_handle_exception:
213 L_asm_handle_exception:                 /* required for PIC code              */
214         sub     $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned         */
215
216         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
217         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
218
219         mov     $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
220         mov     $1,t0                       /* set maybe-leaf flag                */
221
222 L_asm_handle_exception_stack_loop:
223         sub     $(12*4),sp                  /* keep stack 16-byte aligned         */
224         mov     xptr,4*4(sp)                /* save exception pointer             */
225         mov     xpc,5*4(sp)                 /* save exception pc                  */
226         add     sp,itmp3                    /* calculate Java sp into a3...       */
227         add     $(12*4),itmp3
228         mov     itmp3,7*4(sp)               /* ...and save it                     */
229         mov     t0,8*4(sp)                  /* save maybe-leaf flag               */
230
231         mov     xpc,0*4(sp)                 /* pass exception pc                  */
232 #if defined(ENABLE_PIC_ASM)
233         call    .GETPC
234         add     $_GLOBAL_OFFSET_TABLE_, %ebx
235         call    methodtree_find@PLT
236 #else
237         call    methodtree_find
238 #endif
239         mov     v0,6*4(sp)                  /* save data segment pointer          */
240
241         mov     4*4(sp),itmp3               /* pass exception pointer             */
242         mov     itmp3,0*4(sp)
243         mov     5*4(sp),itmp3               /* pass exception pc                  */
244         mov     itmp3,1*4(sp)
245         mov     v0,2*4(sp)                  /* pass data segment pointer          */
246         mov     7*4(sp),itmp3               /* pass Java stack pointer            */
247         mov     itmp3,3*4(sp)
248 #if defined(ENABLE_PIC_ASM)
249         /* GOT still in %ebx */
250         call    exceptions_handle_exception@PLT
251 #else
252         call    exceptions_handle_exception
253 #endif
254
255         test    v0,v0
256         jz      L_asm_handle_exception_not_catched
257
258         mov     v0,xpc                      /* move handlerpc into xpc            */
259         mov     4*4(sp),xptr                /* restore exception pointer          */
260         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
261         add     $(12*4),sp                  /* free stackframe                    */
262
263         test    t0,t0                       /* test for maybe-leaf flag           */
264         jz      L_asm_handle_exception_no_leaf
265
266         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
267         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
268
269         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
270
271 L_asm_handle_exception_no_leaf:
272         jmp     *xpc                        /* jump to exception handler          */
273
274 L_asm_handle_exception_not_catched:
275         mov     4*4(sp),xptr                /* restore exception pointer          */
276         mov     6*4(sp),itmp3               /* restore data segment pointer       */
277         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
278         add     $(12*4),sp                  /* free stackframe                    */
279
280         test    t0,t0
281         jz      L_asm_handle_exception_no_leaf_stack
282
283         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
284         xor     t0,t0                       /* clear the maybe-leaf flag          */
285
286 L_asm_handle_exception_no_leaf_stack:
287         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
288         add     sp,itmp2                    /* pointer to save area               */
289
290         push    xptr                        /* we are out of registers            */
291
292         mov     IntSave(itmp3),itmp1        /* itmp1 = saved int register count   */
293         test    itmp1,itmp1
294         je      noint
295
296         cmp     $1,itmp1
297         je      int1
298         cmp     $2,itmp1
299         je      int2
300
301         mov     -4-3*8(itmp2),s0
302 int2:   
303         mov     -4-2*8(itmp2),s1
304 int1:   
305         mov     -4-1*8(itmp2),s2
306
307         shl     $2,itmp1                    /* multiply by 4 bytes                */
308         sub     itmp1,itmp2
309                 
310 noint:
311 #if 0
312         mov     FltSave(itmp3),itmp1        /* itmp1 = saved flt register count   */
313         test    itmp1,itmp1
314         je      noflt
315
316         cmp     $1,itmp1
317         je      flt1
318         cmp     $2,itmp1
319         je      flt2
320         cmp     $3,itmp1
321         je      flt3
322                 
323         fldl    -4*8(itmp2)
324         fstp    %st(1)
325 flt3:
326         fldl    -3*8(itmp2)
327         fstp    %st(2)
328 flt2:
329         fldl    -2*8(itmp2)
330         fstp    %st(3)
331 flt1:
332         fldl    -1*8(itmp2)
333         fstp    %st(4)
334                 
335 noflt:
336 #endif
337         pop     xptr                        /* restore exception pointer          */
338         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
339         add     itmp2,sp                    /* unwind stack                       */
340
341         pop     xpc                         /* the new xpc is return address      */
342         sub     $2,xpc                      /* subtract 2-bytes for call          */
343
344         xor     itmp3,itmp3                 /* prepare a3 for handle_exception    */
345
346         jmp     L_asm_handle_exception_stack_loop
347                 
348
349 /* asm_abstractmethoderror *****************************************************
350
351    Creates and throws an AbstractMethodError.
352
353 *******************************************************************************/
354
355 asm_abstractmethoderror:
356         sub     $(3*4),sp                   /* keep stack 16-byte aligned         */
357         mov     sp,itmp1                    /* pass java sp                       */
358         add     $((1+3)*4),itmp1
359         mov     itmp1,0*4(sp)
360         mov     3*4(sp),itmp2               /* pass exception address             */
361         sub     $2,itmp2
362         mov     itmp2,1*4(sp)
363 #if defined(ENABLE_PIC_ASM)
364         call    .GETPC
365         add     $_GLOBAL_OFFSET_TABLE_, %ebx
366         call    exceptions_asm_new_abstractmethoderror@PLT
367 #else
368         call    exceptions_asm_new_abstractmethoderror
369 #endif
370                                             /* exception pointer is return value  */
371         add     $(3*4),sp                   /* remove stack frame                 */
372
373         pop     xpc                         /* get exception address              */
374         sub     $2,xpc                      /* exception address is ra - 2        */
375         jmp     L_asm_handle_exception
376
377
378 /************************ function asm_builtin_x2x *****************************
379 *                                                                              *
380 *   Wrapper functions for corner cases                                         *
381 *                                                                              *
382 *******************************************************************************/
383
384 #if defined(ENABLE_PIC_ASM)
385 .GETPC:
386         mov     (%esp), %ebx
387         ret
388 #endif
389
390 asm_builtin_f2i:
391         sub     $(3*4),%esp
392 #if defined(ENABLE_PIC_ASM)
393         sub     $12, %esp
394         push    %ebx
395         fsts    (%esp)
396         call    .GETPC
397         add     $_GLOBAL_OFFSET_TABLE_, %ebx
398         call    builtin_f2i@PLT
399         pop     %ebx
400         add     $12, %esp
401 #else
402         fsts    (%esp)
403         call    builtin_f2i
404 #endif
405         add     $(3*4),%esp
406         ret
407
408 asm_builtin_d2i:
409         sub     $(3*4),%esp
410 #if defined(ENABLE_PIC_ASM)
411         sub     $12, %esp
412         push    %ebx
413         fstl    (%esp)
414         call    .GETPC
415         add     $_GLOBAL_OFFSET_TABLE_, %ebx
416         call    builtin_d2i@PLT
417         pop     %ebx
418         add     $12, %esp
419 #else
420         fstl    (%esp)
421         call    builtin_d2i
422 #endif
423         add     $(3*4),%esp
424         ret
425
426 asm_builtin_f2l:
427         sub     $(3*4),%esp
428 #if defined(ENABLE_PIC_ASM)
429         sub     $12, %esp
430         push    %ebx
431         fsts    (%esp)
432         call    .GETPC
433         add     $_GLOBAL_OFFSET_TABLE_, %ebx
434         call    builtin_f2l@PLT
435         pop     %ebx
436         add     $12, %esp
437 #else
438         fsts    (%esp)
439         call    builtin_f2l
440 #endif
441         add     $(3*4),%esp
442         ret
443
444 asm_builtin_d2l:
445         sub     $(3*4),%esp
446 #if defined(ENABLE_PIC_ASM)
447         sub     $12, %esp
448         push    %ebx
449         fstl    (%esp)
450         call    .GETPC
451         add     $_GLOBAL_OFFSET_TABLE_, %ebx
452         call    builtin_d2l@PLT
453         pop     %ebx
454         add     $12, %esp
455 #else
456         fstl    (%esp)
457         call    builtin_d2l
458 #endif
459         add     $(3*4),%esp
460         ret
461
462
463 /* asm_compare_and_swap ********************************************************
464
465    Does an atomic compare and swap.  Required for the lock
466    implementation.
467
468    Atomically do the following: Check if the location still contains
469    `oldval`. If so, replace it by `newval` and return `oldval`.
470
471    RETURN VALUE:
472        the old value at *p
473
474    long compare_and_swap(volatile long *p, long oldval, long newval);
475
476 *******************************************************************************/
477
478 asm_compare_and_swap:
479         mov     1*4(sp),%ecx            /* load p into a register                 */
480         mov     2*4(sp),%eax            /* load oldval into return register       */
481         mov     3*4(sp),%edx            /* load newval into a register            */
482         lock; cmpxchgl %edx,0(%ecx)
483         ret
484
485
486 /* asm_memory_barrier **********************************************************
487
488    A memory barrier for the Java Memory Model.
489
490 *******************************************************************************/
491
492 asm_memory_barrier:
493         lock; add $0,0(sp)
494         ret
495
496
497 #if defined(ENABLE_ESCAPE_CHECK)
498 asm_escape_check:
499         sub     $24,%esp
500
501         mov     t0, 4(%esp)
502         mov     itmp1, 8(%esp)
503         mov     itmp2, 12(%esp)
504         mov     itmp3, 16(%esp)
505
506         mov     28(%esp), itmp1
507         mov     itmp1, (%esp)
508
509         call    escape_analysis_escape_check
510
511         mov     4(%esp), t0
512         mov     8(%esp), itmp1
513         mov     12(%esp), itmp2
514         mov     16(%esp), itmp3
515
516         add     $24,sp
517         ret
518 #endif
519
520
521 /* disable exec-stacks ********************************************************/
522
523 #if defined(__linux__) && defined(__ELF__)
524         .section .note.GNU-stack,"",%progbits
525 #endif
526
527 /*
528  * These are local overrides for various environment variables in Emacs.
529  * Please do not remove this and leave it at the end of the file, where
530  * Emacs will automagically detect them.
531  * ---------------------------------------------------------------------
532  * Local variables:
533  * mode: asm
534  * indent-tabs-mode: t
535  * c-basic-offset: 4
536  * tab-width: 4
537  * End:
538  * vim:noexpandtab:sw=4:ts=4:
539  */