- show float arguments as hex values in runverbose mode
[cacao.git] / src / vm / jit / mips / asmpart.S
1 /* jit/mips/asmpart.S - Java-C interface functions for mips
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6    S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
7    J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29
30    $Id: asmpart.S 902 2004-01-22 21:38:58Z twisti $
31
32 */
33
34
35 #include "offsets.h"
36
37 #define zero    $0
38 #define itmp1   $1
39 #define v0      $2
40 #define itmp2   $3
41 #define a0      $4
42 #define a1      $5
43 #define a2      $6
44 #define a3      $7
45
46 #define a4      $8
47 #define a5      $9
48 #define a6      $10
49 #define a7      $11
50 #define t0      $12
51 #define t1      $13
52 #define t2      $14
53 #define t3      $15
54
55 #define s0      $16
56 #define s1      $17
57 #define s2      $18
58 #define s3      $19
59 #define s4      $20
60 #define s5      $21
61 #define s6      $22
62 #define s7      $23
63
64 #define t4      $24
65 #define itmp3   $25
66 #define k0      $26
67 #define k1      $27
68
69 #define gp      $28
70 #define sp      $29
71 #define s8      $30
72 #define ra      $31
73
74 #define pv      s8
75 #define t9      itmp3
76
77 #define xptr    itmp1
78 #define xpc     itmp2
79 #define mptr    itmp3
80 #define mptrreg 25
81
82 #define fv0     $f0
83 #define ft0     $f1
84 #define ft1     $f2
85 #define ft2     $f3
86 #define ft3     $f4
87 #define ft4     $f5
88 #define ft5     $f6
89 #define ft6     $f7
90
91 #define ft7     $f8
92 #define ft8     $f9
93 #define ft9     $f10
94 #define ft10    $f11
95 #define fa0     $f12
96 #define fa1     $f13
97 #define fa2     $f14
98 #define fa3     $f15
99
100 #define fa4     $f16
101 #define fa5     $f17
102 #define fa6     $f18
103 #define fa7     $f19
104 #define ft11    $f20
105 #define ft12    $f21
106 #define ft13    $f22
107 #define ft14    $f23
108
109 #define fs0     $f24
110 #define ft15    $f25
111 #define fs1     $f26
112 #define ft16    $f27
113 #define fs2     $f28
114 #define ft17    $f29
115 #define fs3     $f30
116 #define ft18    $f31
117
118 #define fss0    $f20
119 #define fss1    $f22
120 #define fss2    $f25
121 #define fss3    $f27
122 #define fss4    $f29
123 #define fss5    $f31
124
125 #define aaddu   daddu
126 #define asubu   dsubu
127 #define aaddiu  daddiu
128 #define ald     ld
129 #define ast     sd
130 #define ala     dla
131 #define asll    dsll
132 #define ashift  3
133
134 #define MethodPointer   -8
135 #define FrameSize       -12
136 #define IsSync          -16
137 #define IsLeaf          -20
138 #define IntSave         -24
139 #define FltSave         -28
140 #define ExTableSize     -32
141 #define ExTableStart    -32
142
143 #define ExEntrySize     -32
144 #define ExStartPC       -8
145 #define ExEndPC         -16
146 #define ExHandlerPC     -24
147 #define ExCatchType     -32
148
149
150         .text
151         .set    noat
152
153
154 /********************* exported functions and variables ***********************/
155
156         .globl synchronize_caches
157         .globl asm_calljavafunction
158         .globl asm_calljavafunction2
159         .globl asm_calljavafunction2long
160         .globl asm_calljavafunction2double
161         .globl asm_call_jit_compiler
162         .globl asm_dumpregistersandcall
163         .globl asm_handle_exception
164         .globl asm_handle_nat_exception
165         .globl asm_check_clinit
166         .globl asm_builtin_checkarraycast
167         .globl asm_builtin_checkcast
168         .globl asm_builtin_aastore
169         .globl asm_builtin_monitorenter
170         .globl asm_builtin_monitorexit
171         .globl asm_builtin_idiv
172         .globl asm_builtin_irem
173         .globl asm_builtin_ldiv
174         .globl asm_builtin_lrem
175         .globl asm_perform_threadswitch
176         .globl asm_initialize_thread_stack
177         .globl asm_switchstackandcall
178         .globl asm_getcallingmethod
179         .globl asm_builtin_trace
180         .globl asm_builtin_exittrace
181
182
183 /*************************** imported functions *******************************/
184
185         .globl jit_compile
186         .globl builtin_monitorexit
187         .globl builtin_throw_exception
188         .globl builtin_trace_exception
189         .globl class_java_lang_Object
190
191
192 /********************* function synchronize_caches ****************************/
193
194         .ent    synchronize_caches
195 synchronize_caches:
196
197 /*      li      a0,BCACHE          */     /* flush both caches                    */
198 /*      li      v0,SYS_cacheflush  */     /* Syscall number for cacheflush()      */
199 /*      syscall                    */     /* call cacheflush()                    */
200         j       ra                        /* return                               */
201
202         .end    synchronize_caches
203
204
205 /********************* function asm_calljavafunction ****************************
206 *                                                                              *
207 *   This function calls a Java-method (which possibly needs compilation)       *
208 *   with up to 4 address parameters.                                           *
209 *                                                                              *
210 *   This functions calls the JIT-compiler which eventually translates the      *
211 *   method into machine code.                                                  *
212 *                                                                              *
213 *   A possibly throwed exception will be returned to the caller as function    *
214 *   return value, so the java method cannot return a fucntion value (this      *
215 *   function usually calls 'main' and '<clinit>' which do not return a         *
216 *   function value).                                                           *
217 *                                                                              *
218 *   C-prototype:                                                               *
219 *    javaobject_header *asm_calljavafunction (methodinfo *m,                   *
220 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
221 *                                                                              *
222 *******************************************************************************/
223
224         .ent    asm_calljavafunction
225
226 call_name:
227         .ascii  "calljavafunction\0\0"
228
229         .align  3
230         .quad   0                         /* catch type all                       */
231         .quad   calljava_xhandler         /* handler pc                           */
232         .quad   calljava_xhandler         /* end pc                               */
233         .quad   asm_calljavafunction      /* start pc                             */
234         .long   1                         /* extable size                         */
235         .long   0                         /* fltsave                              */
236         .long   0                         /* intsave                              */
237         .long   0                         /* isleaf                               */
238         .long   0                         /* IsSync                               */
239         .long   80                        /* frame size                           */
240         .quad   0                         /* method pointer (pointer to name)     */
241
242 asm_calljavafunction:
243         aaddiu  sp,sp,-10*8               /* allocate stack space                 */
244         sd      ra,0(sp)                  /* save return address                  */
245
246         .set    noreorder
247         bal     call_java_pc
248         sd      pv,3*8(sp)                /* procedure vector                     */
249 call_java_pc:
250         aaddiu  pv,ra,-4*4
251
252         .set    reorder
253         
254         sdc1    fss0,4*8(sp)              /* save non JavaABI saved flt registers */
255         sdc1    fss1,5*8(sp)
256         sdc1    fss2,6*8(sp)
257         sdc1    fss3,7*8(sp)
258         sdc1    fss4,8*8(sp)
259         sdc1    fss5,9*8(sp)
260         sd      a0,2*8(sp)                /* save method pointer for compiler     */
261         aaddiu  itmp1,sp,16               /* pass pointer to methodptr via itmp1  */
262
263         move    a0,a1                     /* pass the remaining parameters        */
264         move    a1,a2
265         move    a2,a3
266         move    a3,a4
267
268         ala     mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
269         ast     mptr,1*8(sp)              /* store function address               */
270         move    mptr,sp                   /* set method pointer                   */
271
272         .set    noreorder
273         
274         ald     pv,1*8(mptr)              /* method call as in Java               */
275         jalr    pv                        /* call JIT compiler                    */
276         nop
277         aaddiu  pv,ra,-23*4               /* recompute procedure vector           */
278 #if 0
279         move    v0,zero                   /* clear return value (exception ptr)   */
280 #else
281         nop
282 #endif
283
284 calljava_return:
285         ld      ra,0(sp)                  /* restore return address               */
286         ld      pv,3*8(sp)                /* restore procedure vector             */
287
288         ldc1    fss0,4*8(sp)              /* restore non JavaABI saved flt regs   */
289         ldc1    fss1,5*8(sp)
290         ldc1    fss2,6*8(sp)
291         ldc1    fss3,7*8(sp)
292         ldc1    fss4,8*8(sp)
293         ldc1    fss5,9*8(sp)
294         j       ra                        /* return                               */
295         aaddiu  sp,sp,10*8                /* free stack space                     */
296
297         .set    reorder
298         
299 calljava_xhandler:
300         move    a0,itmp1                  
301         jal     builtin_throw_exception
302         b       calljava_return
303
304         .end    asm_calljavafunction
305
306
307         .ent    asm_calljavafunction2
308
309 call_name2:
310         .ascii  "calljavafunction2\0\0"
311
312         .align  3
313         .quad   0                         /* catch type all                       */
314         .quad   calljava_xhandler2        /* handler pc                           */
315         .quad   calljava_xhandler2        /* end pc                               */
316         .quad   asm_calljavafunction2     /* start pc                             */
317         .long   1                         /* extable size                         */
318         .long   0                         /* fltsave                              */
319         .long   1                         /* intsave                              */
320         .long   0                         /* isleaf                               */
321         .long   0                         /* IsSync                               */
322         .long   96                        /* frame size                           */
323         .quad   0                         /* method pointer (pointer to name)     */
324
325 asm_calljavafunction2:
326 asm_calljavafunction2double:
327 asm_calljavafunction2long:
328         aaddiu  sp,sp,-12*8               /* allocate stack space (only 11 needed)*/
329         sd      ra,0(sp)                  /* save return address                  */
330
331         .set    noreorder
332         bal     call_java_pc2
333         sd      pv,1*8(sp)                /* procedure vector                     */
334 call_java_pc2:
335         aaddiu  pv,ra,-4*4
336         sd      s7,3*8(sp)
337
338         .set    reorder
339         
340         sdc1    fss0,5*8(sp)              /* save non JavaABI saved flt registers */
341         sdc1    fss1,6*8(sp)
342         sdc1    fss2,7*8(sp)
343         sdc1    fss3,8*8(sp)
344         sdc1    fss4,9*8(sp)
345         sdc1    fss5,10*8(sp)
346         sd      a0,4*8(sp)                /* save method pointer for compiler     */
347         move    t0,a3
348         move    s7,a1
349
350         blez    s7,calljava_argsloaded
351         ald     a0,offjniitem(t0)
352         ldc1    fa0,offjniitem(t0)
353         daddi   s7,s7,-1
354         blez    s7,calljava_argsloaded
355
356         ald     a1,offjniitem+sizejniblock*1(t0)
357         ldc1    fa1,offjniitem+sizejniblock*1(t0)
358         daddi   s7,s7,-1
359         blez    s7,calljava_argsloaded
360
361         ald     a2,offjniitem+sizejniblock*2(t0)
362         ldc1    fa2,offjniitem+sizejniblock*2(t0)
363         daddi   s7,s7,-1
364         blez    s7,calljava_argsloaded
365
366         ald     a3,offjniitem+sizejniblock*3(t0)
367         ldc1    fa3,offjniitem+sizejniblock*3(t0)
368         daddi   s7,s7,-1
369         blez    s7,calljava_argsloaded
370
371         ald     a4,offjniitem+sizejniblock*4(t0)
372         ldc1    fa4,offjniitem+sizejniblock*4(t0)
373         daddi   s7,s7,-1
374         blez    s7,calljava_argsloaded
375
376         ald     a5,offjniitem+sizejniblock*5(t0)
377         ldc1    fa5,offjniitem+sizejniblock*5(t0)
378         daddi   s7,s7,-1
379         blez    s7,calljava_argsloaded
380
381         ald     a6,offjniitem+sizejniblock*6(t0)
382         ldc1    fa6,offjniitem+sizejniblock*6(t0)
383         daddi   s7,s7,-1
384         blez    s7,calljava_argsloaded
385
386         ald     a7,offjniitem+sizejniblock*7(t0)
387         ldc1    fa7,offjniitem+sizejniblock*7(t0)
388         daddi   s7,s7,-1
389                 
390 calljava_argsloaded:
391     move    t4,sp
392         blez    s7,calljava_nocopy
393         subu    t1,zero,s7
394         sll     t2,t1,3
395         daddu   sp,sp,t2
396         daddu   t2,t2,t4
397
398 calljava_copyloop:
399     ald     t3,offjniitem+sizejniblock*8(t0)
400         ast     t3,0(t2)
401         ala     t1,1(t1)
402         ala     t0,sizejniblock(t0)
403         ala     t2,8(t2)
404         bnez    t1,calljava_copyloop
405
406 calljava_nocopy:
407         ala     itmp1,32(t4)              /* pass pointer to methodptr via itmp1  */
408
409         ala     mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
410         ast     mptr,16(sp)               /* store function address               */
411         ala     mptr,8(t4)                /* set method pointer                   */
412
413         .set    noreorder
414         
415         ald     pv,8(mptr)                /* method call as in Java               */
416         jalr    pv                        /* call JIT compiler                    */
417         nop
418         aaddiu  pv,ra,-76*4               /* recompute procedure vector           */
419
420 calljava_return2:
421         ld      ra,0(sp)                  /* restore return address               */
422         ld      pv,8(sp)                  /* restore procedure vector             */
423         ld      s7,24(sp)
424
425         ldc1    fss0,5*8(sp)              /* restore non JavaABI saved flt regs   */
426         ldc1    fss1,6*8(sp)
427         ldc1    fss2,7*8(sp)
428         ldc1    fss3,8*8(sp)
429         ldc1    fss4,9*8(sp)
430         ldc1    fss5,10*8(sp)
431         j       ra                        /* return                               */
432         aaddiu  sp,sp,12*8                /* free stack space                     */
433
434         .set    reorder
435         
436 calljava_xhandler2:
437     sll     s7,s7,3
438         aaddu   sp,s7,sp
439         move    a0,itmp1                  
440         jal     builtin_throw_exception
441         b       calljava_return2
442
443         .end    asm_calljavafunction2
444
445
446 /****************** function asm_call_jit_compiler *****************************
447 *                                                                              *
448 *   invokes the compiler for untranslated JavaVM methods.                      *
449 *                                                                              *
450 *   Register REG_ITEMP1 contains a pointer to the method info structure        *
451 *   (prepared by createcompilerstub). Using the return address in R31 and the  *
452 *   offset in the LDA instruction or using the value in methodptr R25 the      *
453 *   patching address for storing the method address can be computed:           *
454 *                                                                              *
455 *   method address was either loaded using                                     *
456 *   M_ALD (REG_PV, REG_PV, a)        ; invokestatic/special    ($28)           *
457 *   M_JSR (REG_RA, REG_PV);                                                    *
458 *   M_NOP                                                                      *
459 *   M_LDA (REG_PV, REG_RA, val)                                                *
460 *   or                                                                         *
461 *   M_ALD (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($25)           *
462 *   M_JSR (REG_RA, REG_PV);                                                    *
463 *   M_NOP                                                                      *
464 *   in the static case the method pointer can be computed using the            *
465 *   return address and the lda function following the jmp instruction          *
466 *                                                                              *
467 *******************************************************************************/
468
469
470         .ent    asm_call_jit_compiler
471 asm_call_jit_compiler:
472
473         lw      t0,-12(ra)            /* load instruction LD PV,xxx($y)           */
474         srl     t0,t0,21              /* shift right register number $y           */
475         and     t0,t0,31              /* isolate register number                  */
476         addiu   t0,t0,-mptrreg        /* test for REG_METHODPTR                   */
477         beqz    t0,noregchange       
478
479         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
480         sll     t0,t0,16
481         sra     t0,t0,16              /* isolate offset                           */
482         aaddu   mptr,t0,ra            /* compute update address                   */
483
484 noregchange:
485
486         aaddiu  sp,sp,-18*8           /* allocate stack space                     */
487         sd      a0,0*8(sp)            /* save all argument registers              */
488         sd      a1,1*8(sp)            /* they could be used by method             */
489         sd      a2,2*8(sp)
490         sd      a3,3*8(sp)
491         sd      a4,4*8(sp)
492         sd      a5,5*8(sp)
493         sd      a6,6*8(sp)
494         sd      a7,7*8(sp)
495         sdc1    fa0,8*8(sp)
496         sdc1    fa1,9*8(sp)
497         sdc1    fa2,10*8(sp)
498         sdc1    fa3,11*8(sp)
499         sdc1    fa4,12*8(sp)
500         sdc1    fa5,13*8(sp)
501         sdc1    fa6,14*8(sp)
502         sdc1    fa7,15*8(sp)
503         sd      mptr,16*8(sp)         /* save method pointer                      */
504         sd      ra,17*8(sp)           /* save return address                      */
505
506         ald     a0,0(itmp1)           /* pass 'methodinfo' pointer to             */
507         jal     jit_compile           /* jit compiler                             */
508
509         ld      a0,0*8(sp)            /* restore argument registers               */
510         ld      a1,1*8(sp)            /* they could be used by method             */
511         ld      a2,2*8(sp)
512         ld      a3,3*8(sp)
513         ld      a4,4*8(sp)
514         ld      a5,5*8(sp)
515         ld      a6,6*8(sp)
516         ld      a7,7*8(sp)
517         ldc1    fa0,8*8(sp)
518         ldc1    fa1,9*8(sp)
519         ldc1    fa2,10*8(sp)
520         ldc1    fa3,11*8(sp)
521         ldc1    fa4,12*8(sp)
522         ldc1    fa5,13*8(sp)
523         ldc1    fa6,14*8(sp)
524         ldc1    fa7,15*8(sp)
525         ld      mptr,16*8(sp)         /* restore method pointer                   */
526         ld      ra,17*8(sp)           /* restore return address                   */
527         aaddiu  sp,sp,18*8            /* deallocate stack area                    */
528
529         lw      t0,-12(ra)            /* load instruction LDQ PV,xxx($yy)         */
530         sll     t0,t0,16
531         sra     t0,t0,16              /* isolate offset                           */
532
533         aaddu   t0,t0,mptr            /* compute update address via method pointer*/
534         ast     v0,0(t0)              /* save new method address there            */
535
536         move    pv,v0                 /* move method address into pv              */
537
538         jr      pv                    /* and call method. The method returns      */
539                                       /* directly to the caller (ra).             */
540
541         .end    asm_call_jit_compiler
542
543
544 /****************** function asm_dumpregistersandcall **************************
545 *                                                                              *
546 *   This funtion saves all callee saved (address) registers and calls the      *
547 *   function which is passed as parameter.                                     *
548 *                                                                              *
549 *   This function is needed by the garbage collector, which needs to access    *
550 *   all registers which are stored on the stack. Unused registers are          *
551 *   cleared to avoid interferances with the GC.                                *
552 *                                                                              *
553 *   void asm_dumpregistersandcall (functionptr f);                             *
554 *                                                                              *
555 *******************************************************************************/
556
557         .ent    asm_dumpregistersandcall
558 asm_dumpregistersandcall:
559         aaddiu  sp,sp,-10*8           /* allocate stack                           */
560         sd      ra,0(sp)              /* save return address                      */
561
562         sd      s0,1*8(sp)            /* save all callee saved registers          */
563         sd      s1,2*8(sp)
564         sd      s2,3*8(sp)
565         sd      s3,4*8(sp)
566         sd      s4,5*8(sp)
567         sd      s5,6*8(sp)
568         sd      s6,7*8(sp)
569         sd      s7,8*8(sp)
570         sd      s8,9*8(sp)
571
572         move    itmp3,a0
573         jalr    itmp3                 /* and call function                        */
574
575         ld      ra,0(sp)              /* restore return address                   */
576         aaddiu  sp,sp,10*8            /* deallocate stack                         */
577         j       ra                    /* return                                   */
578
579         .end    asm_dumpregistersandcall
580
581
582 /********************* function asm_handle_exception ***************************
583 *                                                                              *
584 *   This function handles an exception. It does not use the usual calling      *
585 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
586 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
587 *   the local exception table for a handler. If no one is found, it unwinds    *
588 *   stacks and continues searching the callers.                                *
589 *                                                                              *
590 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
591 *                                                                              *
592 *******************************************************************************/
593
594         .ent    asm_handle_nat_exception
595 asm_handle_nat_exception:
596
597         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
598         sll     t0,t0,16
599         sra     t0,t0,16              /* isolate offset                           */
600         aaddu   pv,t0,ra              /* compute update address                   */
601
602         .aent    asm_handle_exception
603 asm_handle_exception:
604
605         aaddiu  sp,sp,-14*8           /* allocate stack                           */
606         sd      v0,0*8(sp)            /* save possible used registers             */
607         sd      t0,1*8(sp)            /* also registers used by trace_exception   */
608         sd      t1,2*8(sp)
609         sd      t2,3*8(sp)
610         sd      t3,4*8(sp)
611         sd      t4,5*8(sp)
612         sd      a0,6*8(sp)
613         sd      a1,7*8(sp)
614         sd      a2,8*8(sp)
615         sd      a3,9*8(sp)
616         sd      a4,10*8(sp)
617         sd      a5,11*8(sp)
618         sd      a6,12*8(sp)
619         sd      a7,13*8(sp)
620
621         addu    t3,zero,1             /* set no unwind flag                       */
622 ex_stack_loop:
623         aaddiu  sp,sp,-6*8            /* allocate stack                           */
624         sd      xptr,0*8(sp)          /* save used registers                      */
625         sd      xpc,1*8(sp)
626         sd      pv,2*8(sp)
627         sd      ra,3*8(sp)
628         sd      t3,4*8(sp)
629
630         move    a0,xptr
631         ald     a1,MethodPointer(pv)
632         move    a2,xpc
633 /*      move    a3,t3 */
634         addu    a3,zero,1
635         jal     builtin_trace_exception /* trace_exception(xptr,methodptr)        */
636         
637         ld      xptr,0*8(sp)          /* restore used register                    */
638         ld      xpc,1*8(sp)
639         ld      pv,2*8(sp)
640         ld      ra,3*8(sp)
641         ld      t3,4*8(sp)
642         aaddiu  sp,sp,6*8             /* deallocate stack                         */
643         
644         lw      t0,ExTableSize(pv)    /* t0 = exception table size                */
645         beqz    t0,empty_table        /* if empty table skip                      */
646         aaddiu  t1,pv,ExTableStart    /* t1 = start of exception table            */
647
648 ex_table_loop:
649         ald     t2,ExStartPC(t1)      /* t2 = exception start pc                  */
650         slt     t2,xpc,t2             /* t2 = (xpc < startpc)                     */
651         bnez    t2,ex_table_cont      /* if (true) continue                       */
652         ald     t2,ExEndPC(t1)        /* t2 = exception end pc                    */
653         slt     t2,xpc,t2             /* t2 = (xpc < endpc)                       */
654         beqz    t2,ex_table_cont      /* if (false) continue                      */
655         ald     a1,ExCatchType(t1)    /* arg1 = exception catch type              */
656         beqz    a1,ex_handle_it       /* NULL catches everything                  */
657
658         ald     a0,offobjvftbl(xptr)  /* a0 = vftblptr(xptr)                      */
659         ald     a1,offclassvftbl(a1)  /* a1 = vftblptr(catchtype) class (not obj) */
660         lw      a0,offbaseval(a0)     /* a0 = baseval(xptr)                       */
661         lw      v0,offbaseval(a1)     /* a2 = baseval(catchtype)                  */
662         lw      a1,offdiffval(a1)     /* a1 = diffval(catchtype)                  */
663         subu    a0,a0,v0              /* a0 = baseval(xptr) - baseval(catchtype)  */
664         sltu    v0,a1,a0              /* v0 = xptr is instanceof catchtype        */
665         bnez    v0,ex_table_cont      /* if (false) continue                      */
666
667 ex_handle_it:
668
669         ald     xpc,ExHandlerPC(t1)   /* xpc = exception handler pc               */
670
671         beqz    t3,ex_jump            /* if (!(no stack unwinding) skip           */
672
673         ld      v0,0*8(sp)            /* restore possible used registers          */
674         ld      t0,1*8(sp)            /* also registers used by trace_exception   */
675         ld      t1,2*8(sp)
676         ld      t2,3*8(sp)
677         ld      t3,4*8(sp)
678         ld      t4,5*8(sp)
679         ld      a0,6*8(sp)
680         ld      a1,7*8(sp)
681         ld      a2,8*8(sp)
682         ld      a3,9*8(sp)
683         ld      a4,10*8(sp)
684         ld      a5,11*8(sp)
685         ld      a6,12*8(sp)
686         ld      a7,13*8(sp)
687         
688         aaddiu  sp,sp,14*8            /* deallocate stack                         */
689
690 ex_jump:
691         jr      xpc                   /* jump to the handler                      */
692
693 ex_table_cont:
694         aaddiu  t1,t1,ExEntrySize     /* next exception table entry               */
695         addiu   t0,t0,-1              /* decrement entry counter                  */
696         bgtz    t0,ex_table_loop      /* if (t0 > 0) next entry                   */
697
698 empty_table:
699         beqz    t3,ex_already_cleared /* if here the first time, then             */
700         aaddiu  sp,sp,14*8            /* deallocate stack and                     */
701         move    t3,zero               /* clear the no unwind flag                 */
702 ex_already_cleared:
703         lw      t0,IsSync(pv)         /* t0 = SyncOffset                          */
704         beqz    t0,no_monitor_exit    /* if zero no monitorexit                   */
705         aaddu   t0,sp,t0              /* add stackptr to Offset                   */
706         ald     a0,-8(t0)             /* load monitorexit pointer                 */
707
708         aaddiu  sp,sp,-8*8            /* allocate stack                           */
709         sd      t0,0*8(sp)            /* save used register                       */
710         sd      t1,1*8(sp)
711         sd      t3,2*8(sp)
712         sd      xptr,3*8(sp)
713         sd      xpc,4*8(sp)
714         sd      pv,5*8(sp)
715         sd      ra,6*8(sp)
716
717         jal     builtin_monitorexit   /* builtin_monitorexit(objectptr)           */
718         
719         ld      t0,0*8(sp)            /* restore used register                    */
720         ld      t1,1*8(sp)
721         ld      t3,2*8(sp)
722         ld      xptr,3*8(sp)
723         ld      xpc,4*8(sp)
724         ld      pv,5*8(sp)
725         ld      ra,6*8(sp)
726         aaddiu  sp,sp,8*8             /* deallocate stack                         */
727
728 no_monitor_exit:
729         lw      t0,FrameSize(pv)      /* t0 = frame size                          */
730         aaddu   sp,sp,t0              /* unwind stack                             */
731         move    t0,sp                 /* t0 = pointer to save area                */
732         lw      t1,IsLeaf(pv)         /* t1 = is leaf procedure                   */
733         bnez    t1,ex_no_restore      /* if (leaf) skip                           */
734         ld      ra,-8(t0)             /* restore ra                               */
735         aaddiu  t0,t0,-8              /* t0--                                     */
736 ex_no_restore:
737         move    xpc,ra                /* the new xpc is ra                        */
738         lw      t1,IntSave(pv)        /* t1 = saved int register count            */
739         ala     t2,ex_int2            /* t2 = current pc                          */
740         sll     t1,t1,2               /* t1 = register count * 4                  */
741         asubu   t2,t2,t1              /* t2 = ex_int_sav - 4 * register count     */
742         jr      t2                    /* jump to save position                    */
743         ld      s0,-8*8(t0)
744         ld      s1,-7*8(t0)
745         ld      s2,-6*8(t0)
746         ld      s3,-5*8(t0)
747         ld      s4,-4*8(t0)
748         ld      s5,-3*8(t0)
749         ld      s6,-2*8(t0)
750         ld      s7,-1*8(t0)
751 ex_int2:
752         sll     t1,t1,1               /* t1 = register count * 4 * 2              */
753         asubu   t0,t0,t1              /* t0 = t0 - 8 * register count             */
754
755         lw      t1,FltSave(pv)        /* t1 = saved flt register count            */
756         ala     t2,ex_flt2            /* t2 = current pc                          */
757         sll     t1,t1,2               /* t1 = register count * 4                  */
758         asubu   t2,t2,t1              /* t2 = ex_int_sav - 4 * register count     */
759         jr      t2                    /* jump to save position                    */
760         ldc1    fs0,-4*8(t0)
761         ldc1    fs1,-3*8(t0)
762         ldc1    fs2,-2*8(t0)
763         ldc1    fs3,-1*8(t0)
764 ex_flt2:
765         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
766         sll     t0,t0,16
767         sra     t0,t0,16              /* isolate offset                           */
768         aaddu   pv,t0,ra              /* compute update address                   */
769         b       ex_stack_loop
770
771         .end    asm_handle_nat_exception
772
773
774 /********************* asm_check_clinit ****************************************
775 *                                                                              *
776 *   Checks if class is initialized. If not, do it right now.                   *
777 *                                                                              *
778 *******************************************************************************/
779                 
780     .ent    asm_check_clinit
781 asm_check_clinit:
782         lw      itmp2,offclassinit(itmp1)
783         bnez    itmp2,L_is_initialized
784         
785         daddiu  sp,sp,-18*8
786         sd      ra,0*8(sp)
787         sd      a0,1*8(sp)            /* save argument registers for leaf funcs   */
788         sd      a1,2*8(sp)
789         sd      a2,3*8(sp)
790         sd      a3,4*8(sp)
791         sd      a4,5*8(sp)
792         sd      a5,6*8(sp)
793         sd      a6,7*8(sp)
794         sd      a7,8*8(sp)
795         sdc1    fa0,9*8(sp)
796         sdc1    fa1,10*8(sp)
797         sdc1    fa2,11*8(sp)
798         sdc1    fa3,12*8(sp)
799         sdc1    fa4,13*8(sp)
800         sdc1    fa5,14*8(sp)
801         sdc1    fa6,15*8(sp)
802         sdc1    fa7,16*8(sp)
803                 
804         move    a0,itmp1
805         jal     class_init
806                 
807         ld      ra,0*8(sp)
808         ld      a0,1*8(sp)            /* restore argument registers               */
809         ld      a1,2*8(sp)
810         ld      a2,3*8(sp)
811         ld      a3,4*8(sp)
812         ld      a4,5*8(sp)
813         ld      a5,6*8(sp)
814         ld      a6,7*8(sp)
815         ld      a7,8*8(sp)
816         ldc1    fa0,9*8(sp)
817         ldc1    fa1,10*8(sp)
818         ldc1    fa2,11*8(sp)
819         ldc1    fa3,12*8(sp)
820         ldc1    fa4,13*8(sp)
821         ldc1    fa5,14*8(sp)
822         ldc1    fa6,15*8(sp)
823         ldc1    fa7,16*8(sp)
824         daddiu  sp,sp,18*8
825         
826 L_is_initialized:
827         move    itmp1,ra              /* now patch the calling code               */
828         daddiu  itmp1,itmp1,-4*4      /* go back 4 instructions                   */
829         lui     itmp2,0x1000          /* b                                        */
830         daddiu  itmp2,itmp2,3         /* jump over 3 instructions                 */
831         sw      itmp2,0(itmp1)        /* store the new branch: br +3              */
832         sw      zero,4(itmp1)         /* and a nop delay slot                     */
833                 
834         j       ra
835                 
836         .end    asm_check_clinit
837
838                 
839 /********************* function asm_builtin_monitorenter ***********************
840 *                                                                              *
841 *   Does null check and calls monitorenter or throws an exception              *
842 *                                                                              *
843 *******************************************************************************/
844
845         .ent    asm_builtin_monitorenter
846 asm_builtin_monitorenter:
847
848         beqz    a0,nb_monitorenter        /* if (null) throw exception            */
849         ala     t9,builtin_monitorenter   /* else call builtin_monitorenter       */
850         j       t9
851
852 nb_monitorenter:
853         ald     xptr,proto_java_lang_NullPointerException
854         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
855         b       asm_handle_nat_exception
856         .end    asm_builtin_monitorenter
857
858
859 /********************* function asm_builtin_monitorexit ************************
860 *                                                                              *
861 *   Does null check and calls monitorexit or throws an exception               *
862 *                                                                              *
863 *******************************************************************************/
864
865         .ent    asm_builtin_monitorexit
866 asm_builtin_monitorexit:
867
868         beqz    a0,nb_monitorexit         /* if (null) throw exception            */
869         ala     t9,builtin_monitorexit    /* else call builtin_monitorexit        */
870         j       t9
871
872 nb_monitorexit:
873         ald     xptr,proto_java_lang_NullPointerException
874         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
875         b       asm_handle_nat_exception
876         .end    asm_builtin_monitorexit
877
878
879 /************************ function asm_builtin_idiv ****************************
880 *                                                                              *
881 *   Does null check and calls idiv or throws an exception                      *
882 *                                                                              *
883 *******************************************************************************/
884
885         .ent    asm_builtin_idiv
886 asm_builtin_idiv:
887
888         beqz    a1,nb_idiv                /* if (null) throw exception            */
889         ala     itmp3,builtin_idiv        /* else call builtin_idiv               */
890         j       itmp3
891
892 nb_idiv:
893         ald     xptr,proto_java_lang_ArithmeticException
894         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
895         b       asm_handle_nat_exception
896         .end    asm_builtin_idiv
897
898
899 /************************ function asm_builtin_ldiv ****************************
900 *                                                                              *
901 *   Does null check and calls ldiv or throws an exception                      *
902 *                                                                              *
903 *******************************************************************************/
904
905         .ent    asm_builtin_ldiv
906 asm_builtin_ldiv:
907
908         beqz    a1,nb_ldiv                /* if (null) throw exception            */
909         ala     itmp3,builtin_ldiv        /* else call builtin_ldiv               */
910         j       itmp3
911
912 nb_ldiv:
913         ald     xptr,proto_java_lang_ArithmeticException
914         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
915         b       asm_handle_nat_exception
916         .end    asm_builtin_ldiv
917
918
919 /************************ function asm_builtin_irem ****************************
920 *                                                                              *
921 *   Does null check and calls irem or throws an exception                      *
922 *                                                                              *
923 *******************************************************************************/
924
925         .ent    asm_builtin_irem
926 asm_builtin_irem:
927
928         beqz    a1,nb_irem                /* if (null) throw exception            */
929         ala     t9,builtin_irem           /* else call builtin_irem               */
930         j       t9
931
932 nb_irem:
933         ald     xptr,proto_java_lang_ArithmeticException
934         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
935         b       asm_handle_nat_exception
936         .end    asm_builtin_irem
937
938
939 /************************ function asm_builtin_lrem ****************************
940 *                                                                              *
941 *   Does null check and calls lrem or throws an exception                      *
942 *                                                                              *
943 *******************************************************************************/
944
945         .ent    asm_builtin_lrem
946 asm_builtin_lrem:
947
948         beqz    a1,nb_lrem                /* if (null) throw exception            */
949         ala     t9,builtin_lrem           /* else call builtin_lrem               */
950         j       t9
951
952 nb_lrem:
953         ald     xptr,proto_java_lang_ArithmeticException
954         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
955         b       asm_handle_nat_exception
956         .end    asm_builtin_lrem
957
958
959 /******************* function asm_builtin_checkarraycast ***********************
960 *                                                                              *
961 *   Does the cast check and eventually throws an exception                     *
962 *                                                                              *
963 *******************************************************************************/
964
965         .ent    asm_builtin_checkarraycast
966 asm_builtin_checkarraycast:
967
968         aaddiu  sp,sp,-16                 /* allocate stack space                 */
969         sd      ra,0(sp)                  /* save return address                  */
970         sd      a0,8(sp)                  /* save object pointer                  */
971         jal     builtin_checkarraycast    /* builtin_checkarraycast               */
972         beqz    v0,nb_carray_throw        /* if (false) throw exception           */
973         ld      ra,0(sp)                  /* restore return address               */
974         ld      v0,8(sp)                  /* return object pointer                */
975         aaddiu  sp,sp,16                  /* deallocate stack                     */
976         j       ra                        /* return                               */
977
978 nb_carray_throw:
979         ald     xptr,proto_java_lang_ClassCastException
980         ld      ra,0(sp)                  /* restore return address               */
981         aaddiu  sp,sp,16                  /* free stack space                     */
982         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
983         b       asm_handle_nat_exception
984         .end    asm_builtin_checkarraycast
985
986
987 /********************* function asm_builtin_checkcast **************************
988 *                                                                              *
989 *   Does the cast check and eventually throws an exception                     *
990 *                                                                              *
991 *******************************************************************************/
992
993         .ent    asm_builtin_checkcast
994 asm_builtin_checkcast:
995
996         aaddiu  sp,sp,-16                 /* allocate stack space                 */
997         sd      ra,0(sp)                  /* save return address                  */
998         sd      a0,8(sp)                  /* save object pointer                  */
999         jal     builtin_checkcast         /* builtin_checkcast                    */
1000         beqz    v0,nb_ccast_throw         /* if (false) throw exception           */
1001         ld      ra,0(sp)                  /* restore return address               */
1002         ld      v0,8(sp)                  /* return object pointer                */
1003         aaddiu  sp,sp,16                  /* deallocate stack                     */
1004         j       ra                        /* return                               */
1005
1006 nb_ccast_throw:
1007         ald     xptr,proto_java_lang_ClassCastException
1008         ld      ra,0(sp)                  /* restore return address               */
1009         aaddiu  sp,sp,16                  /* free stack space                     */
1010         aaddiu  xpc,ra,-4                 /* faulting address is return adress - 4*/
1011         b       asm_handle_nat_exception
1012         .end    asm_builtin_checkcast
1013
1014
1015 /******************* function asm_builtin_aastore ******************************
1016 *                                                                              *
1017 *   Does the cast check and eventually throws an exception                     *
1018 *   a0 = arrayref, a1 = index, a2 = value                                      *
1019 *                                                                              *
1020 *******************************************************************************/
1021
1022         .ent    asm_builtin_aastore
1023 asm_builtin_aastore:
1024
1025         beqz    a0,nb_aastore_null        /* if null pointer throw exception      */
1026         lw      t0,offarraysize(a0)       /* load size                            */
1027         aaddiu  sp,sp,-32                 /* allocate stack space                 */
1028         sd      ra,0(sp)                  /* save return address                  */
1029         asll    t1,a1,ashift              /* add index*8 to arrayref              */
1030         aaddu   t1,a0,t1                  /* add index * ashift to arrayref       */
1031         sltu    t0,a1,t0                  /* do bound check                       */
1032         beqz    t0,nb_aastore_bound       /* if out of bounds throw exception     */
1033         move    a1,a2                     /* object is second argument            */
1034         sd      t1,8(sp)                  /* save store position                  */
1035         sd      a1,16(sp)                 /* save object                          */
1036         jal     builtin_canstore          /* builtin_canstore(arrayref,object)    */
1037         ld      ra,0(sp)                  /* restore return address               */
1038         ld      a0,8(sp)                  /* restore store position               */
1039         ld      a1,16(sp)                 /* restore object                       */
1040         aaddiu  sp,sp,32                  /* free stack space                     */
1041         beqz    v0,nb_aastore_throw       /* if (false) throw exception           */
1042         ast     a1,offobjarrdata(a0)      /* store objectptr in array             */
1043         j       ra                        /* return                               */
1044
1045 nb_aastore_null:
1046         ald     xptr,proto_java_lang_NullPointerException
1047         move    xpc,ra                    /* faulting address is return adress    */
1048         b       asm_handle_nat_exception
1049
1050 nb_aastore_bound:
1051         ald     xptr,proto_java_lang_ArrayIndexOutOfBoundsException
1052         aaddiu  sp,sp,32                  /* free stack space                     */
1053         move    xpc,ra                    /* faulting address is return adress    */
1054         b       asm_handle_nat_exception
1055
1056 nb_aastore_throw:
1057         ald     xptr,proto_java_lang_ArrayStoreException
1058         move    xpc,ra                    /* faulting address is return adress    */
1059         b       asm_handle_nat_exception
1060
1061         .end    asm_builtin_aastore
1062
1063
1064 /******************* function asm_initialize_thread_stack **********************
1065 *                                                                              *
1066 *   u1* asm_initialize_thread_stack (void *func, u1 *stack);                   *
1067 *                                                                              *
1068 *   initialize a thread stack                                                  *
1069 *                                                                              *
1070 *******************************************************************************/
1071
1072         .ent    asm_initialize_thread_stack
1073 asm_initialize_thread_stack:
1074
1075         aaddiu  a1,a1,-14*8     /* allocate save area                             */
1076         sd      zero, 0*8(a1)   /* s0 initalize thread area                       */
1077         sd      zero, 1*8(a1)   /* s1                                             */
1078         sd      zero, 2*8(a1)   /* s2                                             */
1079         sd      zero, 3*8(a1)   /* s3                                             */
1080         sd      zero, 4*8(a1)   /* s4                                             */
1081         sd      zero, 5*8(a1)   /* s5                                             */
1082         sd      zero, 6*8(a1)   /* s6                                             */
1083         sd      zero, 7*8(a1)   /* s7                                             */
1084         sd      zero, 8*8(a1)   /* s8                                             */
1085         sd      zero, 9*8(a1)   /* fs0                                            */
1086         sd      zero,10*8(a1)   /* fs1                                            */
1087         sd      zero,11*8(a1)   /* fs2                                            */
1088         sd      zero,12*8(a1)   /* fs3                                            */
1089         sd      a0, 13*8(a1)
1090         move    v0,a1
1091         j       ra              /* return                                         */
1092         .end    asm_initialize_thread_stack
1093
1094
1095 /******************* function asm_perform_threadswitch *************************
1096 *                                                                              *
1097 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
1098 *                                                                              *
1099 *   performs a threadswitch                                                    *
1100 *                                                                              *
1101 *******************************************************************************/
1102
1103         .ent    asm_perform_threadswitch
1104 asm_perform_threadswitch:
1105
1106         aaddiu  sp,sp,-14*8     /* allocate new stack                             */
1107         sd      s0,  0*8(sp)    /* save saved registers of old thread             */
1108         sd      s1,  1*8(sp)
1109         sd      s2,  2*8(sp)
1110         sd      s3,  3*8(sp)
1111         sd      s4,  4*8(sp)
1112         sd      s5,  5*8(sp)
1113         sd      s6,  6*8(sp)
1114         sd      s7,  7*8(sp)
1115         sd      s8,  8*8(sp)
1116         sdc1    fs0, 9*8(sp)
1117         sdc1    fs1,10*8(sp)
1118         sdc1    fs2,11*8(sp)
1119         sdc1    fs3,12*8(sp)
1120         sd      ra, 13*8(sp)
1121         ast     sp,0(a0)        /* save old stack pointer                         */
1122         ast     sp,0(a2)        /* stackTop = old stack pointer                   */
1123         ald     sp,0(a1)        /* load new stack pointer                         */
1124         ld      s0,  0*8(sp)    /* load saved registers of new thread             */
1125         ld      s1,  1*8(sp)
1126         ld      s2,  2*8(sp)
1127         ld      s3,  3*8(sp)
1128         ld      s4,  4*8(sp)
1129         ld      s5,  5*8(sp)
1130         ld      s6,  6*8(sp)
1131         ld      s7,  7*8(sp)
1132         ld      s8,  8*8(sp)
1133         ldc1    fs0, 9*8(sp)
1134         ldc1    fs1,10*8(sp)
1135         ldc1    fs2,11*8(sp)
1136         ldc1    fs3,12*8(sp)
1137         ld      ra, 13*8(sp)
1138         aaddiu  sp,sp,14*8      /* deallocate new stack                           */
1139         move    itmp3, ra
1140         j       ra              /* return                                         */
1141         .end    asm_perform_threadswitch
1142
1143
1144 /********************* function asm_switchstackandcall *************************
1145 *                                                                              *
1146 *  void asm_switchstackandcall (void *stack, void *func, void **stacktopsave); *
1147 *                                                                              *
1148 *   Switches to a new stack, calls a function and switches back.               *
1149 *       a0      new stack pointer                                              *
1150 *       a1      function pointer                                               *
1151 *               a2              pointer to variable where stack top should be stored           *
1152 *                                                                              *
1153 *******************************************************************************/
1154
1155         .ent    asm_switchstackandcall
1156 asm_switchstackandcall:
1157         aaddiu  a0,a0,-16       /* allocate new stack                             */
1158         sd      ra,0(a0)        /* save return address on new stack               */
1159         sd      sp,8(a0)        /* save old stack pointer on new stack            */
1160         sd      sp,0(a2)        /* save old stack pointer to variable             */
1161         move    sp,a0           /* switch to new stack                            */
1162         
1163         move    itmp3,a1
1164         move    a0,a3
1165         jalr    itmp3           /* and call function                              */
1166
1167         ld      ra,0(sp)        /* load return address                            */
1168         ld      sp,8(sp)        /* switch to old stack                            */
1169
1170         j       ra              /* return                                         */
1171
1172         .end    asm_switchstackandcall
1173
1174         .ent    asm_getcallingmethod
1175 asm_getcallingmethod:
1176         li      v0,0
1177         j       ra
1178         .end    asm_getcallingmethod
1179
1180
1181 /*
1182  * These are local overrides for various environment variables in Emacs.
1183  * Please do not remove this and leave it at the end of the file, where
1184  * Emacs will automagically detect them.
1185  * ---------------------------------------------------------------------
1186  * Local variables:
1187  * mode: asm
1188  * indent-tabs-mode: t
1189  * c-basic-offset: 4
1190  * tab-width: 4
1191  * End:
1192  */