Merged revisions 7797-7917 via svnmerge from
[cacao.git] / src / vm / jit / s390 / asmpart.S
1 /* src/vm/jit/s390/asmpart.S - Java-C interface functions for s390
2
3    Copyright (C) 2006, 2007 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    $Id: asmpart.S 7839 2007-04-29 22:46:56Z pm $
26
27 */
28
29
30 #include "config.h"
31
32 #include "vm/jit/s390/arch.h"
33 #include "vm/jit/s390/md-abi.h"
34 #include "vm/jit/s390/md-asm.h"
35 #include "vm/jit/s390/offsets.h"
36
37 #include "vm/jit/abi-asm.h"
38 #include "vm/jit/methodheader.h"
39
40         .text
41
42
43 /* export functions ***********************************************************/
44
45         .globl asm_vm_call_method
46         .globl asm_vm_call_method_int
47         .globl asm_vm_call_method_long
48         .globl asm_vm_call_method_float
49         .globl asm_vm_call_method_double
50         .globl asm_vm_call_method_exception_handler
51         .globl asm_vm_call_method_end
52
53         .globl asm_call_jit_compiler
54
55         .globl asm_handle_exception
56         .globl asm_handle_nat_exception
57
58         .globl asm_abstractmethoderror
59
60         .globl asm_patcher_wrapper
61
62         .globl asm_replacement_out
63         .globl asm_replacement_in
64
65         .globl asm_builtin_f2i
66         .globl asm_builtin_f2l
67         .globl asm_builtin_d2i
68         .globl asm_builtin_d2l
69
70         .globl asm_criticalsections
71         .globl asm_getclassvalues_atomic
72
73
74 asm_abstractmethoderror:
75         .long 0
76 asm_replacement_out:
77         .long 0
78 asm_replacement_in:
79         .long 0
80 asm_builtin_f2i:
81         .long 0
82 asm_builtin_f2l:
83         .long 0
84 asm_builtin_d2i:
85         .long 0
86 asm_builtin_d2l:
87         .long 0
88
89 /********************* function asm_calljavafunction ***************************
90 *                                                                              *
91 *   This function calls a Java-method (which possibly needs compilation)       *
92 *   with up to 4 address parameters.                                           *
93 *                                                                              *
94 *   This functions calls the JIT-compiler which eventually translates the      *
95 *   method into machine code.                                                  *
96 *                                                                              *
97 *   C-prototype:                                                               *
98 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
99 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
100 *                                                                              *
101 *******************************************************************************/
102
103         .long   0                         /* catch type all                       */
104         .long   0                         /* exception handler pc                 */
105         .long   0                         /* end pc                               */
106         .long   0                         /* start pc                             */
107         .long   1                         /* extable size                         */
108         .long   0                         /* line number table start              */
109         .long   0                         /* line number table size               */
110         .long   0                         /* fltsave                              */
111         .long   0                         /* intsave                              */
112         .long   0                         /* IsLeaf                               */
113         .long   0                         /* IsSync                               */
114         .long   0                         /* frame size                           */
115         .long   0                         /* codeinfo pointer                     */
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
123 /*
124
125 a0:   methodinfo *m
126 a1:   s4 vmargscount   ---> v0: java_objectheader *
127 a2:   vm_arg *vmargs
128 r14:  return address
129
130 96 ...     on stack parameters (none)
131 0 - 96     register save area
132 -------------------------------------------------- <- SP on asm_vm_... entry
133            local variables
134                    saved return address (important to be at 0(sp) because of md_stacktrace_get_returnaddress)
135 ----------------------------------------- <- SP after stack frame allocation
136            arguments on stack
137 ---------------------------------------------------- <- SP on JIT code entry
138            saved return address (callee saved)
139
140 */
141
142
143 /*
144         Regiser usage:
145         itmp1: argument block pointer
146         itmp2: argument counter
147         s0: integer argument counter
148         s1: float argument counter
149         s2: integer register counter
150         s3: backup argument block pointer
151         s4: backup argument count
152 */
153
154         stm   %r6, %r15, 24(sp)               /* save callers regiters */
155         stm   a0, a2, 8(sp)                   /* save arguments */
156         ahi   sp, -8                          /* allocate stack space for local variables */
157         st    %r14, 0(sp)                     /* store RA once more at bottom of stack frame */
158
159         ltr   a1, a1                          /* maybe we have no args... */
160         je    L_no_args
161
162         lr    itmp2, a1                       /* load arg count */
163         lr    itmp1, a2                       /* load arg pointer */
164
165         ahi   itmp1, -sizevmarg               /* initialize arg pointer */
166         ahi   itmp2, 1                        /* initialize arg count */ 
167         lhi   s0, 0                           /* initialize integer arg counter */
168         lhi   s2, 0                           /* initialize integer register counter */
169         lhi   s1, 0                           /* initialize float arg counter */
170
171         lr    s4, a1                          /* backup arg count */
172         lr    s3, a2                          /* backup arg pointer */
173
174 L_register_copy:
175
176         ahi   itmp1, sizevmarg                /* forward arg pointer */
177         ahi   itmp2, -1                       /* decrement arg count */
178         je    L_register_copy_done            /* no arguments left */
179
180         tm    offvmargtype+7(itmp1), 0x02     /* is this a float/double type? */
181         jne   L_register_handle_float
182
183 L_register_handle_int:
184
185         chi   s2, INT_ARG_CNT                 /* are we out of integer arg registers ? */
186         je    L_register_copy                 /* yes, next loop */
187
188         tm    offvmargtype+7(itmp1), 0x01       /* is this a 2 word type ? */
189         jne   L_register_handle_long
190
191         ahi   s0, 1                           /* increment integer arg counter */
192         ahi   s2, 1                           /* increment integer register counter */
193
194         /* handle argument */
195
196         chi   s2, 1
197         je    L_handle_i0
198         chi   s2, 2
199         je    L_handle_i1
200         chi   s2, 3
201         je    L_handle_i2
202         chi   s2, 4
203         je    L_handle_i3
204         chi   s2, 5
205         je    L_handle_i4
206
207 L_register_handle_long:
208
209         chi   s2, (INT_ARG_CNT - 1)           /* are there 2 integer arg registers left ? */
210         jl    L_register_handle_long_continue /* yes */
211         lhi   s2, INT_ARG_CNT                 /* no, drop last register */
212         j     L_register_copy
213
214 L_register_handle_long_continue:
215
216         ahi   s0, 1                           /* increment integer arg counter */
217         ahi   s2, 2                           /* consume 2 integer arg registers */
218
219         /* handle argument */
220
221         chi   s2, 2
222         je    L_handle_l0
223         chi   s2, 3
224         je    L_handle_l1
225         chi   s2, 4
226         je    L_handle_l2
227         chi   s2, 5
228         je    L_handle_l3
229
230 L_register_handle_float:
231
232         chi   s1, FLT_ARG_CNT                 /* are we out of float arg registers */
233         je    L_register_copy                 /* no arg regisers left */
234
235         ahi   s1, 1                           /* increment float argument counter */
236
237         tm    offvmargtype+7(itmp1), 0x01     /* is this a 2 word type ? */
238         jne   L_register_handle_double
239
240         /* handle argument */
241
242         chi   s1, 1
243         je    L_handle_f0
244         chi   s1, 2
245         je    L_handle_f1
246
247 L_register_handle_double:
248
249         /* handle argument */
250
251         chi   s1, 1
252         je    L_handle_d0
253         chi   s1, 2
254         je    L_handle_d1
255
256 L_register_copy_done:
257
258 /*
259         Regiser usage:
260         itmp1: argument block pointer
261         itmp2: argument counter
262         s0: integer argument counter (initialized by previous code) 
263         s1: float argument counter (initialized by previous code)
264         s2: pointer to current argument on stack
265         s3: backup argument block pointer (used to initialize itmp1)
266             after used as backup of original stack pointer
267         s4: backup argument count (used to initialize itmp2)
268             after used as size of parameters on stack
269 */
270
271         lr    itmp2, s4                     /* restore argument counter */
272         lr    itmp1, s3                     /* restore argument block pointer */
273
274                                             /* calculate remaining arguments */
275         sr    s4, s0                        /* - integer arguments in registers */
276         sr    s4, s1                        /* - float arguments in registers */
277
278         lr    s3, sp                        /* backup stack pointer (does not alter CC) */
279
280         je    L_copy_done                   /* no arguments left for stack */
281
282         sll   s4, 3                         /* allocate 8 bytes per parameter on stack */       
283         sr    sp, s4                        /* allocate stack space for arguments */ 
284
285         lr    s2, sp                        /* points now to current argument on stack */
286
287         ahi   itmp1, -sizevmarg             /* initialize argument block pointer */
288         ahi   itmp2, 1                      /* initialize argument counter */
289
290 L_stack_copy_loop:
291
292         ahi   itmp1, sizevmarg              /* forward argument block pointer */
293         ahi   itmp2, -1                     /* decrement argument counter */
294         je    L_copy_done                   /* all arguments done */
295
296         tm    offvmargtype+7(itmp1), 0x02   /* is this a float/double type? */
297         jne   L_stack_handle_float
298
299 L_stack_handle_int:
300
301         ahi   s0, -1                         /* decrement number of integer arguments in regs */
302         jhe   L_stack_copy_loop              /* argument is in register */
303
304         tm    offvmargtype+7(itmp1), 0x01    /* is this a 2 word type ? */
305         jne   L_stack_handle_long
306
307         mvc   0(4, s2), offvmargdata+4(itmp1)/* copy integer value */
308         ahi   s2, 4
309         j     L_stack_copy_loop
310
311 L_stack_handle_long:
312
313         mvc   0(8, s2), offvmargdata(itmp1)  /* copy long value */
314         ahi   s2, 8
315         j     L_stack_copy_loop
316
317 L_stack_handle_float:
318
319         ahi   s1, -1                         /* decrement number of float arguments in regs */
320         jhe   L_stack_copy_loop              /* argument is in register */
321
322         tm    offvmargtype+7(itmp1), 0x01    /* is this a 2 word type ? */
323         jne   L_stack_handle_double
324
325         mvc   0(4, s2), offvmargdata(itmp1)  /* copy float value */
326         ahi   s2, 4
327         j     L_stack_copy_loop
328
329 L_stack_handle_double:
330
331         mvc   0(8, s2), offvmargdata(itmp1)  /* copy double value */
332         ahi   s2, 8
333         j     L_stack_copy_loop
334
335 L_copy_done:
336
337         /* Now we call the compiler in a rather questionable way i needed
338          * some days to understand:
339          *
340          * We can't simply call asm_call_jit_compiler, but we have to call an 
341          * address loaded from memory like it is done in JIT code.
342          *
343          * This is because the compiler will intercept the instruction before 
344          * the call instruction, extract the address where the function pointer
345          * has been loaded from and overwrite it with the code entry.
346          *
347          * Arguments are passed in temporary registers.
348          */
349
350         /* load address of L_asm_call_jit_compiler into memory */
351
352         basr  mptr, 0                         /* store PC */
353 L_basr:
354         la    mptr, L_asm_call_jit_compiler-L_basr(mptr) /* add offset to PC */
355         st    mptr, 4(s3)                     /* store on stack */
356
357         l     itmp1, 8+8(s3)                  /* load methodinfo for compiler */
358         la    mptr, 4(s3)                     /* store **function in mptr for compiler */
359
360         /* call L_asm_call_jit_compiler like JIT code would do */
361
362         l     itmp3, 0(mptr)                  /* load address of target from memory */
363         basr  %r14, itmp3                     /* jump to target */
364
365         /* todo will s4 survive the call? */
366         ar    sp, s4                          /* remove stack space for arguments */
367
368 L_asm_vm_call_method_return:
369
370         ahi   sp, 8                           /* remove stack space for local variables */
371         lm    %r6, %r15, 24(sp)               /* restore callers registers */
372         br    %r14                            /* return */
373
374 asm_vm_call_method_exception_handler:
375         lr    a0, xptr
376
377         bras  %r14, L_avcmeh_bras
378         .long builtin_throw_exception
379 L_avcmeh_bras:
380         l     %r14, 0(%r14)
381         ahi   sp, -96
382         basr  %r14, %r14
383         ahi   sp, 96
384
385         j     L_asm_vm_call_method_return
386
387 /* .... */
388
389 L_no_args:
390         lr    s3, sp
391         lhi   s4, 0
392         j     L_copy_done
393
394 L_handle_i0:
395         l     a0, offvmargdata+4(itmp1)
396         j     L_register_copy
397 L_handle_i1:
398         l     a1, offvmargdata+4(itmp1)
399         j     L_register_copy
400 L_handle_i2:
401         l     a2, offvmargdata+4(itmp1)
402         j     L_register_copy
403 L_handle_i3:
404         l     a3, offvmargdata+4(itmp1)
405         j     L_register_copy
406 L_handle_i4:
407         l     a4, offvmargdata+4(itmp1)
408         j     L_register_copy
409
410 L_handle_l0:
411         lm    a0, a1, offvmargdata(itmp1)
412         j     L_register_copy
413 L_handle_l1:
414         lm    a1, a2, offvmargdata(itmp1)
415         j     L_register_copy
416 L_handle_l2:
417         lm    a2, a3, offvmargdata(itmp1)
418         j     L_register_copy
419 L_handle_l3:
420         lm    a3, a4, offvmargdata(itmp1)
421         j     L_register_copy
422
423 L_handle_f0:
424         le    fa0, offvmargdata(itmp1)
425         j     L_register_copy
426 L_handle_f1:
427         le    fa1, offvmargdata(itmp1)
428         j     L_register_copy
429
430 L_handle_d0:
431         ld    fa0, offvmargdata(itmp1)
432         j     L_register_copy
433 L_handle_d1:
434         ld    fa1, offvmargdata(itmp1)
435         j     L_register_copy
436
437 asm_vm_call_method_end:
438         brc   0,0       
439
440 /****************** function asm_call_jit_compiler *****************************
441 *                                                                              *
442 *   invokes the compiler for untranslated JavaVM methods.                      *
443 *                                                                              *
444 *   itmp1: methodinfo pointer                                                  *
445 *   itmp2: method pointer                                                      *
446 *                                                                              *
447 *******************************************************************************/
448
449 /*
450
451 argument registers: arguments (like in JIT)
452
453         arguments on stack (like in JIT)
454 ------------------------------------------------------------- <- SP on entry
455
456         saved return address                                           \
457         stored volatile (in terms of C ABI) floag argument registers   | 
458 96      stored volatile (in terms of C ABI) integer argument registers | ACJC_STACKFRAME
459 0 - 96  register save area (C ABI)                                     /
460 -------------------------------------------------- <- SP for jit_asm_compile
461 */
462
463 /* This is called from a compiler stub.
464  * Arguments are already in registers and the stack is setup like in CACAO.
465  */
466
467 asm_call_jit_compiler:
468 L_asm_call_jit_compiler:
469
470 #       define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96)
471
472         ahi     sp,-ACJC_STACKFRAME        /* allocate stack space */
473
474         stm         %r2,%r5,96(sp)             /* store volatile int arg regs */
475         std     %f0,96+16(sp)              /* store volatile float arg regs */
476         std     %f2,96+24(sp)              
477         st      %r14,96+32(sp)             /* store return address */
478
479         /* load arguments */
480
481         lr      a0,itmp1                   /* pass methodinfo pointer            */
482         lr      a1,itmp2                   /* pass method pointer                */
483         la      a2,ACJC_STACKFRAME(sp)     /* pass java sp                       */
484         la      a3,0(%r14)                 /* pass return address, make sure bit 32 is 0 */
485
486         /* call jit_asm_compile in a PIC way */
487
488         bras    itmp2, L_bras_jac
489         .long   jit_asm_compile
490 L_bras_jac:
491         l       itmp2, 0(itmp2)
492         basr    %r14, itmp2
493
494         lr      pv, v0                     /* save return value */
495
496         lm      %r2,%r5,96(sp)             /* restore volatile int arg regs */
497         ld      %f0,96+16(sp)              /* restore volatile float arg regs */
498         ld      %f2,96+24(sp)              /* restore volatile float arg regs */
499
500         ltr     pv,pv
501         je      L_asm_call_jit_compiler_exception
502
503         l       %r14,96+32(sp)             /* restore return address */
504         ahi     sp, ACJC_STACKFRAME        /* remove stack frame */
505
506 jit_code_entry:                        /* label to set breakpoint on */
507         br      pv                         /* call the method, it will return to the caller */
508
509
510 L_asm_call_jit_compiler_exception:
511         bras    itmp2, L_bras_acjce
512         .long exceptions_get_and_clear_exception
513 L_bras_acjce:
514         l       itmp2, 0(itmp2)
515         basr    %r14, itmp2
516         lr      xptr, %r2
517         l       xpc,96+32(sp)              /* restore return address */
518         ahi     sp, ACJC_STACKFRAME        /* remove stack frame */
519         j       L_asm_handle_nat_exception
520
521
522 #if 0
523 /* asm_handle_exception ********************************************************
524 *                                                                              *
525 *   This function handles an exception. It does not use the usual calling      *
526 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
527 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
528 *   the local exception table for a handler. If no one is found, it unwinds    *
529 *   stacks and continues searching the callers.                                *
530 *                                                                              *
531 *******************************************************************************/
532
533 #endif
534
535 asm_handle_nat_exception:
536 L_asm_handle_nat_exception:
537         /* TODO really nothing here ? */
538 asm_handle_exception:
539 L_asm_handle_exception:                 /* required for PIC code              */
540
541         ahi     sp, -(ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* create maybe-leaf stackframe */
542         STORE_ARGUMENT_REGISTERS(0)
543         STORE_TEMPORARY_REGISTERS(ARGUMENT_REGISTERS_SIZE)      
544         lhi     a3, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* prepare a3 for handle_exception */
545
546         lhi     %r0, 1                      /* set maybe-leaf flag */
547
548 L_asm_handle_exception_stack_loop:
549         ahi     sp,-(6*4)
550         st      xptr,0*4(sp)                /* save exception pointer             */
551         st      xpc,1*4(sp)                 /* save exception pc                  */
552         la      a3,(6*4)(a3,sp)             /* calculate Java sp into a3...       */
553         st      a3,3*4(sp)                  /* ...and save it                     */
554         st      %r0,4*4(sp)                 /* save maybe-leaf flag               */
555
556         lr      a0,xpc                      /* exception pc                       */
557
558         ahi     sp,-96                      /* add register save area for C code */
559
560         bras    %r14,L_ahe_bras             /* call codegen_get_pv_from_pc */
561         .long   codegen_get_pv_from_pc
562 L_ahe_bras:
563         l       %r14,0(%r14)
564         basr    %r14,%r14
565         st      v0,2*4+96(sp)               /* save data segment pointer          */
566     
567         lr      a2,v0                       /* pass data segment pointer          */
568         l       a0,0*4+96(sp)               /* pass exception pointer             */
569         l       a1,1*4+96(sp)               /* pass exception pc                  */
570         l       a3,3*4+96(sp)               /* pass Java stack pointer            */
571
572         bras    %r14,L_ahe_bras2            /* call exceptions_handle_exception */
573         .long   exceptions_handle_exception
574 L_ahe_bras2:
575         l       %r14,0(%r14)
576         basr    %r14,%r14
577
578         ahi     sp,96                       /* remove regiser save area for C code */
579
580         ltr     v0,v0
581         jz      L_asm_handle_exception_not_catched
582
583         lr      xpc,v0                      /* move handlerpc into xpc            */
584         l       xptr,0*4(sp)                /* restore exception pointer          */
585         l       pv,2*4(sp)                  /* restore PV                         */
586         l       %r0,4*4(sp)                 /* get maybe-leaf flag                */
587         ahi     sp,(6*4)                    /* free stack frame                   */
588
589         ltr     %r0, %r0
590         jz      L_asm_handle_exception_no_leaf
591
592         LOAD_ARGUMENT_REGISTERS(0)
593         LOAD_TEMPORARY_REGISTERS(ARGUMENT_REGISTERS_SIZE)       
594
595         ahi     sp, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* Remove maybe-leaf stackframe */
596
597 L_asm_handle_exception_no_leaf:
598         br      xpc                         /* jump to the handler */
599
600 L_asm_handle_exception_not_catched:
601         l       xptr,0*4(sp)                /* restore exception pointer          */
602         l       itmp3,2*4(sp)               /* restore data segment pointer       */
603         ahi     itmp3,-0xfff                /* for negative displacements */
604         l       %r0,4*4(sp)                 /* get maybe-leaf flag                */
605         ahi     sp,(6*4)
606
607         ltr     %r0,%r0
608         jz      L_asm_handle_exception_no_leaf_stack
609
610         ahi     sp, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* Remove maybe-leaf stackframe */
611         lhi     %r0,0                       /* clear the isleaf flag              */
612
613         /*
614         +-----------------+-----------+---------+----+
615         | Memuse          | Float Sav | Int Sav | RA |
616         |                 | 0 ... n   | 0 ... n |    |
617         +-----------------+-----------+---------+----+
618         ^                 ^           ^
619         SP                F           I
620
621                                       ^         ^    ^
622                                   p3        p2   p1     
623         */
624
625 L_asm_handle_exception_no_leaf_stack:
626
627         l       itmp2,0xfff+FrameSize(itmp3)/* get frame size                     */
628         la      itmp2,0(itmp2,sp)           /* pointer to save area (p1) */
629         ahi     itmp2,-4                    /* skip RA (p2) */
630         ahi     itmp2,-0xfff                /* for negative displacements */
631
632         l       a0,0xfff+IntSave(itmp3)     /* a0 = saved int register count  */
633
634         ltr     a0,a0
635         je      noint
636
637         chi     a0,1
638         je      int1
639         chi     a0,2
640         je      int2
641         chi     a0,3
642         je      int3
643         chi     a0,4
644         je      int4
645         
646 int5:
647         l       s0,0xfff-5*4(itmp2)
648 int4:   
649         l       s1,0xfff-4*4(itmp2)
650 int3:   
651         l       s2,0xfff-3*4(itmp2)
652 int2:   
653         l       s3,0xfff-2*4(itmp2)
654 int1:   
655         l       s4,0xfff-1*4(itmp2)
656
657 noint:
658
659         sll     a0,2                        /* a0 = saved int register count * 4 */
660         sr      itmp2, a0                   /* skip Int Sav (p3) */
661
662         l       a0,0xfff+FltSave(itmp3)
663         ltr         a0,a0                       /* Number of saved floating point registers */
664         je      noflt
665
666         chi     a0,1
667         je      flt1
668
669 flt2:   
670         ld    %f4,0xfff-2*8(itmp2)
671 flt1:   
672         ld    %f6,0xfff-1*8(itmp2)
673                 
674 noflt:
675
676         l       itmp3,0xfff+FrameSize(itmp3)/* get frame size (at least 4 - RA)   */
677         ahi     itmp3,-4                    /* substract 4 */
678         l       xpc,0(itmp3,sp)             /* load the new xpc -  return address */
679         la      sp, 4(itmp3,sp)             /* unwind stack                       */
680
681                                             /* exception pointer is still set     */
682 #if 0
683         sub     $3,xpc                      /* subtract 3 bytes for call          */
684 #endif
685
686         lhi     a3,0                        /* prepare a3 for handle_exception    */
687         
688         j               L_asm_handle_exception_stack_loop
689
690
691 #if 0
692
693 /* asm_abstractmethoderror *****************************************************
694
695    Creates and throws an AbstractMethodError.
696
697 *******************************************************************************/
698
699 asm_abstractmethoderror:
700         mov     sp,a0                       /* pass java sp                       */
701         add     $1*8,a0
702         mov     0*8(sp),a1                  /* pass exception address             */
703         sub     $3,a1
704         call    exceptions_asm_new_abstractmethoderror@PLT
705                                             /* exception pointer is return value  */
706         pop     xpc                         /* get exception address              */
707         sub     $3,xpc                      /* exception address is ra - 3        */
708         jmp     L_asm_handle_exception
709
710 #endif
711
712 /* asm_patcher_wrapper *********************************************************
713
714    XXX
715
716    Stack layout:
717      20   return address into JIT code (patch position)
718      16   pointer to virtual java_objectheader
719      12   machine code (which is patched back later)
720       8   unresolved class/method/field reference
721       4   data segment displacement from load instructions
722       0   patcher function pointer to call (pv afterwards)
723
724 *******************************************************************************/
725
726 asm_patcher_wrapper:
727 #       define  apw_sfs (96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE + VOLATILE_FLOAT_REGISTERS_SIZE)
728
729         ahi     sp, -apw_sfs                /* create stack frame */
730
731         /* store all volatile registers and a2, because we will touch it */
732
733         st      a2, 96(sp)
734         STORE_VOLATILE_INTEGER_REGISTERS(96 + 4)
735         STORE_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
736
737         /* pass arguments */
738
739         la      a0, apw_sfs(sp)             /* pass SP of patcher stub */
740         lr      a1, pv                      /* pass PV (if NULL, use findmethod)  */
741         lhi     a2, 0                       /* pass RA                            */
742
743         /* call patcher_wrapper */
744
745         bras    itmp1, L_apw_bras           /* call patcher_wrapper */
746         .long   patcher_wrapper
747 L_apw_bras:
748         l       itmp1, 0(itmp1)
749         basr    %r14, itmp1
750
751         /* store return value */
752
753         st      v0,0(sp)                    /* save return value */
754
755         /* restore volatile registers */
756
757         l       a2, 96(sp)
758         LOAD_VOLATILE_INTEGER_REGISTERS(96 + 4)
759         LOAD_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
760
761         l       itmp3, 0(sp)                /* restore return value */
762         ltr     itmp3, itmp3                /* exception thrown ? */
763         jne     L_asm_patcher_wrapper_exception /* handle exception */
764         l       itmp3, apw_sfs + (5 * 4)(sp) /* load return address to JIT from stack */
765         ahi     sp, apw_sfs + (6 * 4)       /* remove stack frame, and stack frame by patcher stub */
766         br      itmp3                       /* return */
767
768 L_asm_patcher_wrapper_exception:
769         lr      xptr,itmp3                  /* get exception                      */
770         l       xpc, apw_sfs + (5 * 4)(sp)  /* load return address to JIT from stack */
771         ahi     sp, apw_sfs + (6 * 4)       /* remove stack frame, and stack frame by patcher stub */
772         j       L_asm_handle_exception
773
774 #if 0
775
776 /* asm_replacement_out *********************************************************
777
778    This code is jumped to from the replacement-out stubs that are executed
779    when a thread reaches an activated replacement point.
780
781    The purpose of asm_replacement_out is to read out the parts of the
782    execution state that cannot be accessed from C code, store this state,
783    and then call the C function replace_me.
784
785    Stack layout:
786       8                 start of stack inside method to replace
787       0   rplpoint *    info on the replacement point that was reached
788
789 *******************************************************************************/
790
791 /* some room to accomodate changes of the stack frame size during replacement */
792         /* XXX we should find a cleaner solution here */
793 #define REPLACEMENT_ROOM  512
794
795 asm_replacement_out:
796     /* create stack frame */
797         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
798
799         /* save registers in execution state */
800         mov     %rax,(RAX*8+offes_intregs)(sp)
801         mov     %rbx,(RBX*8+offes_intregs)(sp)
802         mov     %rcx,(RCX*8+offes_intregs)(sp)
803         mov     %rdx,(RDX*8+offes_intregs)(sp)
804         mov     %rsi,(RSI*8+offes_intregs)(sp)
805         mov     %rdi,(RDI*8+offes_intregs)(sp)
806         mov     %rbp,(RBP*8+offes_intregs)(sp)
807         movq    $0  ,(RSP*8+offes_intregs)(sp) /* not used */
808         mov     %r8 ,(R8 *8+offes_intregs)(sp)
809         mov     %r9 ,(R9 *8+offes_intregs)(sp)
810         mov     %r10,(R10*8+offes_intregs)(sp)
811         mov     %r11,(R11*8+offes_intregs)(sp)
812         mov     %r12,(R12*8+offes_intregs)(sp)
813         mov     %r13,(R13*8+offes_intregs)(sp)
814         mov     %r14,(R14*8+offes_intregs)(sp)
815         mov     %r15,(R15*8+offes_intregs)(sp)
816
817         movq    %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
818         movq    %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
819         movq    %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
820         movq    %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
821         movq    %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
822         movq    %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
823         movq    %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
824         movq    %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
825         movq    %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
826         movq    %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
827         movq    %xmm10,(XMM10*8+offes_fltregs)(sp)
828         movq    %xmm11,(XMM11*8+offes_fltregs)(sp)
829         movq    %xmm12,(XMM12*8+offes_fltregs)(sp)
830         movq    %xmm13,(XMM13*8+offes_fltregs)(sp)
831         movq    %xmm14,(XMM14*8+offes_fltregs)(sp)
832         movq    %xmm15,(XMM15*8+offes_fltregs)(sp)
833
834         /* calculate sp of method */
835         mov     sp,itmp1
836         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
837         mov     itmp1,(offes_sp)(sp)
838
839         /* pv must be looked up via AVL tree */
840         movq    $0,(offes_pv)(sp)
841
842         /* call replace_me */
843         mov     -8(itmp1),a0                /* rplpoint *                         */
844     mov     sp,a1                       /* arg1: execution state              */
845     call    replace_me@PLT              /* call C function replace_me         */
846     call    abort@PLT                   /* NEVER REACHED                      */
847
848 /* asm_replacement_in **********************************************************
849
850    This code writes the given execution state and jumps to the replacement
851    code.
852
853    This function never returns!
854
855    C prototype:
856       void asm_replacement_in(executionstate *es);
857
858 *******************************************************************************/
859
860 asm_replacement_in:
861         mov     a0,%rbp                     /* executionstate *es                 */
862
863         /* set new sp */
864         mov     (offes_sp)(%rbp),%rsp
865         
866         /* store address of new code */
867         push    (offes_pc)(%rbp)
868         
869         /* copy registers from execution state */
870         movq    (XMM0 *8+offes_fltregs)(%rbp),%xmm0
871         movq    (XMM1 *8+offes_fltregs)(%rbp),%xmm1
872         movq    (XMM2 *8+offes_fltregs)(%rbp),%xmm2
873         movq    (XMM3 *8+offes_fltregs)(%rbp),%xmm3
874         movq    (XMM4 *8+offes_fltregs)(%rbp),%xmm4
875         movq    (XMM5 *8+offes_fltregs)(%rbp),%xmm5
876         movq    (XMM6 *8+offes_fltregs)(%rbp),%xmm6
877         movq    (XMM7 *8+offes_fltregs)(%rbp),%xmm7
878         movq    (XMM8 *8+offes_fltregs)(%rbp),%xmm8
879         movq    (XMM9 *8+offes_fltregs)(%rbp),%xmm9
880         movq    (XMM10*8+offes_fltregs)(%rbp),%xmm10
881         movq    (XMM11*8+offes_fltregs)(%rbp),%xmm11
882         movq    (XMM12*8+offes_fltregs)(%rbp),%xmm12
883         movq    (XMM13*8+offes_fltregs)(%rbp),%xmm13
884         movq    (XMM14*8+offes_fltregs)(%rbp),%xmm14
885         movq    (XMM15*8+offes_fltregs)(%rbp),%xmm15
886
887         mov     (RAX*8+offes_intregs)(%rbp),%rax
888         mov     (RBX*8+offes_intregs)(%rbp),%rbx
889         mov     (RCX*8+offes_intregs)(%rbp),%rcx
890         mov     (RDX*8+offes_intregs)(%rbp),%rdx
891         mov     (RSI*8+offes_intregs)(%rbp),%rsi
892         mov     (RDI*8+offes_intregs)(%rbp),%rdi
893         mov     (R8 *8+offes_intregs)(%rbp),%r8
894         mov     (R9 *8+offes_intregs)(%rbp),%r9
895         mov     (R10*8+offes_intregs)(%rbp),%r10
896         mov     (R11*8+offes_intregs)(%rbp),%r11
897         mov     (R12*8+offes_intregs)(%rbp),%r12
898         mov     (R13*8+offes_intregs)(%rbp),%r13
899         mov     (R14*8+offes_intregs)(%rbp),%r14
900         mov     (R15*8+offes_intregs)(%rbp),%r15
901
902         mov     (RBP*8+offes_intregs)(%rbp),%rbp
903
904         /* jump to new code */
905         ret
906
907
908 /* asm_builtin_x2x *************************************************************
909 *                                                                              *
910 *   Wrapper functions for float to int corner cases                            *
911 *                                                                              *
912 *******************************************************************************/
913
914 asm_builtin_f2i:
915         sub     $(ARG_CNT*8),sp
916         
917         SAVE_ARGUMENT_REGISTERS(0)
918         
919         movq    ftmp1,fa0
920         call    builtin_f2i@PLT
921         
922         RESTORE_ARGUMENT_REGISTERS(0)
923         
924         add     $(ARG_CNT*8),sp
925         ret
926
927
928 asm_builtin_f2l:
929         sub     $(ARG_CNT*8),sp
930         
931         SAVE_ARGUMENT_REGISTERS(0)
932         
933         movq    ftmp1,fa0
934         call    builtin_f2l@PLT
935         
936         RESTORE_ARGUMENT_REGISTERS(0)
937         
938         add     $(ARG_CNT*8),sp
939         ret
940
941
942 asm_builtin_d2i:
943         sub     $(ARG_CNT*8),sp
944         
945         SAVE_ARGUMENT_REGISTERS(0)
946         
947         movq    ftmp1,fa0
948         call    builtin_d2i@PLT
949         
950         RESTORE_ARGUMENT_REGISTERS(0)
951         
952         add     $(ARG_CNT*8),sp
953         ret
954
955
956 asm_builtin_d2l:
957         sub     $(ARG_CNT*8),sp
958         
959         SAVE_ARGUMENT_REGISTERS(0)
960         
961         movq    ftmp1,fa0
962         call    builtin_d2l@PLT
963         
964         RESTORE_ARGUMENT_REGISTERS(0)
965         
966         add     $(ARG_CNT*8),sp
967         ret
968
969 #endif /* if 0 */
970
971 /* TODO use move here ? */
972
973 asm_getclassvalues_atomic:
974 _crit_restart:
975 _crit_begin:
976         l       %r0,offbaseval(a0)
977         l       %r1,offdiffval(a0)
978         l       a3,offbaseval(a1)
979 _crit_end:
980         st      %r0,offcast_super_baseval(a2)
981         st      %r1,offcast_super_diffval(a2)
982         st      a3,offcast_sub_baseval(a2)
983         br      %r14
984
985         .data
986                 
987 asm_criticalsections:
988 #if defined(ENABLE_THREADS)
989         .long   _crit_begin
990         .long   _crit_end
991         .long   _crit_restart
992 #endif
993         .long 0
994
995
996 /* disable exec-stacks ********************************************************/
997
998 #if 0
999
1000 #if defined(__linux__) && defined(__ELF__)
1001         .section .note.GNU-stack,"",%progbits
1002 #endif
1003
1004
1005 #endif /* if 0 */
1006
1007 /*
1008  * These are local overrides for various environment variables in Emacs.
1009  * Please do not remove this and leave it at the end of the file, where
1010  * Emacs will automagically detect them.
1011  * ---------------------------------------------------------------------
1012  * Local variables:
1013  * mode: asm
1014  * indent-tabs-mode: t
1015  * c-basic-offset: 4
1016  * tab-width: 4
1017  * End:
1018  * vim:noexpandtab:sw=4:ts=4:
1019  */