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