* Implemented stacktraces
[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 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28
29    Changes: Christian Thalinger
30
31    $Id: asmpart.S 3023 2005-07-12 23:49:49Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include "vm/jit/mips/offsets.h"
39 #include "vm/jit/mips/asmoffsets.h"
40 #include "vm/jit/mips/md-asm.h"
41
42
43         .text
44         .set    noat
45
46
47 /* exported functions and variables *******************************************/
48
49         .globl asm_calljavafunction
50         .globl asm_calljavafunction_int
51
52         .globl asm_calljavafunction2
53         .globl asm_calljavafunction2int
54         .globl asm_calljavafunction2long
55         .globl asm_calljavafunction2float
56         .globl asm_calljavafunction2double
57
58         .globl asm_call_jit_compiler
59         .globl asm_handle_exception
60         .globl asm_handle_nat_exception
61
62         .globl asm_wrapper_patcher
63
64         .globl asm_perform_threadswitch
65         .globl asm_initialize_thread_stack
66         .globl asm_switchstackandcall
67         .globl asm_getclassvalues_atomic
68         .globl asm_criticalsections
69
70         .globl compare_and_swap
71
72
73 /********************* function asm_calljavafunction ***************************
74 *                                                                              *
75 *   This function calls a Java-method (which possibly needs compilation)       *
76 *   with up to 4 address parameters.                                           *
77 *                                                                              *
78 *   This functions calls the JIT-compiler which eventually translates the      *
79 *   method into machine code.                                                  *
80 *                                                                              *
81 *   A possibly throwed exception will be returned to the caller as function    *
82 *   return value, so the java method cannot return a fucntion value (this      *
83 *   function usually calls 'main' and '<clinit>' which do not return a         *
84 *   function value).                                                           *
85 *                                                                              *
86 *   C-prototype:                                                               *
87 *    javaobject_header *asm_calljavafunction (methodinfo *m,                   *
88 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
89 *                                                                              *
90 *******************************************************************************/
91
92         .ent    asm_calljavafunction
93
94         .align  3
95
96         .dword  0                         /* catch type all                       */
97         .dword  calljava_xhandler         /* handler pc                           */
98         .dword  calljava_xhandler         /* end pc                               */
99         .dword  asm_calljavafunction      /* start pc                             */
100         .word   1                         /* extable size                         */
101         .word   0                         /* ALIGNMENT PADDING                    */
102         .dword  0                         /* line number table start              */
103         .dword  0                         /* line number table size               */
104         .word   0                         /* ALIGNMENT PADDING                    */
105         .word   0                         /* fltsave                              */
106         .word   0                         /* intsave                              */
107         .word   0                         /* isleaf                               */
108         .word   0                         /* IsSync                               */
109         .word   10*8                      /* frame size                           */
110         .dword  0                         /* method pointer (pointer to name)     */
111
112 asm_calljavafunction:
113 asm_calljavafunction_int:
114         aaddiu  sp,sp,-10*8               /* allocate stack space                 */
115         ast     ra,0(sp)                  /* save return address                  */
116
117         .set    noreorder
118
119         bal     call_java_pc
120         ast     pv,3*8(sp)                /* procedure vector (delay slot)        */
121 call_java_pc:
122         aaddiu  pv,ra,-4*4
123
124         .set    reorder
125         
126         sdc1    fss0,4*8(sp)              /* save non JavaABI saved flt registers */
127         sdc1    fss1,5*8(sp)
128         sdc1    fss2,6*8(sp)
129         sdc1    fss3,7*8(sp)
130         sdc1    fss4,8*8(sp)
131         sdc1    fss5,9*8(sp)
132
133         move    itmp1,a0                  /* pass method pointer via tmp1         */
134
135         move    a0,a1                     /* pass the remaining parameters        */
136         move    a1,a2
137         move    a2,a3
138         move    a3,a4
139
140         ala     mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
141         ast     mptr,1*8(sp)              /* store function address               */
142         move    mptr,sp                   /* set method pointer                   */
143
144         .set    noreorder
145
146         ald     pv,1*8(mptr)              /* method call as in Java               */
147         jalr    pv                        /* call JIT compiler                    */
148         nop
149         aaddiu  pv,ra,-22*4               /* recompute procedure vector           */
150
151         .set    reorder
152
153 calljava_return:
154         ald     ra,0(sp)                  /* restore return address               */
155         ald     pv,3*8(sp)                /* restore procedure vector             */
156
157         ldc1    fss0,4*8(sp)              /* restore non JavaABI saved flt regs   */
158         ldc1    fss1,5*8(sp)
159         ldc1    fss2,6*8(sp)
160         ldc1    fss3,7*8(sp)
161         ldc1    fss4,8*8(sp)
162         ldc1    fss5,9*8(sp)
163
164         aaddiu  sp,sp,10*8                /* free stack space                     */
165         j       ra                        /* return                               */
166
167 calljava_xhandler:
168         move    a0,itmp1                  
169         jal     builtin_throw_exception
170         move    v0,zero                   /* clear return value for exception     */
171         b       calljava_return
172
173         .end    asm_calljavafunction
174
175
176         .ent    asm_calljavafunction2
177
178         .align  3
179
180         .dword  0                         /* catch type all                       */
181         .dword  calljava_xhandler2        /* handler pc                           */
182         .dword  calljava_xhandler2        /* end pc                               */
183         .dword  asm_calljavafunction2     /* start pc                             */
184         .word   1                         /* extable size                         */
185         .word   0                         /* ALIGNMENT PADDING                    */
186         .dword  0                         /* line number table start              */
187         .dword  0                         /* line number table size               */
188         .word   0                         /* ALIGNMENT PADDING                    */
189         .word   0                         /* fltsave                              */
190         .word   1                         /* intsave                              */
191         .word   0                         /* isleaf                               */
192         .word   0                         /* IsSync                               */
193         .word   12*8                      /* frame size                           */
194         .dword  0                         /* method pointer (pointer to name)     */
195
196 asm_calljavafunction2:
197 asm_calljavafunction2int:
198 asm_calljavafunction2long:
199 asm_calljavafunction2float:
200 asm_calljavafunction2double:
201         aaddiu  sp,sp,-12*8               /* allocate stack space (only 11 needed)*/
202         ast     ra,0(sp)                  /* save return address                  */
203
204         .set    noreorder
205         bal     call_java_pc2
206         ast     pv,1*8(sp)                /* procedure vector                     */
207 call_java_pc2:
208         aaddiu  pv,ra,-4*4
209         ast     s7,3*8(sp)
210
211         .set    reorder
212         
213         sdc1    fss0,5*8(sp)              /* save non JavaABI saved flt registers */
214         sdc1    fss1,6*8(sp)
215         sdc1    fss2,7*8(sp)
216         sdc1    fss3,8*8(sp)
217         sdc1    fss4,9*8(sp)
218         sdc1    fss5,10*8(sp)
219
220         ast     a0,4*8(sp)                /* save method pointer for compiler     */
221
222         move    t0,a3
223         move    s7,a1
224         blez    s7,calljava_argsloaded
225
226         ald     a0,offjniitem(t0)
227         ldc1    fa0,offjniitem(t0)
228         daddi   s7,s7,-1
229         blez    s7,calljava_argsloaded
230
231         ald     a1,offjniitem+sizejniblock*1(t0)
232         ldc1    fa1,offjniitem+sizejniblock*1(t0)
233         daddi   s7,s7,-1
234         blez    s7,calljava_argsloaded
235
236         ald     a2,offjniitem+sizejniblock*2(t0)
237         ldc1    fa2,offjniitem+sizejniblock*2(t0)
238         daddi   s7,s7,-1
239         blez    s7,calljava_argsloaded
240
241         ald     a3,offjniitem+sizejniblock*3(t0)
242         ldc1    fa3,offjniitem+sizejniblock*3(t0)
243         daddi   s7,s7,-1
244         blez    s7,calljava_argsloaded
245
246         ald     a4,offjniitem+sizejniblock*4(t0)
247         ldc1    fa4,offjniitem+sizejniblock*4(t0)
248         daddi   s7,s7,-1
249         blez    s7,calljava_argsloaded
250
251         ald     a5,offjniitem+sizejniblock*5(t0)
252         ldc1    fa5,offjniitem+sizejniblock*5(t0)
253         daddi   s7,s7,-1
254         blez    s7,calljava_argsloaded
255
256         ald     a6,offjniitem+sizejniblock*6(t0)
257         ldc1    fa6,offjniitem+sizejniblock*6(t0)
258         daddi   s7,s7,-1
259         blez    s7,calljava_argsloaded
260
261         ald     a7,offjniitem+sizejniblock*7(t0)
262         ldc1    fa7,offjniitem+sizejniblock*7(t0)
263         daddi   s7,s7,-1
264                 
265 calljava_argsloaded:
266         move    t8,sp                      /* save stack pointer                  */
267         blez    s7,calljava_nocopy
268         subu    t1,zero,s7
269         sll     t2,t1,3
270         aaddu   sp,sp,t2
271         aaddu   t2,t2,t8
272
273 calljava_copyloop:
274     ald     t3,offjniitem+sizejniblock*8(t0)
275         ast     t3,0(t2)
276         ala     t1,1(t1)
277         ala     t0,sizejniblock(t0)
278         ala     t2,8(t2)
279         bnez    t1,calljava_copyloop
280
281 calljava_nocopy:
282         ald     itmp1,4*8(t8)             /* pass method pointer via itmp1        */
283
284         ala     mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
285         ast     mptr,2*8(sp)              /* store function address               */
286         ala     mptr,1*8(sp)              /* set method pointer                   */
287
288         .set    noreorder
289
290         ald     pv,1*8(mptr)              /* method call as in Java               */
291         jalr    pv                        /* call JIT compiler                    */
292         nop
293         aaddiu  pv,ra,-76*4               /* recompute procedure vector           */
294
295         .set    reorder
296
297 calljava_return2:
298         ald     ra,0(sp)                  /* restore return address               */
299         ald     pv,8(sp)                  /* restore procedure vector             */
300         ald     s7,3*8(sp)
301
302         ldc1    fss0,5*8(sp)              /* restore non JavaABI saved flt regs   */
303         ldc1    fss1,6*8(sp)
304         ldc1    fss2,7*8(sp)
305         ldc1    fss3,8*8(sp)
306         ldc1    fss4,9*8(sp)
307         ldc1    fss5,10*8(sp)
308
309         aaddiu  sp,sp,12*8                /* free stack space                     */
310         j       ra                        /* return                               */
311
312 calljava_xhandler2:
313         asll    s7,s7,3
314         aaddu   sp,s7,sp
315         move    a0,itmp1                  
316         jal     builtin_throw_exception
317         b       calljava_return2
318
319         .end    asm_calljavafunction2
320
321
322 /****************** function asm_call_jit_compiler *****************************
323 *                                                                              *
324 *   invokes the compiler for untranslated JavaVM methods.                      *
325 *                                                                              *
326 *   Register REG_ITEMP1 contains a pointer to the method info structure        *
327 *   (prepared by createcompilerstub). Using the return address in R31 and the  *
328 *   offset in the LDA instruction or using the value in methodptr R25 the      *
329 *   patching address for storing the method address can be computed:           *
330 *                                                                              *
331 *   method address was either loaded using                                     *
332 *   M_ALD (REG_PV, REG_PV, a)        ; invokestatic/special    ($28)           *
333 *   M_JSR (REG_RA, REG_PV);                                                    *
334 *   M_NOP                                                                      *
335 *   M_LDA (REG_PV, REG_RA, val)                                                *
336 *   or                                                                         *
337 *   M_ALD (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($25)           *
338 *   M_JSR (REG_RA, REG_PV);                                                    *
339 *   M_NOP                                                                      *
340 *   in the static case the method pointer can be computed using the            *
341 *   return address and the lda function following the jmp instruction          *
342 *                                                                              *
343 *******************************************************************************/
344
345
346         .ent    asm_call_jit_compiler
347
348 asm_call_jit_compiler:
349         lw      t0,-12(ra)            /* load instruction LD PV,xxx($y)           */
350         srl     t0,t0,21              /* shift right register number $y           */
351         and     t0,t0,31              /* isolate register number                  */
352         addiu   t0,t0,-mptrreg        /* test for REG_METHODPTR                   */
353         beqz    t0,noregchange       
354
355         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
356         sll     t0,t0,16
357         sra     t0,t0,16              /* isolate offset                           */
358         aaddu   mptr,t0,ra            /* compute update address                   */
359
360 noregchange:
361         aaddiu  sp,sp,-18*8           /* allocate stack space                     */
362
363         SAVE_ARGUMENT_REGISTERS(0)
364
365         sd      mptr,16*8(sp)         /* save method pointer                      */
366         sd      ra,17*8(sp)           /* save return address                      */
367
368         move    a0,itmp1              /* pass 'methodinfo' pointer to             */
369         jal     jit_compile           /* jit compiler                             */
370
371         RESTORE_ARGUMENT_REGISTERS(0)
372
373         ld      mptr,16*8(sp)         /* restore method pointer                   */
374         ld      ra,17*8(sp)           /* restore return address                   */
375         aaddiu  sp,sp,18*8            /* deallocate stack area                    */
376
377         beqz    v0,L_asm_call_jit_compiler_exception
378
379         lw      t0,-12(ra)            /* load instruction LDQ PV,xxx($yy)         */
380         sll     t0,t0,16
381         sra     t0,t0,16              /* isolate offset                           */
382
383         aaddu   t0,t0,mptr            /* compute update address via method pointer*/
384         ast     v0,0(t0)              /* save new method address there            */
385
386         move    pv,v0                 /* move method address into pv              */
387
388         jr      pv                    /* and call method. The method returns      */
389                                       /* directly to the caller (ra).             */
390
391 L_asm_call_jit_compiler_exception:
392 #if 0
393 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
394         aaddiu  sp,sp,-2*8
395         ast     ra,0*8(sp)
396         jal     builtin_asm_get_exceptionptrptr
397         ald     ra,0*8(sp)
398         aaddiu  sp,sp,2*8
399 #else
400         la      v0,_exceptionptr
401 #endif
402         ald     xptr,0(v0)            /* get the exception pointer                */
403         ast     zero,0(v0)            /* clear the exception pointer              */
404 #endif
405
406         aaddiu  sp,sp,-2*8
407         ast     ra,0*8(sp)
408
409         move    a0,zero               /* fill in the correct stacktrace           */
410         aaddiu  a1,sp,2*8             /* pass sp of parent Java function          */
411         move    a2,ra                 /* pass ra to parent Java function          */
412         move    a3,a2                 /* xpc is the same as ra                    */
413         jal     stacktrace_extern_fillInStackTrace
414         move    xptr,v0
415
416         ald     ra,0*8(sp)
417         aaddiu  sp,sp,2*8
418
419         aaddiu  xpc,ra,-4             /* faulting address is return adress - 4    */
420         b       asm_handle_nat_exception
421
422         .end    asm_call_jit_compiler
423
424
425 /********************* function asm_handle_exception ***************************
426 *                                                                              *
427 *   This function handles an exception. It does not use the usual calling      *
428 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
429 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
430 *   the local exception table for a handler. If no one is found, it unwinds    *
431 *   stacks and continues searching the callers.                                *
432 *                                                                              *
433 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
434 *                                                                              *
435 *******************************************************************************/
436
437         .ent    asm_handle_nat_exception
438
439 asm_handle_nat_exception:
440         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
441         sll     t0,t0,16
442         sra     t0,t0,16              /* isolate offset                           */
443         aaddu   pv,t0,ra              /* compute update address                   */
444
445         .aent    asm_handle_exception
446
447 asm_handle_exception:
448         aaddiu  sp,sp,-14*8           /* allocate stack                           */
449
450         sd      v0,0*8(sp)            /* save possible used registers             */
451         sd      t0,1*8(sp)            /* also registers used by trace_exception   */
452         sd      t1,2*8(sp)
453         sd      t2,3*8(sp)
454         sd      t3,4*8(sp)
455         sd      t8,5*8(sp)
456         sd      a0,6*8(sp)
457         sd      a1,7*8(sp)
458         sd      a2,8*8(sp)
459         sd      a3,9*8(sp)
460         sd      a4,10*8(sp)
461         sd      a5,11*8(sp)
462         sd      a6,12*8(sp)
463         sd      a7,13*8(sp)
464
465         addu    t3,zero,1             /* set no unwind flag                       */
466 ex_stack_loop:
467         aaddiu  sp,sp,-6*8            /* allocate stack                           */
468         sd      xptr,0*8(sp)          /* save used registers                      */
469         sd      xpc,1*8(sp)
470         sd      pv,2*8(sp)
471         sd      ra,3*8(sp)
472         sd      t3,4*8(sp)
473
474         move    a0,xptr
475         ald     a1,MethodPointer(pv)
476         move    a2,xpc
477 /*      move    a3,t3 */
478         move    a3,zero
479         addu    a4,zero,1
480         jal     builtin_trace_exception /* trace_exception(xptr,methodptr)        */
481         
482         ld      xptr,0*8(sp)          /* restore used register                    */
483         ld      xpc,1*8(sp)
484         ld      pv,2*8(sp)
485         ld      ra,3*8(sp)
486         ld      t3,4*8(sp)
487         aaddiu  sp,sp,6*8             /* deallocate stack                         */
488         
489         lw      t0,ExTableSize(pv)    /* t0 = exception table size                */
490         beqz    t0,empty_table        /* if empty table skip                      */
491         aaddiu  t1,pv,ExTableStart    /* t1 = start of exception table            */
492
493 ex_table_loop:
494         ald     t2,ExStartPC(t1)      /* t2 = exception start pc                  */
495         sle     t2,t2,xpc             /* t2 = (startpc <= xpc)                    */
496         beqz    t2,ex_table_cont      /* if (false) continue                      */
497         ald     t2,ExEndPC(t1)        /* t2 = exception end pc                    */
498         slt     t2,xpc,t2             /* t2 = (xpc < endpc)                       */
499         beqz    t2,ex_table_cont      /* if (false) continue                      */
500         ald     a1,ExCatchType(t1)    /* arg1 = exception catch type              */
501         beqz    a1,ex_handle_it       /* NULL catches everything                  */
502
503         lw      itmp3,offclassloaded(a1)
504         bnez    itmp3,L_class_loaded
505
506         aaddiu  sp,sp,-8*8            /* allocate stack                           */
507         sd      t0,0*8(sp)            /* save used register                       */
508         sd      t1,1*8(sp)
509         sd      t3,2*8(sp)
510         sd      xptr,3*8(sp)
511         sd      xpc,4*8(sp)
512         sd      pv,5*8(sp)
513         sd      ra,6*8(sp)
514         sd      a1,7*8(sp)
515                 
516         move    a0,a1
517         jal     load_class_bootstrap
518                 
519         ld      t0,0*8(sp)            /* restore used register                    */
520         ld      t1,1*8(sp)
521         ld      t3,2*8(sp)
522         ld      xptr,3*8(sp)
523         ld      xpc,4*8(sp)
524         ld      pv,5*8(sp)
525         ld      ra,6*8(sp)
526         ld      a1,7*8(sp)
527         aaddiu  sp,sp,8*8             /* deallocate stack                         */
528         
529 L_class_loaded:
530         lw      itmp3,offclasslinked(a1)
531         aaddiu  sp,sp,-8*8            /* allocate stack                           */
532         sd      a1,7*8(sp)
533         bnez    itmp3,L_class_linked
534
535         sd      t0,0*8(sp)            /* save used register                       */
536         sd      t1,1*8(sp)
537         sd      t3,2*8(sp)
538         sd      xptr,3*8(sp)
539         sd      xpc,4*8(sp)
540         sd      pv,5*8(sp)
541         sd      ra,6*8(sp)
542                 
543         move    a0,a1
544         jal     link_class
545                 
546         ld      t0,0*8(sp)            /* restore used register                    */
547         ld      t1,1*8(sp)
548         ld      t3,2*8(sp)
549         ld      xptr,3*8(sp)
550         ld      xpc,4*8(sp)
551         ld      pv,5*8(sp)
552         ld      ra,6*8(sp)
553
554 L_class_linked:
555 _crit_restart1:
556         ld      a1,7*8(sp)
557 _crit_begin1:
558         ald     a0,offobjvftbl(xptr)  /* a0 = vftblptr(xptr)                      */
559         ald     a1,offclassvftbl(a1)  /* a1 = vftblptr(catchtype) class (not obj) */
560         lw      a0,offbaseval(a0)     /* a0 = baseval(xptr)                       */
561         lw      v0,offbaseval(a1)     /* a2 = baseval(catchtype)                  */
562         lw      a1,offdiffval(a1)     /* a1 = diffval(catchtype)                  */
563 _crit_end1:
564         subu    a0,a0,v0              /* a0 = baseval(xptr) - baseval(catchtype)  */
565         sltu    v0,a1,a0              /* v0 = xptr is instanceof catchtype        */
566         aaddiu  sp,sp,8*8             /* deallocate stack                         */
567         bnez    v0,ex_table_cont      /* if (false) continue                      */
568
569 ex_handle_it:
570         ald     xpc,ExHandlerPC(t1)   /* xpc = exception handler pc               */
571
572         beqz    t3,ex_jump            /* if (!(no stack unwinding) skip           */
573
574         ld      v0,0*8(sp)            /* restore possible used registers          */
575         ld      t0,1*8(sp)            /* also registers used by trace_exception   */
576         ld      t1,2*8(sp)
577         ld      t2,3*8(sp)
578         ld      t3,4*8(sp)
579         ld      t8,5*8(sp)
580         ld      a0,6*8(sp)
581         ld      a1,7*8(sp)
582         ld      a2,8*8(sp)
583         ld      a3,9*8(sp)
584         ld      a4,10*8(sp)
585         ld      a5,11*8(sp)
586         ld      a6,12*8(sp)
587         ld      a7,13*8(sp)
588         
589         aaddiu  sp,sp,14*8            /* deallocate stack                         */
590
591 ex_jump:
592         jr      xpc                   /* jump to the handler                      */
593
594 ex_table_cont:
595         aaddiu  t1,t1,ExEntrySize     /* next exception table entry               */
596         addiu   t0,t0,-1              /* decrement entry counter                  */
597         bgtz    t0,ex_table_loop      /* if (t0 > 0) next entry                   */
598
599 empty_table:
600         beqz    t3,ex_already_cleared /* if here the first time, then             */
601         aaddiu  sp,sp,14*8            /* deallocate stack and                     */
602         move    t3,zero               /* clear the no unwind flag                 */
603 ex_already_cleared:
604         lw      t0,IsSync(pv)         /* t0 = SyncOffset                          */
605         beqz    t0,no_monitor_exit    /* if zero no monitorexit                   */
606
607 #if defined(USE_THREADS)
608         aaddu   t0,sp,t0              /* add stackptr to Offset                   */
609         ald     a0,-8(t0)             /* load monitorexit pointer                 */
610
611         aaddiu  sp,sp,-8*8            /* allocate stack                           */
612         sd      t0,0*8(sp)            /* save used register                       */
613         sd      t1,1*8(sp)
614         sd      t3,2*8(sp)
615         sd      xptr,3*8(sp)
616         sd      xpc,4*8(sp)
617         sd      pv,5*8(sp)
618         sd      ra,6*8(sp)
619
620         jal     builtin_monitorexit   /* builtin_monitorexit(objectptr)           */
621         
622         ld      t0,0*8(sp)            /* restore used register                    */
623         ld      t1,1*8(sp)
624         ld      t3,2*8(sp)
625         ld      xptr,3*8(sp)
626         ld      xpc,4*8(sp)
627         ld      pv,5*8(sp)
628         ld      ra,6*8(sp)
629         aaddiu  sp,sp,8*8             /* deallocate stack                         */
630 #endif
631
632 no_monitor_exit:
633         lw      t0,FrameSize(pv)      /* t0 = frame size                          */
634         aaddu   sp,sp,t0              /* unwind stack                             */
635         move    t0,sp                 /* t0 = pointer to save area                */
636         lw      t1,IsLeaf(pv)         /* t1 = is leaf procedure                   */
637         bnez    t1,ex_no_restore      /* if (leaf) skip                           */
638         ld      ra,-8(t0)             /* restore ra                               */
639         aaddiu  t0,t0,-8              /* t0--                                     */
640 ex_no_restore:
641         move    xpc,ra                /* the new xpc is ra                        */
642         lw      t1,IntSave(pv)        /* t1 = saved int register count            */
643         ala     t2,ex_int2            /* t2 = current pc                          */
644         sll     t1,t1,2               /* t1 = register count * 4                  */
645         asubu   t2,t2,t1              /* t2 = ex_int_sav - 4 * register count     */
646         jr      t2                    /* jump to save position                    */
647         ld      s0,-8*8(t0)
648         ld      s1,-7*8(t0)
649         ld      s2,-6*8(t0)
650         ld      s3,-5*8(t0)
651         ld      s4,-4*8(t0)
652         ld      s5,-3*8(t0)
653         ld      s6,-2*8(t0)
654         ld      s7,-1*8(t0)
655 ex_int2:
656         sll     t1,t1,1               /* t1 = register count * 4 * 2              */
657         asubu   t0,t0,t1              /* t0 = t0 - 8 * register count             */
658
659         lw      t1,FltSave(pv)        /* t1 = saved flt register count            */
660         ala     t2,ex_flt2            /* t2 = current pc                          */
661         sll     t1,t1,2               /* t1 = register count * 4                  */
662         asubu   t2,t2,t1              /* t2 = ex_int_sav - 4 * register count     */
663         jr      t2                    /* jump to save position                    */
664         ldc1    fs0,-4*8(t0)
665         ldc1    fs1,-3*8(t0)
666         ldc1    fs2,-2*8(t0)
667         ldc1    fs3,-1*8(t0)
668 ex_flt2:
669         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
670         sll     t0,t0,16
671         sra     t0,t0,16              /* isolate offset                           */
672         aaddu   pv,t0,ra              /* compute update address                   */
673         b       ex_stack_loop
674
675         .end    asm_handle_nat_exception
676
677
678 /* asm_wrapper_patcher *********************************************************
679
680    XXX
681
682    Stack layout:
683          32   return address into JIT code (patch position)
684      24   pointer to virtual java_objectheader
685      16   machine code (which is patched back later)
686       8   unresolved class/method/field reference
687       0   patcher function pointer to call
688
689 *******************************************************************************/
690                 
691     .ent    asm_wrapper_patcher
692
693 asm_wrapper_patcher:
694         aaddiu  sp,sp,-((16+21+4)*8+sizestackframeinfo) /* create stack frame     */
695
696         SAVE_ARGUMENT_REGISTERS(0)    /* save 8 int/8 float argument registers    */
697         SAVE_TEMPORARY_REGISTERS(16)  /* save 5 int/16 float temporary registers  */
698
699         ast     itmp1,(16+21+0)*8(sp) /* save itmp1                               */
700         ast     itmp2,(16+21+1)*8(sp) /* save itmp2                               */
701         ast     ra,(16+21+2)*8(sp)    /* save method return address (for leafs)   */
702         ast     pv,(16+21+3)*8(sp)    /* save pv of calling java function         */
703
704 #if 1
705         aaddiu  a0,sp,(16+21+4)*8     /* create stackframe info                   */
706         move    a1,pv                 /* pass java pv                             */
707         aaddiu  a2,sp,((5+16+21+4)*8+sizestackframeinfo) /* pass java sp          */
708         move    a3,ra                 /* this is correct for leafs                */
709         ald     a4,((4+16+21+4)*8+sizestackframeinfo)(sp) /* pass xpc             */
710         jal     stacktrace_create_extern_stackframeinfo
711 #endif
712
713         aaddiu  a0,sp,((0+16+21+4)*8+sizestackframeinfo) /* pass sp               */
714         ald     itmp3,((0+16+21+4)*8+sizestackframeinfo)(sp) /* get function pointer  */
715         ald     itmp1,(16+21+3)*8(sp) /* save pv to the position of fp            */
716         ast     itmp1,((0+16+21+4)*8+sizestackframeinfo)(sp)
717         jalr    itmp3
718         ast     v0,((0+16+21+4)*8+sizestackframeinfo)(sp) /* save return value    */
719
720 #if 1
721         aaddiu  a0,sp,(16+21+4)*8     /* remove stackframe info                   */
722         jal     stacktrace_remove_stackframeinfo
723 #endif
724
725         RESTORE_ARGUMENT_REGISTERS(0) /* restore 8 int/8 float argument registers */
726         RESTORE_TEMPORARY_REGISTERS(16) /* restore 5 int/16 float temporary reg.  */
727
728         ald     itmp1,(16+21+0)*8(sp) /* restore itmp1                            */
729         ald     itmp2,(16+21+1)*8(sp) /* restore itmp2                            */
730         ald     ra,(16+21+2)*8(sp)    /* restore method return address (for leafs)*/
731         ald     pv,(16+21+3)*8(sp)    /* restore pv of calling java function      */
732
733         ald     v0,((0+16+21+4)*8+sizestackframeinfo)(sp) /* restore return value */
734
735         ald     itmp3,((4+16+21+4)*8+sizestackframeinfo)(sp) /* get ra to jit code*/
736         aaddiu  sp,sp,((5+16+21+4)*8+sizestackframeinfo) /* remove stack frame    */
737
738         beqz    v0,L_asm_wrapper_patcher_exception
739
740         jr      itmp3                 /* jump to new patched code                 */
741
742 L_asm_wrapper_patcher_exception:
743         move    xpc,itmp3             /* return address into JIT code is xpc      */
744
745 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
746         daddiu  sp,sp,-4*8
747         sd      xpc,0*8(sp)
748         sd      ra,1*8(sp)
749         sd      pv,2*8(sp)
750         jal     builtin_asm_get_exceptionptrptr
751         ld      xpc,0*8(sp)
752         ld      ra,1*8(sp)
753         ld      pv,2*8(sp)
754         daddiu  sp,sp,4*8
755 #else
756         la      v0,_exceptionptr
757 #endif
758         ld      xptr,0(v0)            /* get the exception pointer                */
759         sd      zero,0(v0)            /* clear the exception pointer              */
760         b       asm_handle_exception
761
762         .end    asm_wrapper_patcher
763
764                 
765 /******************* function asm_initialize_thread_stack **********************
766 *                                                                              *
767 *   u1* asm_initialize_thread_stack (void *func, u1 *stack);                   *
768 *                                                                              *
769 *   initialize a thread stack                                                  *
770 *                                                                              *
771 *******************************************************************************/
772
773         .ent    asm_initialize_thread_stack
774
775 asm_initialize_thread_stack:
776         aaddiu  a1,a1,-14*8     /* allocate save area                             */
777         sd      zero, 0*8(a1)   /* s0 initalize thread area                       */
778         sd      zero, 1*8(a1)   /* s1                                             */
779         sd      zero, 2*8(a1)   /* s2                                             */
780         sd      zero, 3*8(a1)   /* s3                                             */
781         sd      zero, 4*8(a1)   /* s4                                             */
782         sd      zero, 5*8(a1)   /* s5                                             */
783         sd      zero, 6*8(a1)   /* s6                                             */
784         sd      zero, 7*8(a1)   /* s7                                             */
785         sd      zero, 8*8(a1)   /* s8                                             */
786         sd      zero, 9*8(a1)   /* fs0                                            */
787         sd      zero,10*8(a1)   /* fs1                                            */
788         sd      zero,11*8(a1)   /* fs2                                            */
789         sd      zero,12*8(a1)   /* fs3                                            */
790         sd      a0, 13*8(a1)
791         move    v0,a1
792         j       ra              /* return                                         */
793
794         .end    asm_initialize_thread_stack
795
796
797 /******************* function asm_perform_threadswitch *************************
798 *                                                                              *
799 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
800 *                                                                              *
801 *   performs a threadswitch                                                    *
802 *                                                                              *
803 *******************************************************************************/
804
805         .ent    asm_perform_threadswitch
806
807 asm_perform_threadswitch:
808         aaddiu  sp,sp,-14*8     /* allocate new stack                             */
809         sd      s0,  0*8(sp)    /* save saved registers of old thread             */
810         sd      s1,  1*8(sp)
811         sd      s2,  2*8(sp)
812         sd      s3,  3*8(sp)
813         sd      s4,  4*8(sp)
814         sd      s5,  5*8(sp)
815         sd      s6,  6*8(sp)
816         sd      s7,  7*8(sp)
817         sd      s8,  8*8(sp)
818         sdc1    fs0, 9*8(sp)
819         sdc1    fs1,10*8(sp)
820         sdc1    fs2,11*8(sp)
821         sdc1    fs3,12*8(sp)
822         sd      ra, 13*8(sp)
823         ast     sp,0(a0)        /* save old stack pointer                         */
824         ast     sp,0(a2)        /* stackTop = old stack pointer                   */
825         ald     sp,0(a1)        /* load new stack pointer                         */
826         ld      s0,  0*8(sp)    /* load saved registers of new thread             */
827         ld      s1,  1*8(sp)
828         ld      s2,  2*8(sp)
829         ld      s3,  3*8(sp)
830         ld      s4,  4*8(sp)
831         ld      s5,  5*8(sp)
832         ld      s6,  6*8(sp)
833         ld      s7,  7*8(sp)
834         ld      s8,  8*8(sp)
835         ldc1    fs0, 9*8(sp)
836         ldc1    fs1,10*8(sp)
837         ldc1    fs2,11*8(sp)
838         ldc1    fs3,12*8(sp)
839         ld      ra, 13*8(sp)
840         aaddiu  sp,sp,14*8      /* deallocate new stack                           */
841         move    itmp3, ra
842         j       ra              /* return                                         */
843
844         .end    asm_perform_threadswitch
845
846
847 /********************* function asm_switchstackandcall *************************
848 *                                                                              *
849 *  void asm_switchstackandcall (void *stack, void *func, void **stacktopsave); *
850 *                                                                              *
851 *   Switches to a new stack, calls a function and switches back.               *
852 *       a0      new stack pointer                                              *
853 *       a1      function pointer                                               *
854 *               a2              pointer to variable where stack top should be stored           *
855 *                                                                              *
856 *******************************************************************************/
857
858         .ent    asm_switchstackandcall
859
860 asm_switchstackandcall:
861         aaddiu  a0,a0,-16       /* allocate new stack                             */
862         sd      ra,0(a0)        /* save return address on new stack               */
863         sd      sp,8(a0)        /* save old stack pointer on new stack            */
864         sd      sp,0(a2)        /* save old stack pointer to variable             */
865         move    sp,a0           /* switch to new stack                            */
866         
867         move    itmp3,a1
868         move    a0,a3
869         jalr    itmp3           /* and call function                              */
870
871         ld      ra,0(sp)        /* load return address                            */
872         ld      sp,8(sp)        /* switch to old stack                            */
873
874         j       ra              /* return                                         */
875
876         .end    asm_switchstackandcall
877
878
879         .ent    asm_getclassvalues_atomic
880
881 asm_getclassvalues_atomic:
882 _crit_restart2:
883 _crit_begin2:
884         lw      t0,offbaseval(a0)
885         lw      t1,offdiffval(a0)
886         lw      t2,offbaseval(a1)
887 _crit_end2:
888         sw      t0,offcast_super_baseval(a2)
889         sw      t1,offcast_super_diffval(a2)
890         sw      t2,offcast_sub_baseval(a2)
891         j       ra
892
893         .end    asm_getclassvalues_atomic
894
895     .data
896
897 asm_criticalsections:
898 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
899     .dword  _crit_begin1
900     .dword  _crit_end1
901     .dword  _crit_restart1
902     .dword  _crit_begin2
903     .dword  _crit_end2
904     .dword  _crit_restart2
905 #endif
906     .dword  0
907
908
909         .text
910
911         .ent    compare_and_swap
912
913 compare_and_swap:
914 1:
915         all     v0,0(a0)
916         bne     v0,a1,2f
917         move    t0,a2
918         asc     t0,0(a0)
919         beqz    t0,1b
920 2:
921         sync
922         j       ra
923
924         .end    compare_and_swap
925
926
927 /*
928  * These are local overrides for various environment variables in Emacs.
929  * Please do not remove this and leave it at the end of the file, where
930  * Emacs will automagically detect them.
931  * ---------------------------------------------------------------------
932  * Local variables:
933  * mode: asm
934  * indent-tabs-mode: t
935  * c-basic-offset: 4
936  * tab-width: 4
937  * End:
938  */