* asm_call_jit_compiler: handle jit compiler exceptions properly
[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 3055 2005-07-18 21:58:32Z 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                         /* 4-byte ALIGNMENT PADDING             */
102         .dword  0                         /* line number table start              */
103         .dword  0                         /* line number table size               */
104         .word   0                         /* 4-byte 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                         /* 4-byte ALIGNMENT PADDING             */
186         .dword  0                         /* line number table start              */
187         .dword  0                         /* line number table size               */
188         .word   0                         /* 4-byte 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,-(20*8+sizestackframeinfo) /* allocate stack space          */
362
363         SAVE_ARGUMENT_REGISTERS(0)
364
365         ast     mptr,16*8(sp)         /* save method pointer                      */
366         ast     ra,17*8(sp)           /* save return address                      */
367         ast     itmp1,18*8(sp)        /* save methodinfo pointer                  */
368
369         aaddiu  a0,sp,20*8            /* create stackframe info                   */
370         move    a1,zero               /* we don't have pv handy                   */
371         aaddiu  a2,sp,(20*8+sizestackframeinfo) /* pass java sp                   */
372         move    a3,ra                 /* pass java ra                             */
373         move    a4,a3                 /* xpc is equal to ra                       */
374         jal     stacktrace_create_extern_stackframeinfo
375
376         ald     a0,18*8(sp)           /* pass methodinfo pointer                  */
377         jal     jit_compile           /* jit compiler                             */
378         ast     v0,18*8(sp)           /* save return value                        */
379
380         aaddiu  a0,sp,20*8            /* remove stackframe info                   */
381         jal     stacktrace_remove_stackframeinfo
382
383         RESTORE_ARGUMENT_REGISTERS(0)
384
385         ald     mptr,16*8(sp)         /* restore method pointer                   */
386         ald     ra,17*8(sp)           /* restore return address                   */
387         ald     v0,18*8(sp)           /* restore return value                     */
388         aaddiu  sp,sp,20*8+sizestackframeinfo /* deallocate stack area            */
389
390         beqz    v0,L_asm_call_jit_compiler_exception
391
392         lw      t0,-12(ra)            /* load instruction LDQ PV,xxx($yy)         */
393         sll     t0,t0,16
394         sra     t0,t0,16              /* isolate offset                           */
395
396         aaddu   t0,t0,mptr            /* compute update address via method pointer*/
397         ast     v0,0(t0)              /* save new method address there            */
398
399         move    pv,v0                 /* move method address into pv              */
400
401         jr      pv                    /* and call method. The method returns      */
402                                       /* directly to the caller (ra).             */
403
404 L_asm_call_jit_compiler_exception:
405 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
406         aaddiu  sp,sp,-2*8
407         ast     ra,0*8(sp)
408         jal     builtin_asm_get_exceptionptrptr
409         ald     ra,0*8(sp)
410         aaddiu  sp,sp,2*8
411 #else
412         la      v0,_exceptionptr
413 #endif
414         ald     xptr,0(v0)            /* get the exception pointer                */
415         ast     zero,0(v0)            /* clear the exception pointer              */
416
417         aaddiu  xpc,ra,-4             /* faulting address is return adress - 4    */
418         b       asm_handle_nat_exception
419
420         .end    asm_call_jit_compiler
421
422
423 /********************* function asm_handle_exception ***************************
424 *                                                                              *
425 *   This function handles an exception. It does not use the usual calling      *
426 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
427 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
428 *   the local exception table for a handler. If no one is found, it unwinds    *
429 *   stacks and continues searching the callers.                                *
430 *                                                                              *
431 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
432 *                                                                              *
433 *******************************************************************************/
434
435         .ent    asm_handle_nat_exception
436
437 asm_handle_nat_exception:
438         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
439         sll     t0,t0,16
440         sra     t0,t0,16              /* isolate offset                           */
441         aaddu   pv,t0,ra              /* compute update address                   */
442
443         .aent    asm_handle_exception
444
445 asm_handle_exception:
446         aaddiu  sp,sp,-14*8           /* allocate stack                           */
447
448         sd      v0,0*8(sp)            /* save possible used registers             */
449         sd      t0,1*8(sp)            /* also registers used by trace_exception   */
450         sd      t1,2*8(sp)
451         sd      t2,3*8(sp)
452         sd      t3,4*8(sp)
453         sd      t8,5*8(sp)
454         sd      a0,6*8(sp)
455         sd      a1,7*8(sp)
456         sd      a2,8*8(sp)
457         sd      a3,9*8(sp)
458         sd      a4,10*8(sp)
459         sd      a5,11*8(sp)
460         sd      a6,12*8(sp)
461         sd      a7,13*8(sp)
462
463         addu    t3,zero,1             /* set no unwind flag                       */
464 ex_stack_loop:
465         aaddiu  sp,sp,-6*8            /* allocate stack                           */
466         sd      xptr,0*8(sp)          /* save used registers                      */
467         sd      xpc,1*8(sp)
468         sd      pv,2*8(sp)
469         sd      ra,3*8(sp)
470         sd      t3,4*8(sp)
471
472         move    a0,xptr
473         ald     a1,MethodPointer(pv)
474         move    a2,xpc
475 /*      move    a3,t3 */
476         move    a3,zero
477         addu    a4,zero,1
478         jal     builtin_trace_exception /* trace_exception(xptr,methodptr)        */
479         
480         ld      xptr,0*8(sp)          /* restore used register                    */
481         ld      xpc,1*8(sp)
482         ld      pv,2*8(sp)
483         ld      ra,3*8(sp)
484         ld      t3,4*8(sp)
485         aaddiu  sp,sp,6*8             /* deallocate stack                         */
486         
487         lw      t0,ExTableSize(pv)    /* t0 = exception table size                */
488         beqz    t0,empty_table        /* if empty table skip                      */
489         aaddiu  t1,pv,ExTableStart    /* t1 = start of exception table            */
490
491 ex_table_loop:
492         ald     t2,ExStartPC(t1)      /* t2 = exception start pc                  */
493         sle     t2,t2,xpc             /* t2 = (startpc <= xpc)                    */
494         beqz    t2,ex_table_cont      /* if (false) continue                      */
495         ald     t2,ExEndPC(t1)        /* t2 = exception end pc                    */
496         slt     t2,xpc,t2             /* t2 = (xpc < endpc)                       */
497         beqz    t2,ex_table_cont      /* if (false) continue                      */
498         ald     a1,ExCatchType(t1)    /* arg1 = exception catch type              */
499         beqz    a1,ex_handle_it       /* NULL catches everything                  */
500
501         lw      itmp3,offclassloaded(a1)
502         bnez    itmp3,L_class_loaded
503
504         aaddiu  sp,sp,-8*8            /* allocate stack                           */
505         sd      t0,0*8(sp)            /* save used register                       */
506         sd      t1,1*8(sp)
507         sd      t3,2*8(sp)
508         sd      xptr,3*8(sp)
509         sd      xpc,4*8(sp)
510         sd      pv,5*8(sp)
511         sd      ra,6*8(sp)
512         sd      a1,7*8(sp)
513                 
514         move    a0,a1
515         jal     load_class_bootstrap
516                 
517         ld      t0,0*8(sp)            /* restore used register                    */
518         ld      t1,1*8(sp)
519         ld      t3,2*8(sp)
520         ld      xptr,3*8(sp)
521         ld      xpc,4*8(sp)
522         ld      pv,5*8(sp)
523         ld      ra,6*8(sp)
524         ld      a1,7*8(sp)
525         aaddiu  sp,sp,8*8             /* deallocate stack                         */
526         
527 L_class_loaded:
528         lw      itmp3,offclasslinked(a1)
529         aaddiu  sp,sp,-8*8            /* allocate stack                           */
530         sd      a1,7*8(sp)
531         bnez    itmp3,L_class_linked
532
533         sd      t0,0*8(sp)            /* save used register                       */
534         sd      t1,1*8(sp)
535         sd      t3,2*8(sp)
536         sd      xptr,3*8(sp)
537         sd      xpc,4*8(sp)
538         sd      pv,5*8(sp)
539         sd      ra,6*8(sp)
540                 
541         move    a0,a1
542         jal     link_class
543                 
544         ld      t0,0*8(sp)            /* restore used register                    */
545         ld      t1,1*8(sp)
546         ld      t3,2*8(sp)
547         ld      xptr,3*8(sp)
548         ld      xpc,4*8(sp)
549         ld      pv,5*8(sp)
550         ld      ra,6*8(sp)
551
552 L_class_linked:
553 _crit_restart1:
554         ld      a1,7*8(sp)
555 _crit_begin1:
556         ald     a0,offobjvftbl(xptr)  /* a0 = vftblptr(xptr)                      */
557         ald     a1,offclassvftbl(a1)  /* a1 = vftblptr(catchtype) class (not obj) */
558         lw      a0,offbaseval(a0)     /* a0 = baseval(xptr)                       */
559         lw      v0,offbaseval(a1)     /* a2 = baseval(catchtype)                  */
560         lw      a1,offdiffval(a1)     /* a1 = diffval(catchtype)                  */
561 _crit_end1:
562         subu    a0,a0,v0              /* a0 = baseval(xptr) - baseval(catchtype)  */
563         sltu    v0,a1,a0              /* v0 = xptr is instanceof catchtype        */
564         aaddiu  sp,sp,8*8             /* deallocate stack                         */
565         bnez    v0,ex_table_cont      /* if (false) continue                      */
566
567 ex_handle_it:
568         ald     xpc,ExHandlerPC(t1)   /* xpc = exception handler pc               */
569
570         beqz    t3,ex_jump            /* if (!(no stack unwinding) skip           */
571
572         ld      v0,0*8(sp)            /* restore possible used registers          */
573         ld      t0,1*8(sp)            /* also registers used by trace_exception   */
574         ld      t1,2*8(sp)
575         ld      t2,3*8(sp)
576         ld      t3,4*8(sp)
577         ld      t8,5*8(sp)
578         ld      a0,6*8(sp)
579         ld      a1,7*8(sp)
580         ld      a2,8*8(sp)
581         ld      a3,9*8(sp)
582         ld      a4,10*8(sp)
583         ld      a5,11*8(sp)
584         ld      a6,12*8(sp)
585         ld      a7,13*8(sp)
586         
587         aaddiu  sp,sp,14*8            /* deallocate stack                         */
588
589 ex_jump:
590         jr      xpc                   /* jump to the handler                      */
591
592 ex_table_cont:
593         aaddiu  t1,t1,ExEntrySize     /* next exception table entry               */
594         addiu   t0,t0,-1              /* decrement entry counter                  */
595         bgtz    t0,ex_table_loop      /* if (t0 > 0) next entry                   */
596
597 empty_table:
598         beqz    t3,ex_already_cleared /* if here the first time, then             */
599         aaddiu  sp,sp,14*8            /* deallocate stack and                     */
600         move    t3,zero               /* clear the no unwind flag                 */
601 ex_already_cleared:
602         lw      t0,IsSync(pv)         /* t0 = SyncOffset                          */
603         beqz    t0,no_monitor_exit    /* if zero no monitorexit                   */
604
605 #if defined(USE_THREADS)
606         aaddu   t0,sp,t0              /* add stackptr to Offset                   */
607         ald     a0,-8(t0)             /* load monitorexit pointer                 */
608
609         aaddiu  sp,sp,-8*8            /* allocate stack                           */
610         sd      t0,0*8(sp)            /* save used register                       */
611         sd      t1,1*8(sp)
612         sd      t3,2*8(sp)
613         sd      xptr,3*8(sp)
614         sd      xpc,4*8(sp)
615         sd      pv,5*8(sp)
616         sd      ra,6*8(sp)
617
618         jal     builtin_monitorexit   /* builtin_monitorexit(objectptr)           */
619         
620         ld      t0,0*8(sp)            /* restore used register                    */
621         ld      t1,1*8(sp)
622         ld      t3,2*8(sp)
623         ld      xptr,3*8(sp)
624         ld      xpc,4*8(sp)
625         ld      pv,5*8(sp)
626         ld      ra,6*8(sp)
627         aaddiu  sp,sp,8*8             /* deallocate stack                         */
628 #endif
629
630 no_monitor_exit:
631         lw      t0,FrameSize(pv)      /* t0 = frame size                          */
632         aaddu   sp,sp,t0              /* unwind stack                             */
633         move    t0,sp                 /* t0 = pointer to save area                */
634         lw      t1,IsLeaf(pv)         /* t1 = is leaf procedure                   */
635         bnez    t1,ex_no_restore      /* if (leaf) skip                           */
636         ld      ra,-8(t0)             /* restore ra                               */
637         aaddiu  t0,t0,-8              /* t0--                                     */
638 ex_no_restore:
639         move    xpc,ra                /* the new xpc is ra                        */
640         lw      t1,IntSave(pv)        /* t1 = saved int register count            */
641         ala     t2,ex_int2            /* t2 = current pc                          */
642         sll     t1,t1,2               /* t1 = register count * 4                  */
643         asubu   t2,t2,t1              /* t2 = ex_int_sav - 4 * register count     */
644         jr      t2                    /* jump to save position                    */
645         ld      s0,-8*8(t0)
646         ld      s1,-7*8(t0)
647         ld      s2,-6*8(t0)
648         ld      s3,-5*8(t0)
649         ld      s4,-4*8(t0)
650         ld      s5,-3*8(t0)
651         ld      s6,-2*8(t0)
652         ld      s7,-1*8(t0)
653 ex_int2:
654         sll     t1,t1,1               /* t1 = register count * 4 * 2              */
655         asubu   t0,t0,t1              /* t0 = t0 - 8 * register count             */
656
657         lw      t1,FltSave(pv)        /* t1 = saved flt register count            */
658         ala     t2,ex_flt2            /* t2 = current pc                          */
659         sll     t1,t1,2               /* t1 = register count * 4                  */
660         asubu   t2,t2,t1              /* t2 = ex_int_sav - 4 * register count     */
661         jr      t2                    /* jump to save position                    */
662         ldc1    fs0,-4*8(t0)
663         ldc1    fs1,-3*8(t0)
664         ldc1    fs2,-2*8(t0)
665         ldc1    fs3,-1*8(t0)
666 ex_flt2:
667         lw      t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
668         sll     t0,t0,16
669         sra     t0,t0,16              /* isolate offset                           */
670         aaddu   pv,t0,ra              /* compute update address                   */
671         b       ex_stack_loop
672
673         .end    asm_handle_nat_exception
674
675
676 /* asm_wrapper_patcher *********************************************************
677
678    XXX
679
680    Stack layout:
681          32   return address into JIT code (patch position)
682      24   pointer to virtual java_objectheader
683      16   machine code (which is patched back later)
684       8   unresolved class/method/field reference
685       0   patcher function pointer to call
686
687 *******************************************************************************/
688                 
689     .ent    asm_wrapper_patcher
690
691 asm_wrapper_patcher:
692         aaddiu  sp,sp,-((16+21+4)*8+sizestackframeinfo) /* create stack frame     */
693
694         SAVE_ARGUMENT_REGISTERS(0)    /* save 8 int/8 float argument registers    */
695         SAVE_TEMPORARY_REGISTERS(16)  /* save 5 int/16 float temporary registers  */
696
697         ast     itmp1,(16+21+0)*8(sp) /* save itmp1                               */
698         ast     itmp2,(16+21+1)*8(sp) /* save itmp2                               */
699         ast     ra,(16+21+2)*8(sp)    /* save method return address (for leafs)   */
700         ast     pv,(16+21+3)*8(sp)    /* save pv of calling java function         */
701
702         aaddiu  a0,sp,(16+21+4)*8     /* create stackframe info                   */
703         move    a1,pv                 /* pass java pv                             */
704         aaddiu  a2,sp,((5+16+21+4)*8+sizestackframeinfo) /* pass java sp          */
705         move    a3,ra                 /* this is correct for leafs                */
706         ald     a4,((4+16+21+4)*8+sizestackframeinfo)(sp) /* pass xpc             */
707         jal     stacktrace_create_extern_stackframeinfo
708
709         aaddiu  a0,sp,((0+16+21+4)*8+sizestackframeinfo) /* pass sp               */
710         ald     itmp3,((0+16+21+4)*8+sizestackframeinfo)(sp) /* get function      */
711         ald     itmp1,(16+21+3)*8(sp) /* save pv to the position of fp            */
712         ast     itmp1,((0+16+21+4)*8+sizestackframeinfo)(sp)
713         jalr    itmp3
714         ast     v0,((0+16+21+4)*8+sizestackframeinfo)(sp) /* save return value    */
715
716         aaddiu  a0,sp,(16+21+4)*8     /* remove stackframe info                   */
717         jal     stacktrace_remove_stackframeinfo
718
719         RESTORE_ARGUMENT_REGISTERS(0) /* restore 8 int/8 float argument registers */
720         RESTORE_TEMPORARY_REGISTERS(16) /* restore 5 int/16 float temporary reg.  */
721
722         ald     itmp1,(16+21+0)*8(sp) /* restore itmp1                            */
723         ald     itmp2,(16+21+1)*8(sp) /* restore itmp2                            */
724         ald     ra,(16+21+2)*8(sp)    /* restore method return address (for leafs)*/
725         ald     pv,(16+21+3)*8(sp)    /* restore pv of calling java function      */
726
727         ald     v0,((0+16+21+4)*8+sizestackframeinfo)(sp) /* restore return value */
728
729         ald     itmp3,((4+16+21+4)*8+sizestackframeinfo)(sp) /* get ra to jit code*/
730         aaddiu  sp,sp,((5+16+21+4)*8+sizestackframeinfo) /* remove stack frame    */
731
732         beqz    v0,L_asm_wrapper_patcher_exception
733
734         jr      itmp3                 /* jump to new patched code                 */
735
736 L_asm_wrapper_patcher_exception:
737         move    xpc,itmp3             /* return address into JIT code is xpc      */
738
739 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
740         daddiu  sp,sp,-4*8
741         sd      xpc,0*8(sp)
742         sd      ra,1*8(sp)
743         sd      pv,2*8(sp)
744         jal     builtin_asm_get_exceptionptrptr
745         ld      xpc,0*8(sp)
746         ld      ra,1*8(sp)
747         ld      pv,2*8(sp)
748         daddiu  sp,sp,4*8
749 #else
750         la      v0,_exceptionptr
751 #endif
752         ld      xptr,0(v0)            /* get the exception pointer                */
753         sd      zero,0(v0)            /* clear the exception pointer              */
754         b       asm_handle_exception
755
756         .end    asm_wrapper_patcher
757
758                 
759 /******************* function asm_initialize_thread_stack **********************
760 *                                                                              *
761 *   u1* asm_initialize_thread_stack (void *func, u1 *stack);                   *
762 *                                                                              *
763 *   initialize a thread stack                                                  *
764 *                                                                              *
765 *******************************************************************************/
766
767         .ent    asm_initialize_thread_stack
768
769 asm_initialize_thread_stack:
770         aaddiu  a1,a1,-14*8     /* allocate save area                             */
771         sd      zero, 0*8(a1)   /* s0 initalize thread area                       */
772         sd      zero, 1*8(a1)   /* s1                                             */
773         sd      zero, 2*8(a1)   /* s2                                             */
774         sd      zero, 3*8(a1)   /* s3                                             */
775         sd      zero, 4*8(a1)   /* s4                                             */
776         sd      zero, 5*8(a1)   /* s5                                             */
777         sd      zero, 6*8(a1)   /* s6                                             */
778         sd      zero, 7*8(a1)   /* s7                                             */
779         sd      zero, 8*8(a1)   /* s8                                             */
780         sd      zero, 9*8(a1)   /* fs0                                            */
781         sd      zero,10*8(a1)   /* fs1                                            */
782         sd      zero,11*8(a1)   /* fs2                                            */
783         sd      zero,12*8(a1)   /* fs3                                            */
784         sd      a0, 13*8(a1)
785         move    v0,a1
786         j       ra              /* return                                         */
787
788         .end    asm_initialize_thread_stack
789
790
791 /******************* function asm_perform_threadswitch *************************
792 *                                                                              *
793 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
794 *                                                                              *
795 *   performs a threadswitch                                                    *
796 *                                                                              *
797 *******************************************************************************/
798
799         .ent    asm_perform_threadswitch
800
801 asm_perform_threadswitch:
802         aaddiu  sp,sp,-14*8     /* allocate new stack                             */
803         sd      s0,  0*8(sp)    /* save saved registers of old thread             */
804         sd      s1,  1*8(sp)
805         sd      s2,  2*8(sp)
806         sd      s3,  3*8(sp)
807         sd      s4,  4*8(sp)
808         sd      s5,  5*8(sp)
809         sd      s6,  6*8(sp)
810         sd      s7,  7*8(sp)
811         sd      s8,  8*8(sp)
812         sdc1    fs0, 9*8(sp)
813         sdc1    fs1,10*8(sp)
814         sdc1    fs2,11*8(sp)
815         sdc1    fs3,12*8(sp)
816         sd      ra, 13*8(sp)
817         ast     sp,0(a0)        /* save old stack pointer                         */
818         ast     sp,0(a2)        /* stackTop = old stack pointer                   */
819         ald     sp,0(a1)        /* load new stack pointer                         */
820         ld      s0,  0*8(sp)    /* load saved registers of new thread             */
821         ld      s1,  1*8(sp)
822         ld      s2,  2*8(sp)
823         ld      s3,  3*8(sp)
824         ld      s4,  4*8(sp)
825         ld      s5,  5*8(sp)
826         ld      s6,  6*8(sp)
827         ld      s7,  7*8(sp)
828         ld      s8,  8*8(sp)
829         ldc1    fs0, 9*8(sp)
830         ldc1    fs1,10*8(sp)
831         ldc1    fs2,11*8(sp)
832         ldc1    fs3,12*8(sp)
833         ld      ra, 13*8(sp)
834         aaddiu  sp,sp,14*8      /* deallocate new stack                           */
835         move    itmp3, ra
836         j       ra              /* return                                         */
837
838         .end    asm_perform_threadswitch
839
840
841 /********************* function asm_switchstackandcall *************************
842 *                                                                              *
843 *  void asm_switchstackandcall (void *stack, void *func, void **stacktopsave); *
844 *                                                                              *
845 *   Switches to a new stack, calls a function and switches back.               *
846 *       a0      new stack pointer                                              *
847 *       a1      function pointer                                               *
848 *               a2              pointer to variable where stack top should be stored           *
849 *                                                                              *
850 *******************************************************************************/
851
852         .ent    asm_switchstackandcall
853
854 asm_switchstackandcall:
855         aaddiu  a0,a0,-16       /* allocate new stack                             */
856         sd      ra,0(a0)        /* save return address on new stack               */
857         sd      sp,8(a0)        /* save old stack pointer on new stack            */
858         sd      sp,0(a2)        /* save old stack pointer to variable             */
859         move    sp,a0           /* switch to new stack                            */
860         
861         move    itmp3,a1
862         move    a0,a3
863         jalr    itmp3           /* and call function                              */
864
865         ld      ra,0(sp)        /* load return address                            */
866         ld      sp,8(sp)        /* switch to old stack                            */
867
868         j       ra              /* return                                         */
869
870         .end    asm_switchstackandcall
871
872
873         .ent    asm_getclassvalues_atomic
874
875 asm_getclassvalues_atomic:
876 _crit_restart2:
877 _crit_begin2:
878         lw      t0,offbaseval(a0)
879         lw      t1,offdiffval(a0)
880         lw      t2,offbaseval(a1)
881 _crit_end2:
882         sw      t0,offcast_super_baseval(a2)
883         sw      t1,offcast_super_diffval(a2)
884         sw      t2,offcast_sub_baseval(a2)
885         j       ra
886
887         .end    asm_getclassvalues_atomic
888
889     .data
890
891 asm_criticalsections:
892 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
893     .dword  _crit_begin1
894     .dword  _crit_end1
895     .dword  _crit_restart1
896     .dword  _crit_begin2
897     .dword  _crit_end2
898     .dword  _crit_restart2
899 #endif
900     .dword  0
901
902
903         .text
904
905         .ent    compare_and_swap
906
907 compare_and_swap:
908 1:
909         all     v0,0(a0)
910         bne     v0,a1,2f
911         move    t0,a2
912         asc     t0,0(a0)
913         beqz    t0,1b
914 2:
915         sync
916         j       ra
917
918         .end    compare_and_swap
919
920
921 /*
922  * These are local overrides for various environment variables in Emacs.
923  * Please do not remove this and leave it at the end of the file, where
924  * Emacs will automagically detect them.
925  * ---------------------------------------------------------------------
926  * Local variables:
927  * mode: asm
928  * indent-tabs-mode: t
929  * c-basic-offset: 4
930  * tab-width: 4
931  * End:
932  */