* src/vm/jit/alpha/asmpart.S (asm_vm_call_method): Removed !NDEBUG as
[cacao.git] / src / vm / jit / mips / asmpart.S
1 /* src/vm/jit/mips/asmpart.S - Java-C interface functions for MIPS
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28
29    Changes: Christian Thalinger
30             Edwin Steiner
31
32    $Id: asmpart.S 4735 2006-04-05 10:02:14Z twisti $
33
34 */
35
36
37 #include "config.h"
38
39 #include "vm/jit/mips/md-abi.h"
40 #include "vm/jit/mips/md-asm.h"
41 #include "vm/jit/mips/offsets.h"
42
43 #include "vm/jit/abi-asm.h"
44 #include "vm/jit/methodheader.h"
45
46
47         .text
48         .set    noat
49
50
51 /* export functions ***********************************************************/
52
53         .globl asm_vm_call_method
54         .globl asm_vm_call_method_int
55         .globl asm_vm_call_method_long
56         .globl asm_vm_call_method_float
57         .globl asm_vm_call_method_double
58         .globl asm_vm_call_method_exception_handler
59
60         .globl asm_call_jit_compiler
61         .globl asm_handle_exception
62         .globl asm_handle_nat_exception
63
64         .globl asm_wrapper_patcher
65
66         .globl asm_replacement_out
67         .globl asm_replacement_in
68
69         .globl asm_perform_threadswitch
70         .globl asm_initialize_thread_stack
71         .globl asm_switchstackandcall
72         .globl asm_getclassvalues_atomic
73         .globl asm_criticalsections
74
75         .globl compare_and_swap
76
77
78 /********************* function asm_calljavafunction ***************************
79 *                                                                              *
80 *   This function calls a Java-method (which possibly needs compilation)       *
81 *   with up to 4 address parameters.                                           *
82 *                                                                              *
83 *   This functions calls the JIT-compiler which eventually translates the      *
84 *   method into machine code.                                                  *
85 *                                                                              *
86 *   A possibly throwed exception will be returned to the caller as function    *
87 *   return value, so the java method cannot return a fucntion value (this      *
88 *   function usually calls 'main' and '<clinit>' which do not return a         *
89 *   function value).                                                           *
90 *                                                                              *
91 *   C-prototype:                                                               *
92 *    javaobject_header *asm_calljavafunction (methodinfo *m,                   *
93 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
94 *                                                                              *
95 *******************************************************************************/
96
97         .ent    asm_vm_call_method
98
99         .align  3
100
101         .dword  0                           /* catch type all                     */
102         .dword  0                           /* handler pc                         */
103         .dword  0                           /* end pc                             */
104         .dword  0                           /* start pc                           */
105         .word   1                           /* extable size                       */
106         .word   0                           /* 4-byte ALIGNMENT PADDING           */
107         .dword  0                           /* line number table start            */
108         .dword  0                           /* line number table size             */
109         .word   0                           /* 4-byte ALIGNMENT PADDING           */
110         .word   0                           /* fltsave                            */
111         .word   0                           /* intsave                            */
112         .word   0                           /* isleaf                             */
113         .word   0                           /* IsSync                             */
114         .word   0                           /* frame size                         */
115         .dword  0                           /* method pointer (pointer to name)   */
116
117 asm_vm_call_method:
118 asm_vm_call_method_int:
119 asm_vm_call_method_long:
120 asm_vm_call_method_float:
121 asm_vm_call_method_double:
122         .set    noreorder                 /* XXX we need to recompute pv          */
123
124         aaddiu  sp,sp,-12*8               /* allocate stack space (only 11 needed)*/
125         ast     ra,0(sp)                  /* save return address                  */
126
127         bal     L_asm_vm_call_method_compute_pv
128         ast     pv,1*8(sp)                /* procedure vector                     */
129 L_asm_vm_call_method_compute_pv:
130         aaddiu  pv,ra,-4*4
131         ast     s7,3*8(sp)
132
133         sdc1    fss0,5*8(sp)              /* save non JavaABI saved flt registers */
134         sdc1    fss1,6*8(sp)
135         sdc1    fss2,7*8(sp)
136         sdc1    fss3,8*8(sp)
137         sdc1    fss4,9*8(sp)
138         sdc1    fss5,10*8(sp)
139
140         ast     a0,4*8(sp)                /* save method pointer for compiler     */
141
142         move    t0,a2
143         move    s7,a1
144         blez    s7,calljava_argsloaded
145         nop
146
147         ald     a0,offvmargdata(t0)
148         ldc1    fa0,offvmargdata(t0)
149         daddi   s7,s7,-1
150         blez    s7,calljava_argsloaded
151         nop
152
153         ald     a1,offvmargdata+sizevmarg*1(t0)
154         ldc1    fa1,offvmargdata+sizevmarg*1(t0)
155         daddi   s7,s7,-1
156         blez    s7,calljava_argsloaded
157         nop
158
159         ald     a2,offvmargdata+sizevmarg*2(t0)
160         ldc1    fa2,offvmargdata+sizevmarg*2(t0)
161         daddi   s7,s7,-1
162         blez    s7,calljava_argsloaded
163         nop
164
165         ald     a3,offvmargdata+sizevmarg*3(t0)
166         ldc1    fa3,offvmargdata+sizevmarg*3(t0)
167         daddi   s7,s7,-1
168         blez    s7,calljava_argsloaded
169         nop
170
171         ald     a4,offvmargdata+sizevmarg*4(t0)
172         ldc1    fa4,offvmargdata+sizevmarg*4(t0)
173         daddi   s7,s7,-1
174         blez    s7,calljava_argsloaded
175         nop
176
177         ald     a5,offvmargdata+sizevmarg*5(t0)
178         ldc1    fa5,offvmargdata+sizevmarg*5(t0)
179         daddi   s7,s7,-1
180         blez    s7,calljava_argsloaded
181         nop
182
183         ald     a6,offvmargdata+sizevmarg*6(t0)
184         ldc1    fa6,offvmargdata+sizevmarg*6(t0)
185         daddi   s7,s7,-1
186         blez    s7,calljava_argsloaded
187         nop
188
189         ald     a7,offvmargdata+sizevmarg*7(t0)
190         ldc1    fa7,offvmargdata+sizevmarg*7(t0)
191         daddi   s7,s7,-1
192                 
193 calljava_argsloaded:
194         move    t8,sp                      /* save stack pointer                  */
195         blez    s7,calljava_nocopy
196         nop
197         subu    t1,zero,s7
198         sll     t2,t1,3
199         aaddu   sp,sp,t2
200         aaddu   t2,t2,t8
201
202 calljava_copyloop:
203     ald     t3,offvmargdata+sizevmarg*8(t0)
204         ast     t3,0(t2)
205         ala     t1,1(t1)
206         ala     t0,sizevmarg(t0)
207         ala     t2,8(t2)
208         bnez    t1,calljava_copyloop
209         nop
210
211 calljava_nocopy:
212         ald     itmp1,4*8(t8)             /* pass method pointer via itmp1        */
213
214         ala     mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
215         ast     mptr,2*8(t8)              /* store function address               */
216         ala     mptr,1*8(t8)              /* set method pointer                   */
217
218         ald     pv,1*8(mptr)              /* method call as in Java               */
219         jalr    pv                        /* call JIT compiler                    */
220         nop
221 L_asm_vm_call_method_recompute_pv:
222 /*      aaddiu  pv,ra,(asm_vm_call_method - L_asm_vm_call_method_recompute_pv)*/
223         aaddiu  pv,ra,-76*4               /* recompute procedure vector           */
224
225         .set    reorder                   /* XXX we need to recompute pv          */
226
227 calljava_return2:
228         ald     ra,0(sp)                  /* restore return address               */
229         ald     pv,8(sp)                  /* restore procedure vector             */
230         ald     s7,3*8(sp)
231
232         ldc1    fss0,5*8(sp)              /* restore non JavaABI saved flt regs   */
233         ldc1    fss1,6*8(sp)
234         ldc1    fss2,7*8(sp)
235         ldc1    fss3,8*8(sp)
236         ldc1    fss4,9*8(sp)
237         ldc1    fss5,10*8(sp)
238
239         aaddiu  sp,sp,12*8                /* free stack space                     */
240         j       ra                        /* return                               */
241
242 asm_vm_call_method_exception_handler:
243         asll    s7,s7,3
244         aaddu   sp,s7,sp
245         move    a0,itmp1                  
246         jal     builtin_throw_exception
247         move    v0,zero                   /* clear return value for exception     */
248         b       calljava_return2
249
250         .end    asm_vm_call_method
251
252
253 /****************** function asm_call_jit_compiler *****************************
254 *                                                                              *
255 *   invokes the compiler for untranslated JavaVM methods.                      *
256 *                                                                              *
257 *   Register REG_ITEMP1 contains a pointer to the method info structure        *
258 *   (prepared by createcompilerstub). Using the return address in R31 and the  *
259 *   offset in the LDA instruction or using the value in methodptr R25 the      *
260 *   patching address for storing the method address can be computed:           *
261 *                                                                              *
262 *   method address was either loaded using                                     *
263 *   M_ALD (REG_PV, REG_PV, a)        ; invokestatic/special    ($28)           *
264 *   M_JSR (REG_RA, REG_PV);                                                    *
265 *   M_NOP                                                                      *
266 *   M_LDA (REG_PV, REG_RA, val)                                                *
267 *   or                                                                         *
268 *   M_ALD (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($25)           *
269 *   M_JSR (REG_RA, REG_PV);                                                    *
270 *   M_NOP                                                                      *
271 *   in the static case the method pointer can be computed using the            *
272 *   return address and the lda function following the jmp instruction          *
273 *                                                                              *
274 *******************************************************************************/
275
276
277         .ent    asm_call_jit_compiler
278
279 asm_call_jit_compiler:
280         aaddiu  sp,sp,-(20*8+sizestackframeinfo) /* allocate stack space          */
281
282         SAVE_ARGUMENT_REGISTERS(0)
283
284         ast     mptr,16*8(sp)         /* save method pointer                      */
285         ast     ra,17*8(sp)           /* save return address                      */
286         ast     itmp1,18*8(sp)        /* save methodinfo pointer                  */
287
288         aaddiu  a0,sp,20*8            /* create stackframe info                   */
289         move    a1,zero               /* we don't have pv handy                   */
290         aaddiu  a2,sp,(20*8+sizestackframeinfo) /* pass java sp                   */
291         ald     a3,17*8(sp)           /* pass java ra                             */
292         move    a4,a3                 /* xpc is equal to ra                       */
293         jal     stacktrace_create_extern_stackframeinfo
294
295         ald     a0,18*8(sp)           /* pass methodinfo pointer                  */
296         jal     jit_compile           /* jit compiler                             */
297         ast     v0,18*8(sp)           /* save return value                        */
298
299         aaddiu  a0,sp,20*8            /* remove stackframe info                   */
300         jal     stacktrace_remove_stackframeinfo
301
302         ald     a0,17*8(sp)           /* pass return address                      */
303         aaddiu  a1,sp,20*8            /* pass stackframeinfo (for PV)             */
304         ald     a2,16*8(sp)           /* pass method pointer                      */
305         jal     md_assembler_get_patch_address /* get address of patch position   */
306         move    t0,v0                 /* move offset to t0 for later use          */
307
308         RESTORE_ARGUMENT_REGISTERS(0)
309
310         ald     ra,17*8(sp)           /* restore return address                   */
311         ald     v0,18*8(sp)           /* restore return value                     */
312         aaddiu  sp,sp,20*8+sizestackframeinfo /* deallocate stack area            */
313
314         beqz    v0,L_asm_call_jit_compiler_exception
315
316         ast     v0,0(t0)              /* store new method address                 */
317         move    pv,v0                 /* move method address into pv              */
318         jr      pv                    /* and call method. The method returns      */
319                                       /* directly to the caller (ra).             */
320
321 L_asm_call_jit_compiler_exception:
322 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
323         aaddiu  sp,sp,-2*8
324         ast     ra,0*8(sp)
325         jal     builtin_asm_get_exceptionptrptr
326         ald     ra,0*8(sp)
327         aaddiu  sp,sp,2*8
328 #else
329         la      v0,_exceptionptr
330 #endif
331         ald     xptr,0(v0)            /* get the exception pointer                */
332         ast     zero,0(v0)            /* clear the exception pointer              */
333
334         aaddiu  xpc,ra,-4             /* faulting address is return adress - 4    */
335         b       asm_handle_nat_exception
336
337         .end    asm_call_jit_compiler
338
339
340 /* asm_handle_exception ********************************************************
341
342    This function handles an exception. It does not use the usual calling
343    conventions. The exception pointer is passed in REG_ITMP1 and the
344    pc from the exception raising position is passed in REG_ITMP2. It searches
345    the local exception table for a handler. If no one is found, it unwinds
346    stacks and continues searching the callers.
347
348 *******************************************************************************/
349
350         .ent    asm_handle_nat_exception
351
352 asm_handle_nat_exception:
353 L_asm_handle_exception_stack_loop:
354         aaddiu  sp,sp,-6*8                  /* allocate stack                     */
355         ast     xptr,0*8(sp)                /* save exception pointer             */
356         ast     xpc,1*8(sp)                 /* save exception pc                  */
357         ast     ra,3*8(sp)                  /* save return address                */
358         ast     zero,4*8(sp)                /* save maybe-leaf flag (cleared)     */
359
360         move    a0,ra                       /* pass return address                */
361         jal     md_codegen_findmethod       /* get PV from RA                     */
362         ast     v0,2*8(sp)                  /* save data segment pointer          */
363
364         ald     a0,0*8(sp)                  /* pass exception pointer             */
365         ald     a1,1*8(sp)                  /* pass exception pc                  */
366         move    a2,v0                       /* pass data segment pointer          */
367         aaddiu  a3,sp,6*8                   /* pass Java stack pointer            */
368
369         b       L_asm_handle_exception_continue
370
371         .aent    asm_handle_exception
372
373 asm_handle_exception:
374         aaddiu  sp,sp,-(ARG_CNT+TMP_CNT)*8  /* create maybe-leaf stackframe       */
375
376         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
377         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
378
379         aaddiu  sp,sp,-6*8                  /* allocate stack                     */
380         ast     xptr,0*8(sp)                /* save exception pointer             */
381         ast     xpc,1*8(sp)                 /* save exception pc                  */
382         ast     pv,2*8(sp)                  /* save data segment pointer          */
383         ast     ra,3*8(sp)                  /* save return address                */
384         addu    t0,zero,1                   /* set maybe-leaf flag                */
385         ast     t0,4*8(sp)                  /* save maybe-leaf flag               */
386
387         move    a0,xptr                     /* pass exception pointer             */
388         move    a1,xpc                      /* pass exception pc                  */
389         move    a2,pv                       /* pass data segment pointer          */
390         aaddiu  a3,sp,(ARG_CNT+TMP_CNT+6)*8 /* pass Java stack pointer            */
391
392 L_asm_handle_exception_continue:
393         jal     exceptions_handle_exception
394         
395         beqz    v0,L_asm_handle_exception_not_catched
396
397         move    xpc,v0                      /* move handlerpc into xpc            */
398         ald     xptr,0*8(sp)                /* restore exception pointer          */
399         ald     pv,2*8(sp)                  /* restore data segment pointer       */
400         ald     ra,3*8(sp)                  /* restore return address             */
401         ald     t0,4*8(sp)                  /* get maybe-leaf flag                */
402         aaddiu  sp,sp,6*8                   /* free stackframe                    */
403         
404         beqz    t0,L_asm_handle_exception_no_leaf
405
406         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
407         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
408         
409         aaddiu  sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
410
411 L_asm_handle_exception_no_leaf:
412         jr      xpc                         /* jump to the handler                */
413
414 L_asm_handle_exception_not_catched:
415         ald     xptr,0*8(sp)                /* restore exception pointer          */
416         ald     pv,2*8(sp)                  /* restore data segment pointer       */
417         ald     ra,3*8(sp)                  /* restore return address             */
418         ald     t0,4*8(sp)                  /* get maybe-leaf flag                */
419         aaddiu  sp,sp,6*8                   /* free stackframe                    */
420         
421         beqz    t0,L_asm_handle_exception_no_leaf_stack
422
423         aaddiu  sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
424         move    t0,zero                     /* clear the maybe-leaf flag          */
425
426 L_asm_handle_exception_no_leaf_stack:
427         lw      t1,FrameSize(pv)            /* get frame size                     */
428         aaddu   t1,sp,t1                    /* pointer to save area               */
429
430         lw      t2,IsLeaf(pv)               /* is leaf procedure                  */
431         bnez    t2,L_asm_handle_exception_no_ra_restore
432
433         ald     ra,-1*8(t1)                 /* restore ra                         */
434         aaddiu  t1,t1,-8                    /* t1--                               */
435
436 L_asm_handle_exception_no_ra_restore:
437         move    xpc,ra                      /* the new xpc is ra                  */
438         lw      t2,IntSave(pv)              /* t1 = saved int register count      */
439         ala     t3,ex_int2                  /* t3 = current pc                    */
440         sll     t2,t2,2                     /* t2 = register count * 4            */
441         asubu   t3,t3,t2                    /* t3 = IntSave - 4 * register count  */
442         jr      t3                          /* jump to save position              */
443
444         ald     s0,-8*8(t1)
445         ald     s1,-7*8(t1)
446         ald     s2,-6*8(t1)
447         ald     s3,-5*8(t1)
448         ald     s4,-4*8(t1)
449         ald     s5,-3*8(t1)
450         ald     s6,-2*8(t1)
451         ald     s7,-1*8(t1)
452 ex_int2:
453         sll     t2,t2,1               /* t2 = register count * 4 * 2              */
454         asubu   t1,t1,t2              /* t1 = t0 - 8 * register count             */
455
456         lw      t2,FltSave(pv)        /* t2 = saved flt register count            */
457         ala     t3,ex_flt2            /* t3 = current pc                          */
458         sll     t2,t2,2               /* t2 = register count * 4                  */
459         asubu   t3,t3,t2              /* t3 = ex_int_sav - 4 * register count     */
460         jr      t3                          /* jump to save position              */
461
462         ldc1    fs0,-4*8(t1)
463         ldc1    fs1,-3*8(t1)
464         ldc1    fs2,-2*8(t1)
465         ldc1    fs3,-1*8(t1)
466
467 ex_flt2:
468         lw      t1,FrameSize(pv)            /* get frame size                     */
469         aaddu   sp,sp,t1                    /* unwind stack                       */
470         b       L_asm_handle_exception_stack_loop
471
472         .end    asm_handle_nat_exception
473
474
475 /* asm_wrapper_patcher *********************************************************
476
477    XXX
478
479    Stack layout:
480      40   return address into JIT code (patch position)
481      32   pointer to virtual java_objectheader
482      24   machine code (which is patched back later)
483      16   unresolved class/method/field reference
484       8   data segment displacement from load instructions
485       0   patcher function pointer to call
486
487 *******************************************************************************/
488                 
489     .ent    asm_wrapper_patcher
490
491 asm_wrapper_patcher:
492         aaddiu  sp,sp,-((2+16+22+4)*8+sizestackframeinfo) /* create stack frame   */
493
494         SAVE_RETURN_REGISTERS(0)      /* save 1 int/1 float return registers      */
495         SAVE_ARGUMENT_REGISTERS(2)    /* save 8 int/8 float argument registers    */
496         SAVE_TEMPORARY_REGISTERS(18)  /* save 5 int/16 float temporary registers  */
497
498         ast     itmp1,(2+16+22+0)*8(sp) /* save itmp1                             */
499         ast     itmp2,(2+16+22+1)*8(sp) /* save itmp2                             */
500         ast     ra,(2+16+22+2)*8(sp)  /* save method return address (for leafs)   */
501         ast     pv,(2+16+22+3)*8(sp)  /* save pv of calling java function         */
502
503         aaddiu  a0,sp,(2+16+22+4)*8   /* create stackframe info                   */
504         move    a1,pv                 /* pass java pv                             */
505         aaddiu  a2,sp,((6+2+16+22+4)*8+sizestackframeinfo) /* pass java sp        */
506         move    a3,ra                 /* this is correct for leafs                */
507         ald     a4,((5+2+16+22+4)*8+sizestackframeinfo)(sp) /* pass xpc           */
508         jal     stacktrace_create_extern_stackframeinfo
509
510         aaddiu  a0,sp,((0+2+16+22+4)*8+sizestackframeinfo) /* pass sp             */
511         ald     itmp3,((0+2+16+22+4)*8+sizestackframeinfo)(sp) /* get function    */
512         ald     itmp1,(2+16+22+3)*8(sp) /* save pv to the position of fp          */
513         ast     itmp1,((0+2+16+22+4)*8+sizestackframeinfo)(sp)
514         jalr    itmp3
515         ast     v0,((0+2+16+22+4)*8+sizestackframeinfo)(sp) /* save return value  */
516
517         aaddiu  a0,sp,(2+16+22+4)*8   /* remove stackframe info                   */
518         jal     stacktrace_remove_stackframeinfo
519
520         RESTORE_RETURN_REGISTERS(0)   /* restore 1 int/1 float return registers   */
521         RESTORE_ARGUMENT_REGISTERS(2) /* restore 8 int/8 float argument registers */
522         RESTORE_TEMPORARY_REGISTERS(18) /* restore 5 int/16 float temporary reg.  */
523
524         ald     itmp1,(2+16+22+0)*8(sp) /* restore itmp1                          */
525         ald     itmp2,(2+16+22+1)*8(sp) /* restore itmp2                          */
526         ald     ra,(2+16+22+2)*8(sp)  /* restore method return address (for leafs)*/
527         ald     pv,(2+16+22+3)*8(sp)  /* restore pv of calling java function      */
528
529         ald     itmp3,((0+2+16+22+4)*8+sizestackframeinfo)(sp) /* get return value*/
530         beqz    itmp3,L_asm_wrapper_patcher_exception
531
532         ald     itmp3,((5+2+16+22+4)*8+sizestackframeinfo)(sp) /* get RA to JIT   */
533         aaddiu  sp,sp,((6+2+16+22+4)*8+sizestackframeinfo) /* remove stack frame  */
534
535         jr      itmp3                 /* jump to new patched code                 */
536
537 L_asm_wrapper_patcher_exception:
538         ald     xpc,((5+2+16+22+4)*8+sizestackframeinfo)(sp) /* RA to JIT is xpc  */
539         aaddiu  sp,sp,((6+2+16+22+4)*8+sizestackframeinfo) /* remove stack frame  */
540
541 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
542         daddiu  sp,sp,-4*8
543         sd      xpc,0*8(sp)
544         sd      ra,1*8(sp)
545         sd      pv,2*8(sp)
546         jal     builtin_asm_get_exceptionptrptr
547         ld      xpc,0*8(sp)
548         ld      ra,1*8(sp)
549         ld      pv,2*8(sp)
550         daddiu  sp,sp,4*8
551 #else
552         la      v0,_exceptionptr
553 #endif
554         ld      xptr,0(v0)            /* get the exception pointer                */
555         sd      zero,0(v0)            /* clear the exception pointer              */
556         b       asm_handle_exception
557
558         .end    asm_wrapper_patcher
559
560                 
561 /* asm_replacement_out *********************************************************
562
563    This code is jumped to from the replacement-out stubs that are executed
564    when a thread reaches an activated replacement point.
565
566    The purpose of asm_replacement_out is to read out the parts of the
567    execution state that cannot be accessed from C code, store this state,
568    and then call the C function replace_me.
569
570    Stack layout:
571      16                 start of stack inside method to replace
572       0   rplpoint *    info on the replacement point that was reached
573
574    NOTE: itmp3 has been clobbered by the replacement-out stub!
575
576 *******************************************************************************/
577
578 /* some room to accomodate changes of the stack frame size during replacement */
579         /* XXX we should find a cleaner solution here */
580 #define REPLACEMENT_ROOM  512
581
582 #define REPLACEMENT_STACK_OFFSET ((sizeexecutionstate + REPLACEMENT_ROOM + 0xf) & ~0xf)
583
584         .ent asm_replacement_out
585
586 asm_replacement_out:
587     /* create stack frame */
588         daddiu  sp,sp,-REPLACEMENT_STACK_OFFSET
589
590         /* save registers in execution state */
591         sd      $0 ,( 0*8+offes_intregs)(sp)
592         sd      $1 ,( 1*8+offes_intregs)(sp)
593         sd      $2 ,( 2*8+offes_intregs)(sp)
594         sd      $3 ,( 3*8+offes_intregs)(sp)
595         sd      $4 ,( 4*8+offes_intregs)(sp)
596         sd      $5 ,( 5*8+offes_intregs)(sp)
597         sd      $6 ,( 6*8+offes_intregs)(sp)
598         sd      $7 ,( 7*8+offes_intregs)(sp)
599         sd      $8 ,( 8*8+offes_intregs)(sp)
600         sd      $9 ,( 9*8+offes_intregs)(sp)
601         sd      $10,(10*8+offes_intregs)(sp)
602         sd      $11,(11*8+offes_intregs)(sp)
603         sd      $12,(12*8+offes_intregs)(sp)
604         sd      $13,(13*8+offes_intregs)(sp)
605         sd      $14,(14*8+offes_intregs)(sp)
606         sd      $15,(15*8+offes_intregs)(sp)
607         sd      $16,(16*8+offes_intregs)(sp)
608         sd      $17,(17*8+offes_intregs)(sp)
609         sd      $18,(18*8+offes_intregs)(sp)
610         sd      $19,(19*8+offes_intregs)(sp)
611         sd      $20,(20*8+offes_intregs)(sp)
612         sd      $21,(21*8+offes_intregs)(sp)
613         sd      $22,(22*8+offes_intregs)(sp)
614         sd      $23,(23*8+offes_intregs)(sp)
615         sd      $24,(24*8+offes_intregs)(sp)
616         sd      $25,(25*8+offes_intregs)(sp)
617         sd      $26,(26*8+offes_intregs)(sp)
618         sd      $27,(27*8+offes_intregs)(sp)
619         sd      $28,(28*8+offes_intregs)(sp)
620         sd      $29,(29*8+offes_intregs)(sp)
621         sd      $30,(30*8+offes_intregs)(sp)
622         sd      $31,(31*8+offes_intregs)(sp)
623         
624         sdc1    $f0 ,( 0*8+offes_fltregs)(sp)
625         sdc1    $f1 ,( 1*8+offes_fltregs)(sp)
626         sdc1    $f2 ,( 2*8+offes_fltregs)(sp)
627         sdc1    $f3 ,( 3*8+offes_fltregs)(sp)
628         sdc1    $f4 ,( 4*8+offes_fltregs)(sp)
629         sdc1    $f5 ,( 5*8+offes_fltregs)(sp)
630         sdc1    $f6 ,( 6*8+offes_fltregs)(sp)
631         sdc1    $f7 ,( 7*8+offes_fltregs)(sp)
632         sdc1    $f8 ,( 8*8+offes_fltregs)(sp)
633         sdc1    $f9 ,( 9*8+offes_fltregs)(sp)
634         sdc1    $f10,(10*8+offes_fltregs)(sp)
635         sdc1    $f11,(11*8+offes_fltregs)(sp)
636         sdc1    $f12,(12*8+offes_fltregs)(sp)
637         sdc1    $f13,(13*8+offes_fltregs)(sp)
638         sdc1    $f14,(14*8+offes_fltregs)(sp)
639         sdc1    $f15,(15*8+offes_fltregs)(sp)
640         sdc1    $f16,(16*8+offes_fltregs)(sp)
641         sdc1    $f17,(17*8+offes_fltregs)(sp)
642         sdc1    $f18,(18*8+offes_fltregs)(sp)
643         sdc1    $f19,(19*8+offes_fltregs)(sp)
644         sdc1    $f20,(20*8+offes_fltregs)(sp)
645         sdc1    $f21,(21*8+offes_fltregs)(sp)
646         sdc1    $f22,(22*8+offes_fltregs)(sp)
647         sdc1    $f23,(23*8+offes_fltregs)(sp)
648         sdc1    $f24,(24*8+offes_fltregs)(sp)
649         sdc1    $f25,(25*8+offes_fltregs)(sp)
650         sdc1    $f26,(26*8+offes_fltregs)(sp)
651         sdc1    $f27,(27*8+offes_fltregs)(sp)
652         sdc1    $f28,(28*8+offes_fltregs)(sp)
653         sdc1    $f29,(29*8+offes_fltregs)(sp)
654         sdc1    $f30,(30*8+offes_fltregs)(sp)
655         sdc1    $f31,(31*8+offes_fltregs)(sp)
656         
657         /* calculate sp of method */
658         daddiu  itmp1,sp,(REPLACEMENT_STACK_OFFSET + 2*8)
659         sd      itmp1,(offes_sp)(sp)
660
661         /* store pv */
662         sd      pv,(offes_pv)(sp)
663
664         /* call replace_me */
665         ld      a0,-(2*8)(itmp1)            /* arg0: rplpoint *                   */
666     move    a1,sp                       /* arg1: execution state              */
667     jal     replace_me                  /* call C function replace_me         */
668         jal     abort                       /* NEVER REACHED                      */
669
670         .end asm_replacement_out
671
672 /* asm_replacement_in **********************************************************
673
674    This code writes the given execution state and jumps to the replacement
675    code.
676
677    This function never returns!
678
679    NOTE: itmp3 is not restored!
680
681    C prototype:
682       void asm_replacement_in(executionstate *es);
683
684 *******************************************************************************/
685
686         .ent asm_replacement_in
687         
688 asm_replacement_in:
689         /* a0 == executionstate *es */
690
691         /* set new sp and pv */
692         ld      sp,(offes_sp)(a0)
693         ld      pv,(offes_pv)(a0)
694         
695         /* copy registers from execution state */
696         /* $0 is zero                     */
697         ld      $1 ,( 1*8+offes_intregs)(a0)
698         ld      $2 ,( 2*8+offes_intregs)(a0)
699         ld      $3 ,( 2*8+offes_intregs)(a0)
700         /* a0 is loaded below             */
701         ld      $5 ,( 5*8+offes_intregs)(a0)
702         ld      $6 ,( 6*8+offes_intregs)(a0)
703         ld      $7 ,( 7*8+offes_intregs)(a0)
704         ld      $8 ,( 8*8+offes_intregs)(a0)
705         ld      $9 ,( 9*8+offes_intregs)(a0)
706         ld      $10,(10*8+offes_intregs)(a0)
707         ld      $11,(11*8+offes_intregs)(a0)
708         ld      $12,(12*8+offes_intregs)(a0)
709         ld      $13,(13*8+offes_intregs)(a0)
710         ld      $14,(14*8+offes_intregs)(a0)
711         ld      $15,(15*8+offes_intregs)(a0)
712         ld      $16,(16*8+offes_intregs)(a0)
713         ld      $17,(17*8+offes_intregs)(a0)
714         ld      $18,(18*8+offes_intregs)(a0)
715         ld      $19,(19*8+offes_intregs)(a0)
716         ld      $20,(20*8+offes_intregs)(a0)
717         ld      $21,(21*8+offes_intregs)(a0)
718         ld      $22,(22*8+offes_intregs)(a0)
719         ld      $23,(23*8+offes_intregs)(a0)
720         ld      $24,(24*8+offes_intregs)(a0)
721         ld      $25,(25*8+offes_intregs)(a0)
722         ld      $26,(26*8+offes_intregs)(a0)
723         ld      $27,(27*8+offes_intregs)(a0)
724         ld      $28,(28*8+offes_intregs)(a0)
725         /* $29 is sp                      */
726         /* $30 is pv                      */
727         ld      $31,(31*8+offes_intregs)(a0)
728         
729         ldc1    $f0 ,( 0*8+offes_fltregs)(a0)
730         ldc1    $f1 ,( 1*8+offes_fltregs)(a0)
731         ldc1    $f2 ,( 2*8+offes_fltregs)(a0)
732         ldc1    $f3 ,( 3*8+offes_fltregs)(a0)
733         ldc1    $f4 ,( 4*8+offes_fltregs)(a0)
734         ldc1    $f5 ,( 5*8+offes_fltregs)(a0)
735         ldc1    $f6 ,( 6*8+offes_fltregs)(a0)
736         ldc1    $f7 ,( 7*8+offes_fltregs)(a0)
737         ldc1    $f8 ,( 8*8+offes_fltregs)(a0)
738         ldc1    $f9 ,( 9*8+offes_fltregs)(a0)
739         ldc1    $f10,(10*8+offes_fltregs)(a0)
740         ldc1    $f11,(11*8+offes_fltregs)(a0)
741         ldc1    $f12,(12*8+offes_fltregs)(a0)
742         ldc1    $f13,(13*8+offes_fltregs)(a0)
743         ldc1    $f14,(14*8+offes_fltregs)(a0)
744         ldc1    $f15,(15*8+offes_fltregs)(a0)
745         ldc1    $f16,(16*8+offes_fltregs)(a0)
746         ldc1    $f17,(17*8+offes_fltregs)(a0)
747         ldc1    $f18,(18*8+offes_fltregs)(a0)
748         ldc1    $f19,(19*8+offes_fltregs)(a0)
749         ldc1    $f20,(20*8+offes_fltregs)(a0)
750         ldc1    $f21,(21*8+offes_fltregs)(a0)
751         ldc1    $f22,(22*8+offes_fltregs)(a0)
752         ldc1    $f23,(23*8+offes_fltregs)(a0)
753         ldc1    $f24,(24*8+offes_fltregs)(a0)
754         ldc1    $f25,(25*8+offes_fltregs)(a0)
755         ldc1    $f26,(26*8+offes_fltregs)(a0)
756         ldc1    $f27,(27*8+offes_fltregs)(a0)
757         ldc1    $f28,(28*8+offes_fltregs)(a0)
758         ldc1    $f29,(29*8+offes_fltregs)(a0)
759         ldc1    $f30,(30*8+offes_fltregs)(a0)
760         ldc1    $f31,(31*8+offes_fltregs)(a0)
761
762         /* load new pc */
763
764         ld      itmp3,offes_pc(a0)
765
766         /* load a0 */
767         
768         ld      a0,(4*8+offes_intregs)(a0)
769
770         /* jump to new code */
771
772         jr      itmp3
773
774         .end asm_replacement_in
775
776 /******************* function asm_initialize_thread_stack **********************
777 *                                                                              *
778 *   u1* asm_initialize_thread_stack (void *func, u1 *stack);                   *
779 *                                                                              *
780 *   initialize a thread stack                                                  *
781 *                                                                              *
782 *******************************************************************************/
783
784         .ent    asm_initialize_thread_stack
785
786 asm_initialize_thread_stack:
787         aaddiu  a1,a1,-14*8     /* allocate save area                             */
788         sd      zero, 0*8(a1)   /* s0 initalize thread area                       */
789         sd      zero, 1*8(a1)   /* s1                                             */
790         sd      zero, 2*8(a1)   /* s2                                             */
791         sd      zero, 3*8(a1)   /* s3                                             */
792         sd      zero, 4*8(a1)   /* s4                                             */
793         sd      zero, 5*8(a1)   /* s5                                             */
794         sd      zero, 6*8(a1)   /* s6                                             */
795         sd      zero, 7*8(a1)   /* s7                                             */
796         sd      zero, 8*8(a1)   /* s8                                             */
797         sd      zero, 9*8(a1)   /* fs0                                            */
798         sd      zero,10*8(a1)   /* fs1                                            */
799         sd      zero,11*8(a1)   /* fs2                                            */
800         sd      zero,12*8(a1)   /* fs3                                            */
801         sd      a0, 13*8(a1)
802         move    v0,a1
803         j       ra              /* return                                         */
804
805         .end    asm_initialize_thread_stack
806
807
808 /******************* function asm_perform_threadswitch *************************
809 *                                                                              *
810 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
811 *                                                                              *
812 *   performs a threadswitch                                                    *
813 *                                                                              *
814 *******************************************************************************/
815
816         .ent    asm_perform_threadswitch
817
818 asm_perform_threadswitch:
819         aaddiu  sp,sp,-14*8     /* allocate new stack                             */
820         sd      s0,  0*8(sp)    /* save saved registers of old thread             */
821         sd      s1,  1*8(sp)
822         sd      s2,  2*8(sp)
823         sd      s3,  3*8(sp)
824         sd      s4,  4*8(sp)
825         sd      s5,  5*8(sp)
826         sd      s6,  6*8(sp)
827         sd      s7,  7*8(sp)
828         sd      s8,  8*8(sp)
829         sdc1    fs0, 9*8(sp)
830         sdc1    fs1,10*8(sp)
831         sdc1    fs2,11*8(sp)
832         sdc1    fs3,12*8(sp)
833         sd      ra, 13*8(sp)
834         ast     sp,0(a0)        /* save old stack pointer                         */
835         ast     sp,0(a2)        /* stackTop = old stack pointer                   */
836         ald     sp,0(a1)        /* load new stack pointer                         */
837         ld      s0,  0*8(sp)    /* load saved registers of new thread             */
838         ld      s1,  1*8(sp)
839         ld      s2,  2*8(sp)
840         ld      s3,  3*8(sp)
841         ld      s4,  4*8(sp)
842         ld      s5,  5*8(sp)
843         ld      s6,  6*8(sp)
844         ld      s7,  7*8(sp)
845         ld      s8,  8*8(sp)
846         ldc1    fs0, 9*8(sp)
847         ldc1    fs1,10*8(sp)
848         ldc1    fs2,11*8(sp)
849         ldc1    fs3,12*8(sp)
850         ld      ra, 13*8(sp)
851         aaddiu  sp,sp,14*8      /* deallocate new stack                           */
852         move    itmp3, ra
853         j       ra              /* return                                         */
854
855         .end    asm_perform_threadswitch
856
857
858 /********************* function asm_switchstackandcall *************************
859 *                                                                              *
860 *  void asm_switchstackandcall (void *stack, void *func, void **stacktopsave); *
861 *                                                                              *
862 *   Switches to a new stack, calls a function and switches back.               *
863 *       a0      new stack pointer                                              *
864 *       a1      function pointer                                               *
865 *               a2              pointer to variable where stack top should be stored           *
866 *                                                                              *
867 *******************************************************************************/
868
869         .ent    asm_switchstackandcall
870
871 asm_switchstackandcall:
872         aaddiu  a0,a0,-16       /* allocate new stack                             */
873         sd      ra,0(a0)        /* save return address on new stack               */
874         sd      sp,8(a0)        /* save old stack pointer on new stack            */
875         sd      sp,0(a2)        /* save old stack pointer to variable             */
876         move    sp,a0           /* switch to new stack                            */
877         
878         move    itmp3,a1
879         move    a0,a3
880         jalr    itmp3           /* and call function                              */
881
882         ld      ra,0(sp)        /* load return address                            */
883         ld      sp,8(sp)        /* switch to old stack                            */
884
885         j       ra              /* return                                         */
886
887         .end    asm_switchstackandcall
888
889
890         .ent    asm_getclassvalues_atomic
891
892 asm_getclassvalues_atomic:
893 _crit_restart:
894 _crit_begin:
895         lw      t0,offbaseval(a0)
896         lw      t1,offdiffval(a0)
897         lw      t2,offbaseval(a1)
898 _crit_end:
899         sw      t0,offcast_super_baseval(a2)
900         sw      t1,offcast_super_diffval(a2)
901         sw      t2,offcast_sub_baseval(a2)
902         j       ra
903
904         .end    asm_getclassvalues_atomic
905
906     .data
907
908 asm_criticalsections:
909 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
910     .dword  _crit_begin
911     .dword  _crit_end
912     .dword  _crit_restart
913 #endif
914     .dword  0
915
916
917         .text
918
919         .ent    compare_and_swap
920
921 compare_and_swap:
922 1:
923         all     v0,0(a0)
924         bne     v0,a1,2f
925         move    t0,a2
926         asc     t0,0(a0)
927         beqz    t0,1b
928 2:
929         sync
930         j       ra
931
932         .end    compare_and_swap
933
934
935 /* Disable exec-stacks, required for Gentoo ***********************************/
936
937 #if defined(__GCC__) && defined(__ELF__)
938         .section .note.GNU-stack,"",@progbits
939 #endif
940
941
942 /*
943  * These are local overrides for various environment variables in Emacs.
944  * Please do not remove this and leave it at the end of the file, where
945  * Emacs will automagically detect them.
946  * ---------------------------------------------------------------------
947  * Local variables:
948  * mode: asm
949  * indent-tabs-mode: t
950  * c-basic-offset: 4
951  * tab-width: 4
952  * End:
953  * vim:noexpandtab:sw=4:ts=4:
954  */