Merged trunk and subtype.
[cacao.git] / src / vm / jit / mips / asmpart.S
1 /* src/vm/jit/mips/asmpart.S - Java-C interface functions for MIPS
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 "vm/jit/mips/md-abi.h"
29 #include "vm/jit/mips/md-asm.h"
30
31 #include "vm/jit/abi-asm.h"
32 #include "vm/jit/methodheader.h"
33
34
35         .text
36         .set    noat
37
38
39 /* export functions ***********************************************************/
40
41         .globl asm_vm_call_method
42         .globl asm_vm_call_method_int
43         .globl asm_vm_call_method_long
44         .globl asm_vm_call_method_float
45         .globl asm_vm_call_method_double
46         .globl asm_vm_call_method_exception_handler
47         .globl asm_vm_call_method_end
48
49         .globl asm_handle_exception
50         .globl asm_handle_nat_exception
51
52         .globl asm_abstractmethoderror
53
54
55 /* asm_vm_call_method **********************************************************
56 *                                                                              *
57 *   This function calls a Java-method (which possibly needs compilation)       *
58 *   with up to 4 address parameters.                                           *
59 *                                                                              *
60 *   This functions calls the JIT-compiler which eventually translates the      *
61 *   method into machine code.                                                  *
62 *                                                                              *
63 *   A possibly throwed exception will be returned to the caller as function    *
64 *   return value, so the java method cannot return a fucntion value (this      *
65 *   function usually calls 'main' and '<clinit>' which do not return a         *
66 *   function value).                                                           *
67 *                                                                              *
68 *   C-prototype:                                                               *
69 *    javaobject_header *asm_calljavafunction (methodinfo *m,                   *
70 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
71 *                                                                              *
72 *******************************************************************************/
73
74         .ent    asm_vm_call_method
75
76         .align  3
77
78 #if SIZEOF_VOID_P == 8
79
80         .word   0                           /* fltsave                            */
81         .word   0                           /* intsave                            */
82         .word   0                           /* isleaf                             */
83         .word   0                           /* frame size                         */
84         .dword  0                           /* codeinfo pointer                   */
85
86 #else /* SIZEOF_VOID_P == 8 */
87
88         .word   0                           /* fltsave                            */
89         .word   0                           /* intsave                            */
90         .word   0                           /* isleaf                             */
91         .word   0                           /* frame size                         */
92         .word   0                           /* method pointer (pointer to name)   */
93
94 #endif /* SIZEOF_VOID_P == 8 */
95
96 asm_vm_call_method:
97 asm_vm_call_method_int:
98 asm_vm_call_method_long:
99 asm_vm_call_method_float:
100 asm_vm_call_method_double:
101         .set    noreorder                 /* XXX we need to recompute pv          */
102
103         aaddiu  sp,sp,-12*8               /* allocate stack space (only 11 needed)*/
104         ast     ra,0*8(sp)                /* save return address                  */
105
106         bal     L_asm_vm_call_method_compute_pv
107         ast     pv,1*8(sp)                /* procedure vector                     */
108 L_asm_vm_call_method_compute_pv:
109         aaddiu  pv,ra,-4*4
110
111         ast     s0,3*8(sp)                /* save callee saved register           */
112         ast     a0,4*8(sp)                /* save method PV                       */
113
114 #if SIZEOF_VOID_P == 8
115         s.d     fss0,5*8(sp)              /* save non JavaABI saved flt registers */
116         s.d     fss1,6*8(sp)
117         s.d     fss2,7*8(sp)
118         s.d     fss3,8*8(sp)
119         s.d     fss4,9*8(sp)
120         s.d     fss5,10*8(sp)
121 #endif
122
123         move    t0,a1                     /* address of data structure            */
124         move    t1,a2                     /* stack argument count                 */
125         move    s0,sp                     /* save stack pointer                   */
126
127 #if SIZEOF_VOID_P == 8
128
129         ld      a0,0*8(t0)
130         ld      a1,1*8(t0)
131         ld      a2,2*8(t0)
132         ld      a3,3*8(t0)
133         ld      a4,4*8(t0)
134         ld      a5,5*8(t0)
135         ld      a6,6*8(t0)
136         ld      a7,7*8(t0)
137
138         l.d     fa0,8*8(t0)
139         l.d     fa1,9*8(t0)
140         l.d     fa2,10*8(t0)
141         l.d     fa3,11*8(t0)
142         l.d     fa4,12*8(t0)
143         l.d     fa5,13*8(t0)
144         l.d     fa6,14*8(t0)
145         l.d     fa7,15*8(t0)
146
147 #else /* SIZEOF_VOID_P == 8 */
148
149 # if WORDS_BIGENDIAN == 1
150         lw      a0,0*8+4(t0)
151         lw      a1,1*8+4(t0)
152         lw      a2,2*8+4(t0)
153         lw      a3,3*8+4(t0)
154 # else
155         lw      a0,0*8(t0)
156         lw      a1,1*8(t0)
157         lw      a2,2*8(t0)
158         lw      a3,3*8(t0)
159 # endif
160
161 # if !defined(ENABLE_SOFT_FLOAT)
162         l.d     fa0,4*8(t0)
163         l.d     fa1,5*8(t0)
164 # endif
165
166 #endif /* SIZEOF_VOID_P == 8 */
167
168         beqz    t1,L_asm_vm_call_method_stack_copy_done
169         nop
170
171         sll     t2,t1,3                   /* calculate stackframe size (* 8)      */
172         asubu   sp,sp,t2                  /* create stackframe                    */
173         move    t2,sp                     /* temporary stack pointer              */
174
175 L_asm_vm_call_method_stack_copy_loop:
176 #if SIZEOF_VOID_P == 8
177         ld      t3,16*8(t0)               /* load argument                        */
178         sd      t3,0(t2)                  /* store argument on stack              */
179 #else
180 # if !defined(ENABLE_SOFT_FLOAT)
181         lw      t3,6*8+0(t0)              /* load argument                        */
182         lw      t4,6*8+4(t0)
183         sw      t3,0(t2)                  /* store argument on stack              */
184         sw      t4,4(t2)
185 # else
186 #  error implement me
187 # endif
188 #endif
189
190         aaddi   t1,t1,-1                  /* subtract 1 argument                  */
191         aaddi   t0,t0,8                   /* load address of next argument        */
192         aaddi   t2,t2,8                   /* increase stack pointer               */
193
194         bgtz    t1,L_asm_vm_call_method_stack_copy_loop
195         nop
196
197 L_asm_vm_call_method_stack_copy_done:
198         ala     mptr,4*8(s0)              /* get address of PV                    */
199         ald     pv,0*8(mptr)              /* load PV                              */
200         jalr    pv
201         nop
202 L_asm_vm_call_method_recompute_pv:
203 #if SIZEOF_VOID_P == 8
204         aaddiu  pv,ra,-76*4               /* recompute procedure vector           */
205 #else
206         aaddiu  pv,ra,(asm_vm_call_method - L_asm_vm_call_method_recompute_pv)
207 #endif
208
209         .set    reorder                   /* XXX we need to recompute pv          */
210
211 calljava_return2:
212         move    sp,s0                     /* restore stack pointer                */
213
214         ald     ra,0*8(sp)                /* restore return address               */
215         ald     pv,1*8(sp)                /* restore procedure vector             */
216         ald     s0,3*8(sp)
217
218 #if SIZEOF_VOID_P == 8
219         l.d     fss0,5*8(sp)              /* restore non JavaABI saved flt regs   */
220         l.d     fss1,6*8(sp)
221         l.d     fss2,7*8(sp)
222         l.d     fss3,8*8(sp)
223         l.d     fss4,9*8(sp)
224         l.d     fss5,10*8(sp)
225 #endif
226
227         aaddiu  sp,sp,12*8                /* free stack space                     */
228         j       ra                        /* return                               */
229
230 asm_vm_call_method_exception_handler:
231         move    sp,s0                     /* restore stack pointer                */
232 #if SIZEOF_VOID_P == 4
233         aaddiu  sp,sp,-4*4                /* reserve space for 1 argument         */
234 #endif
235
236         move    a0,itmp1                  
237         jal     builtin_throw_exception
238 #if SIZEOF_VOID_P == 4
239         aaddiu  sp,sp,4*4
240 #endif
241 asm_vm_call_method_end:
242         b       calljava_return2
243
244         .end    asm_vm_call_method
245
246
247 /* asm_handle_exception ********************************************************
248
249    This function handles an exception. It does not use the usual calling
250    conventions. The exception pointer is passed in REG_ITMP1 and the
251    pc from the exception raising position is passed in REG_ITMP2. It searches
252    the local exception table for a handler. If no one is found, it unwinds
253    stacks and continues searching the callers.
254
255 *******************************************************************************/
256
257         .ent    asm_handle_nat_exception
258
259 asm_handle_nat_exception:
260 L_asm_handle_exception_stack_loop:
261 #if SIZEOF_VOID_P == 8
262         aaddiu  sp,sp,-6*8                  /* keep stack 16-byte aligned         */
263         ast     xptr,0*8(sp)                /* save exception pointer             */
264         ast     xpc,1*8(sp)                 /* save exception pc                  */
265         ast     ra,3*8(sp)                  /* save RA                            */
266         ast     zero,4*8(sp)                /* save maybe-leaf flag (cleared)     */
267 #else
268         aaddiu  sp,sp,-(4*4+6*8)            /* allocate stack                     */
269         ast     xptr,4*4+0*8(sp)            /* save exception pointer             */
270         ast     xpc,4*4+1*8(sp)             /* save exception pc                  */
271         ast     ra,4*4+3*8(sp)              /* save return address                */
272         ast     zero,4*4+4*8(sp)            /* save maybe-leaf flag (cleared)     */
273 #endif
274
275         move    a0,ra                       /* pass RA                            */
276         jal     md_asm_codegen_get_pv_from_pc /* get PV from RA                   */
277
278 #if SIZEOF_VOID_P == 8
279         ast     v0,2*8(sp)                  /* save PV                            */
280
281         ald     a0,0*8(sp)                  /* pass xptr                          */
282         ald     a1,1*8(sp)                  /* pass xpc                           */
283         move    a2,v0                       /* pass PV                            */
284         aaddiu  a3,sp,6*8                   /* pass Java SP                       */
285 #else
286         ast     v0,4*4+2*8(sp)              /* save data segment pointer          */
287
288         ald     a0,4*4+0*8(sp)              /* pass exception pointer             */
289         ald     a1,4*4+1*8(sp)              /* pass exception pc                  */
290         move    a2,v0                       /* pass data segment pointer          */
291         aaddiu  a3,sp,(4*4+6*8)             /* pass Java stack pointer            */
292 #endif
293
294         b       L_asm_handle_exception_continue
295
296         .aent    asm_handle_exception
297
298 asm_handle_exception:
299         aaddiu  sp,sp,-(ARG_CNT+TMP_CNT)*8  /* create maybe-leaf stackframe       */
300
301         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
302         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
303
304 #if SIZEOF_VOID_P == 8
305         aaddiu  sp,sp,-6*8                  /* allocate stack                     */
306         ast     xptr,0*8(sp)                /* save exception pointer             */
307         ast     pv,2*8(sp)                  /* save PV                            */
308         ast     ra,3*8(sp)                  /* save RA                            */
309         addu    t0,zero,1                   /* set maybe-leaf flag                */
310         ast     t0,4*8(sp)                  /* save maybe-leaf flag               */
311 #else
312         aaddiu  sp,sp,-(4*4+6*8)            /* allocate stack                     */
313         ast     xptr,4*4+0*8(sp)            /* save exception pointer             */
314         ast     xpc,4*4+1*8(sp)             /* save exception pc                  */
315         ast     pv,4*4+2*8(sp)              /* save data segment pointer          */
316         ast     ra,4*4+3*8(sp)              /* save return address                */
317         addu    t0,zero,1                   /* set maybe-leaf flag                */
318         ast     t0,4*4+4*8(sp)              /* save maybe-leaf flag               */
319 #endif
320
321         move    a0,xptr                     /* pass xptr                          */
322         move    a1,xpc                      /* pass xpc                           */
323         move    a2,pv                       /* pass PV                            */
324
325 #if SIZEOF_VOID_P == 8
326         aaddiu  a3,sp,(ARG_CNT+TMP_CNT+6)*8 /* pass Java SP                       */
327 #else
328         aaddiu  a3,sp,4*4+(ARG_CNT+TMP_CNT+6)*8 /* pass Java stack pointer        */
329 #endif
330
331 L_asm_handle_exception_continue:
332         jal     exceptions_handle_exception
333         
334         beqz    v0,L_asm_handle_exception_not_catched
335
336         move    xpc,v0                      /* move handlerpc into xpc            */
337
338 #if SIZEOF_VOID_P == 8
339         ald     xptr,0*8(sp)                /* restore exception pointer          */
340         ald     pv,2*8(sp)                  /* restore PV                         */
341         ald     ra,3*8(sp)                  /* restore RA                         */
342         ald     t0,4*8(sp)                  /* get maybe-leaf flag                */
343         aaddiu  sp,sp,6*8                   /* free stackframe                    */
344 #else
345         ald     xptr,4*4+0*8(sp)            /* restore exception pointer          */
346         ald     pv,4*4+2*8(sp)              /* restore data segment pointer       */
347         ald     ra,4*4+3*8(sp)              /* restore return address             */
348         ald     t0,4*4+4*8(sp)              /* get maybe-leaf flag                */
349         aaddiu  sp,sp,4*4+6*8               /* free stackframe                    */
350 #endif
351         
352         beqz    t0,L_asm_handle_exception_no_leaf
353
354         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
355         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
356         
357         aaddiu  sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
358
359 L_asm_handle_exception_no_leaf:
360         jr      xpc                         /* jump to the handler                */
361
362 L_asm_handle_exception_not_catched:
363 #if SIZEOF_VOID_P == 8
364         ald     xptr,0*8(sp)                /* restore xptr                       */
365         ald     pv,2*8(sp)                  /* restore PV                         */
366         ald     ra,3*8(sp)                  /* restore RA                         */
367         ald     t0,4*8(sp)                  /* get maybe-leaf flag                */
368         aaddiu  sp,sp,6*8                   /* free stackframe                    */
369 #else
370         ald     xptr,4*4+0*8(sp)            /* restore xptr                       */
371         ald     pv,4*4+2*8(sp)              /* restore PV                         */
372         ald     ra,4*4+3*8(sp)              /* restore RA                         */
373         ald     t0,4*4+4*8(sp)              /* get maybe-leaf flag                */
374         aaddiu  sp,sp,4*4+6*8               /* free stackframe                    */
375 #endif
376         
377         beqz    t0,L_asm_handle_exception_no_leaf_stack
378
379         aaddiu  sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
380         move    t0,zero                     /* clear the maybe-leaf flag          */
381
382 L_asm_handle_exception_no_leaf_stack:
383         lw      t1,FrameSize(pv)            /* get frame size                     */
384         aaddu   t1,sp,t1                    /* pointer to save area               */
385
386         lw      t2,IsLeaf(pv)               /* is leaf procedure                  */
387         bnez    t2,L_asm_handle_exception_no_ra_restore
388
389         ald     ra,-1*8(t1)                 /* restore ra                         */
390         aaddiu  t1,t1,-8                    /* t1--                               */
391
392 L_asm_handle_exception_no_ra_restore:
393         move    xpc,ra                      /* the new xpc is ra                  */
394         lw      t2,IntSave(pv)              /* t1 = saved int register count      */
395         ala     t3,ex_int2                  /* t3 = current pc                    */
396         sll     t2,t2,2                     /* t2 = register count * 4            */
397         asubu   t3,t3,t2                    /* t3 = IntSave - 4 * register count  */
398         jr      t3                          /* jump to save position              */
399
400         ald     s0,-8*8(t1)
401         ald     s1,-7*8(t1)
402         ald     s2,-6*8(t1)
403         ald     s3,-5*8(t1)
404         ald     s4,-4*8(t1)
405         ald     s5,-3*8(t1)
406         ald     s6,-2*8(t1)
407         ald     s7,-1*8(t1)
408
409 ex_int2:
410         sll     t2,t2,1               /* t2 = register count * 4 * 2              */
411         asubu   t1,t1,t2              /* t1 = t0 - 8 * register count             */
412
413         lw      t2,FltSave(pv)        /* t2 = saved flt register count            */
414         ala     t3,ex_flt2            /* t3 = current pc                          */
415         sll     t2,t2,2               /* t2 = register count * 4                  */
416         asubu   t3,t3,t2              /* t3 = ex_int_sav - 4 * register count     */
417         jr      t3                          /* jump to save position              */
418
419 #if SIZEOF_VOID_P == 8
420         l.d     fs0,-4*8(t1)
421         l.d     fs1,-3*8(t1)
422         l.d     fs2,-2*8(t1)
423         l.d     fs3,-1*8(t1)
424 #else
425 # if !defined(ENABLE_SOFT_FLOAT)
426         l.d     fs0,-6*8(t1)
427         l.d     fs1,-5*8(t1)
428         l.d     fs2,-4*8(t1)
429         l.d     fs3,-3*8(t1)
430         l.d     fs4,-2*8(t1)
431         l.d     fs5,-1*8(t1)
432 # endif
433 #endif
434
435 ex_flt2:
436         lw      t1,FrameSize(pv)            /* get frame size                     */
437         aaddu   sp,sp,t1                    /* unwind stack                       */
438         b       L_asm_handle_exception_stack_loop
439
440         .end    asm_handle_nat_exception
441
442
443 /* asm_abstractmethoderror *****************************************************
444
445    Creates and throws an AbstractMethodError.
446
447 *******************************************************************************/
448
449         .ent    asm_abstractmethoderror
450
451 asm_abstractmethoderror:
452         aaddiu  sp,sp,-2*8                  /* create stackframe                  */
453         ast     ra,0*8(sp)                  /* save return address                */
454         aaddiu  a0,sp,2*8                   /* pass java sp                       */
455         move    a1,ra                       /* pass exception address             */
456         jal     exceptions_asm_new_abstractmethoderror
457         ald     ra,0*8(sp)                  /* restore return address             */
458         aaddiu  sp,sp,2*8                   /* remove stackframe                  */
459
460         move    xptr,v0                     /* get exception pointer              */
461         aaddiu  xpc,ra,-4                   /* exception address is ra - 4        */
462         b       asm_handle_nat_exception
463
464         .end    asm_abstractmethoderror
465
466
467 /* disable exec-stacks ********************************************************/
468
469 #if defined(__linux__) && defined(__ELF__)
470         .section .note.GNU-stack,"",%progbits
471 #endif
472
473
474 /*
475  * These are local overrides for various environment variables in Emacs.
476  * Please do not remove this and leave it at the end of the file, where
477  * Emacs will automagically detect them.
478  * ---------------------------------------------------------------------
479  * Local variables:
480  * mode: asm
481  * indent-tabs-mode: t
482  * c-basic-offset: 4
483  * tab-width: 4
484  * End:
485  * vim:noexpandtab:sw=4:ts=4:
486  */