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