* src/vm/jit/s390/codegen.c (codegen): Added ICMD_AASTORE.
[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 7414 2007-02-28 07:22:04Z 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         j     L_copy_done
416
417 L_handle_i0:
418         l     a0, offvmargdata+4(itmp1)
419         j     L_register_copy
420 L_handle_i1:
421         l     a1, offvmargdata+4(itmp1)
422         j     L_register_copy
423 L_handle_i2:
424         l     a2, offvmargdata+4(itmp1)
425         j     L_register_copy
426 L_handle_i3:
427         l     a3, offvmargdata+4(itmp1)
428         j     L_register_copy
429 L_handle_i4:
430         l     a4, offvmargdata+4(itmp1)
431         j     L_register_copy
432
433 L_handle_l0:
434         lm    a0, a1, offvmargdata(itmp1)
435         j     L_register_copy
436 L_handle_l1:
437         lm    a1, a2, offvmargdata(itmp1)
438         j     L_register_copy
439 L_handle_l2:
440         lm    a2, a3, offvmargdata(itmp1)
441         j     L_register_copy
442 L_handle_l3:
443         lm    a3, a4, offvmargdata(itmp1)
444         j     L_register_copy
445
446 L_handle_f0:
447         le    fa0, offvmargdata(itmp1)
448         j     L_register_copy
449 L_handle_f1:
450         le    fa1, offvmargdata(itmp1)
451         j     L_register_copy
452
453 L_handle_d0:
454         ld    fa0, offvmargdata(itmp1)
455         j     L_register_copy
456 L_handle_d1:
457         ld    fa1, offvmargdata(itmp1)
458         j     L_register_copy
459
460
461 /****************** function asm_call_jit_compiler *****************************
462 *                                                                              *
463 *   invokes the compiler for untranslated JavaVM methods.                      *
464 *                                                                              *
465 *   itmp1: methodinfo pointer                                                  *
466 *   itmp2: method pointer                                                      *
467 *                                                                              *
468 *******************************************************************************/
469
470 /*
471
472 argument registers: arguments (like in JIT)
473
474         arguments on stack (like in JIT)
475 ------------------------------------------------------------- <- SP on entry
476
477         saved return address                                           \
478         stored volatile (in terms of C ABI) floag argument registers   | 
479 96      stored volatile (in terms of C ABI) integer argument registers | ACJC_STACKFRAME
480 0 - 96  register save area (C ABI)                                     /
481 -------------------------------------------------- <- SP for jit_asm_compile
482 */
483
484 /* This is called from a compiler stub.
485  * Arguments are already in registers and the stack is setup like in CACAO.
486  */
487
488 asm_call_jit_compiler:
489 L_asm_call_jit_compiler:
490
491 #       define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96)
492
493         ahi     sp,-ACJC_STACKFRAME        /* allocate stack space */
494
495         stm         %r2,%r5,96(sp)             /* store volatile int arg regs */
496         std     %f0,96+16(sp)              /* store volatile float arg regs */
497         std     %f2,96+24(sp)              
498         st      %r14,96+32(sp)             /* store return address */
499
500         /* load arguments */
501
502         lr      a0,itmp1                   /* pass methodinfo pointer            */
503         lr      a1,itmp2                   /* pass method pointer                */
504         la      a2,ACJC_STACKFRAME(sp)     /* pass java sp                       */
505         la      a3,0(%r14)                 /* pass return address, make sure bit 32 is 0 */
506
507         /* call jit_asm_compile in a PIC way */
508
509         bras    itmp2, L_bras_jac
510         .long   jit_asm_compile
511 L_bras_jac:
512         l       itmp2, 0(itmp2)
513         basr    %r14, itmp2
514
515         lr      pv, v0                     /* save return value */
516
517         lm      %r2,%r5,96(sp)             /* restore volatile int arg regs */
518         ld      %f0,96+16(sp)              /* restore volatile float arg regs */
519         ld      %f2,96+24(sp)              /* restore volatile float arg regs */
520
521         ltr     pv,pv
522         je      L_asm_call_jit_compiler_exception
523
524         l       %r14,96+32(sp)             /* restore return address */
525         ahi     sp, ACJC_STACKFRAME        /* remove stack frame */
526
527 jit_code_entry:                        /* label to set breakpoint on */
528         br      pv                         /* call the method, it will return to the caller */
529
530
531 L_asm_call_jit_compiler_exception:
532         bras    itmp2, L_bras_acjce
533         .long exceptions_get_and_clear_exception
534 L_bras_acjce:
535         l       itmp2, 0(itmp2)
536         basr    %r14, itmp2
537         lr      xptr, %r2
538         l       xpc,96+32(sp)              /* restore return address */
539         ahi     sp, ACJC_STACKFRAME        /* remove stack frame */
540         j       L_asm_handle_nat_exception
541
542
543 #if 0
544 /* asm_handle_exception ********************************************************
545 *                                                                              *
546 *   This function handles an exception. It does not use the usual calling      *
547 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
548 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
549 *   the local exception table for a handler. If no one is found, it unwinds    *
550 *   stacks and continues searching the callers.                                *
551 *                                                                              *
552 *******************************************************************************/
553
554 #endif
555
556 asm_handle_nat_exception:
557 L_asm_handle_nat_exception:
558         /* TODO really nothing here ? */
559 asm_handle_exception:
560 L_asm_handle_exception:                 /* required for PIC code              */
561
562         ahi     sp, -(ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* create maybe-leaf stackframe */
563         STORE_ARGUMENT_REGISTERS(0)
564         STORE_TEMPORARY_REGISTERS(ARGUMENT_REGISTERS_SIZE)      
565         lhi     a3, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* prepare a3 for handle_exception */
566
567         lhi     %r0, 1                      /* set maybe-leaf flag */
568
569 L_asm_handle_exception_stack_loop:
570         ahi     sp,-(6*4)
571         st      xptr,0*4(sp)                /* save exception pointer             */
572         st      xpc,1*4(sp)                 /* save exception pc                  */
573         la      a3,(6*4)(a3,sp)             /* calculate Java sp into a3...       */
574         st      a3,3*4(sp)                  /* ...and save it                     */
575         st      %r0,4*4(sp)                 /* save maybe-leaf flag               */
576
577         lr      a0,xpc                      /* exception pc                       */
578
579         ahi     sp,-96                      /* add register save area for C code */
580
581         bras    %r14,L_ahe_bras             /* call codegen_get_pv_from_pc */
582         .long   codegen_get_pv_from_pc
583 L_ahe_bras:
584         l       %r14,0(%r14)
585         basr    %r14,%r14
586         st      v0,2*4+96(sp)               /* save data segment pointer          */
587     
588         lr      a2,v0                       /* pass data segment pointer          */
589         l       a0,0*4+96(sp)               /* pass exception pointer             */
590         l       a1,1*4+96(sp)               /* pass exception pc                  */
591         l       a3,3*4+96(sp)               /* pass Java stack pointer            */
592
593         bras    %r14,L_ahe_bras2            /* call exceptions_handle_exception */
594         .long   exceptions_handle_exception
595 L_ahe_bras2:
596         l       %r14,0(%r14)
597         basr    %r14,%r14
598
599         ahi     sp,96                       /* remove regiser save area for C code */
600
601         ltr     v0,v0
602         jz      L_asm_handle_exception_not_catched
603
604         lr      xpc,v0                      /* move handlerpc into xpc            */
605         l       xptr,0*4(sp)                /* restore exception pointer          */
606         l       %r0,4*4(sp)                 /* get maybe-leaf flag                */
607         ahi     sp,(6*4)                    /* free stack frame                   */
608
609         ltr     %r0, %r0
610         jz      L_asm_handle_exception_no_leaf
611
612         LOAD_ARGUMENT_REGISTERS(0)
613         LOAD_TEMPORARY_REGISTERS(ARGUMENT_REGISTERS_SIZE)       
614
615         ahi     sp, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* Remove maybe-leaf stackframe */
616
617 L_asm_handle_exception_no_leaf:
618         br      xpc                         /* jump to the handler */
619
620 L_asm_handle_exception_not_catched:
621         l       xptr,0*4(sp)                /* restore exception pointer          */
622         l       itmp3,2*4(sp)               /* restore data segment pointer       */
623         ahi     itmp3,-0xfff                /* for negative displacements */
624         l       %r0,4*4(sp)                 /* get maybe-leaf flag                */
625         ahi     sp,(6*4)
626
627         ltr     %r0,%r0
628         jz      L_asm_handle_exception_no_leaf_stack
629
630         ahi     sp, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* Remove maybe-leaf stackframe */
631         lhi     %r0,0                       /* clear the isleaf flags             */
632
633         /*
634         +-----------------+-----------+---------+----+
635         | Memuse          | Float Sav | Int Sav | RA |
636         |                 | 0 ... n   | 0 ... n |    |
637         +-----------------+-----------+---------+----+
638         ^                 ^           ^
639         SP                F           I
640         */
641
642 L_asm_handle_exception_no_leaf_stack:
643
644         l       itmp2,0xfff+FrameSize(itmp3)/* get frame size                     */
645         la      itmp2,0(itmp2,sp)           /* pointer to save area */
646         ahi     itmp2,-4                    /* skip RA */
647
648         l       a0,0xfff+IntSave(itmp3)     /* a0 = saved int register count  */
649
650         ltr     a0,a0
651         je      noint
652
653         sll     a0,2                        /* a0 = saved int register count * 4 */
654         sr      itmp2, a0                   /* skip Int Sav */
655
656         chi     a0,1*4
657         je      int1
658         chi     a0,2*4
659         je      int2
660         chi     a0,3*4
661         je      int3
662         chi     a0,4*4
663         je      int4
664         
665         l       s0,0*4(itmp2)
666 int4:   
667         l       s1,1*4(itmp2)
668 int3:   
669         l       s2,2*4(itmp2)
670 int2:   
671         l       s3,3*4(itmp2)
672 int1:   
673         l       s4,4*4(itmp2)
674
675 noint:
676
677         l       a0,0xfff+FltSave(itmp3)
678         ltr         a0,a0                       /* Number of saved floating point registers */
679         je      noflt
680
681         sll     a0,3                        /* Number of saved floating point registers * 8 */
682         sr      itmp2,a0
683         
684         chi     a0,1*8
685         je      flt1
686         chi    a0,2*8
687         je      flt2
688
689 flt2:   
690         ld    %f6,1*8(itmp2)
691 flt1:   
692         ld    %f4,0*8(itmp2)
693                 
694 noflt:
695
696         l       itmp3,0xfff+FrameSize(itmp3)/* get frame size (at least 4 - RA)   */
697         ahi     itmp3,-4                    /* substract 4 */
698         l       xpc,0(itmp3,sp)             /* load the new xpc -  return address */
699         la      sp, 4(itmp3,sp)             /* unwind stack                       */
700
701                                             /* exception pointer is still set     */
702 #if 0
703         sub     $3,xpc                      /* subtract 3 bytes for call          */
704 #endif
705
706         lhi     a3,0                        /* prepare a3 for handle_exception    */
707         
708         j               L_asm_handle_exception_stack_loop
709
710
711 #if 0
712
713 /* asm_abstractmethoderror *****************************************************
714
715    Creates and throws an AbstractMethodError.
716
717 *******************************************************************************/
718
719 asm_abstractmethoderror:
720         mov     sp,a0                       /* pass java sp                       */
721         add     $1*8,a0
722         mov     0*8(sp),a1                  /* pass exception address             */
723         sub     $3,a1
724         call    exceptions_asm_new_abstractmethoderror@PLT
725                                             /* exception pointer is return value  */
726         pop     xpc                         /* get exception address              */
727         sub     $3,xpc                      /* exception address is ra - 3        */
728         jmp     L_asm_handle_exception
729
730 #endif
731
732 /* asm_patcher_wrapper *********************************************************
733
734    XXX
735
736    Stack layout:
737      20   return address into JIT code (patch position)
738      16   pointer to virtual java_objectheader
739      12   machine code (which is patched back later)
740       8   unresolved class/method/field reference
741       4   data segment displacement from load instructions
742       0   patcher function pointer to call (pv afterwards)
743
744 *******************************************************************************/
745
746 asm_patcher_wrapper:
747 #       define  apw_sfs (96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE + VOLATILE_FLOAT_REGISTERS_SIZE)
748
749         ahi     sp, -apw_sfs                /* create stack frame */
750
751         /* store all volatile registers and a2, because we will touch it */
752
753         st      a2, 96(sp)
754         STORE_VOLATILE_INTEGER_REGISTERS(96 + 4)
755         STORE_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
756
757         /* pass arguments */
758
759         la      a0, apw_sfs(sp)             /* pass SP of patcher stub */
760         lr      a1, pv                      /* pass PV (if NULL, use findmethod)  */
761         lhi     a2, 0                       /* pass RA                            */
762
763         /* call patcher_wrapper */
764
765         bras    itmp1, L_apw_bras           /* call patcher_wrapper */
766         .long   patcher_wrapper
767 L_apw_bras:
768         l       itmp1, 0(itmp1)
769         basr    %r14, itmp1
770
771         /* store return value */
772
773         st      v0,0(sp)                    /* save return value */
774
775         /* restore volatile registers */
776
777         l       a2, 96(sp)
778         LOAD_VOLATILE_INTEGER_REGISTERS(96 + 4)
779         LOAD_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
780
781         l       itmp3, 0(sp)                /* restore return value */
782         ltr     itmp3, itmp3                /* exception thrown ? */
783         jne     L_asm_patcher_wrapper_exception /* handle exception */
784         l       itmp3, apw_sfs + (5 * 4)(sp) /* load return address to JIT from stack */
785         ahi     sp, apw_sfs + (6 * 4)       /* remove stack frame, and stack frame by patcher stub */
786         br      itmp3                       /* return */
787
788 L_asm_patcher_wrapper_exception:
789         lr      xptr,itmp3                  /* get exception                      */
790         l       xpc, apw_sfs + (5 * 4)(sp)  /* load return address to JIT from stack */
791         ahi     sp, apw_sfs + (6 * 4)       /* remove stack frame, and stack frame by patcher stub */
792         j       L_asm_handle_exception
793
794 #if 0
795
796 /* asm_replacement_out *********************************************************
797
798    This code is jumped to from the replacement-out stubs that are executed
799    when a thread reaches an activated replacement point.
800
801    The purpose of asm_replacement_out is to read out the parts of the
802    execution state that cannot be accessed from C code, store this state,
803    and then call the C function replace_me.
804
805    Stack layout:
806       8                 start of stack inside method to replace
807       0   rplpoint *    info on the replacement point that was reached
808
809 *******************************************************************************/
810
811 /* some room to accomodate changes of the stack frame size during replacement */
812         /* XXX we should find a cleaner solution here */
813 #define REPLACEMENT_ROOM  512
814
815 asm_replacement_out:
816     /* create stack frame */
817         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
818
819         /* save registers in execution state */
820         mov     %rax,(RAX*8+offes_intregs)(sp)
821         mov     %rbx,(RBX*8+offes_intregs)(sp)
822         mov     %rcx,(RCX*8+offes_intregs)(sp)
823         mov     %rdx,(RDX*8+offes_intregs)(sp)
824         mov     %rsi,(RSI*8+offes_intregs)(sp)
825         mov     %rdi,(RDI*8+offes_intregs)(sp)
826         mov     %rbp,(RBP*8+offes_intregs)(sp)
827         movq    $0  ,(RSP*8+offes_intregs)(sp) /* not used */
828         mov     %r8 ,(R8 *8+offes_intregs)(sp)
829         mov     %r9 ,(R9 *8+offes_intregs)(sp)
830         mov     %r10,(R10*8+offes_intregs)(sp)
831         mov     %r11,(R11*8+offes_intregs)(sp)
832         mov     %r12,(R12*8+offes_intregs)(sp)
833         mov     %r13,(R13*8+offes_intregs)(sp)
834         mov     %r14,(R14*8+offes_intregs)(sp)
835         mov     %r15,(R15*8+offes_intregs)(sp)
836
837         movq    %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
838         movq    %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
839         movq    %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
840         movq    %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
841         movq    %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
842         movq    %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
843         movq    %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
844         movq    %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
845         movq    %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
846         movq    %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
847         movq    %xmm10,(XMM10*8+offes_fltregs)(sp)
848         movq    %xmm11,(XMM11*8+offes_fltregs)(sp)
849         movq    %xmm12,(XMM12*8+offes_fltregs)(sp)
850         movq    %xmm13,(XMM13*8+offes_fltregs)(sp)
851         movq    %xmm14,(XMM14*8+offes_fltregs)(sp)
852         movq    %xmm15,(XMM15*8+offes_fltregs)(sp)
853
854         /* calculate sp of method */
855         mov     sp,itmp1
856         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
857         mov     itmp1,(offes_sp)(sp)
858
859         /* pv must be looked up via AVL tree */
860         movq    $0,(offes_pv)(sp)
861
862         /* call replace_me */
863         mov     -8(itmp1),a0                /* rplpoint *                         */
864     mov     sp,a1                       /* arg1: execution state              */
865     call    replace_me@PLT              /* call C function replace_me         */
866     call    abort@PLT                   /* NEVER REACHED                      */
867
868 /* asm_replacement_in **********************************************************
869
870    This code writes the given execution state and jumps to the replacement
871    code.
872
873    This function never returns!
874
875    C prototype:
876       void asm_replacement_in(executionstate *es);
877
878 *******************************************************************************/
879
880 asm_replacement_in:
881         mov     a0,%rbp                     /* executionstate *es                 */
882
883         /* set new sp */
884         mov     (offes_sp)(%rbp),%rsp
885         
886         /* store address of new code */
887         push    (offes_pc)(%rbp)
888         
889         /* copy registers from execution state */
890         movq    (XMM0 *8+offes_fltregs)(%rbp),%xmm0
891         movq    (XMM1 *8+offes_fltregs)(%rbp),%xmm1
892         movq    (XMM2 *8+offes_fltregs)(%rbp),%xmm2
893         movq    (XMM3 *8+offes_fltregs)(%rbp),%xmm3
894         movq    (XMM4 *8+offes_fltregs)(%rbp),%xmm4
895         movq    (XMM5 *8+offes_fltregs)(%rbp),%xmm5
896         movq    (XMM6 *8+offes_fltregs)(%rbp),%xmm6
897         movq    (XMM7 *8+offes_fltregs)(%rbp),%xmm7
898         movq    (XMM8 *8+offes_fltregs)(%rbp),%xmm8
899         movq    (XMM9 *8+offes_fltregs)(%rbp),%xmm9
900         movq    (XMM10*8+offes_fltregs)(%rbp),%xmm10
901         movq    (XMM11*8+offes_fltregs)(%rbp),%xmm11
902         movq    (XMM12*8+offes_fltregs)(%rbp),%xmm12
903         movq    (XMM13*8+offes_fltregs)(%rbp),%xmm13
904         movq    (XMM14*8+offes_fltregs)(%rbp),%xmm14
905         movq    (XMM15*8+offes_fltregs)(%rbp),%xmm15
906
907         mov     (RAX*8+offes_intregs)(%rbp),%rax
908         mov     (RBX*8+offes_intregs)(%rbp),%rbx
909         mov     (RCX*8+offes_intregs)(%rbp),%rcx
910         mov     (RDX*8+offes_intregs)(%rbp),%rdx
911         mov     (RSI*8+offes_intregs)(%rbp),%rsi
912         mov     (RDI*8+offes_intregs)(%rbp),%rdi
913         mov     (R8 *8+offes_intregs)(%rbp),%r8
914         mov     (R9 *8+offes_intregs)(%rbp),%r9
915         mov     (R10*8+offes_intregs)(%rbp),%r10
916         mov     (R11*8+offes_intregs)(%rbp),%r11
917         mov     (R12*8+offes_intregs)(%rbp),%r12
918         mov     (R13*8+offes_intregs)(%rbp),%r13
919         mov     (R14*8+offes_intregs)(%rbp),%r14
920         mov     (R15*8+offes_intregs)(%rbp),%r15
921
922         mov     (RBP*8+offes_intregs)(%rbp),%rbp
923
924         /* jump to new code */
925         ret
926
927
928 /* asm_builtin_x2x *************************************************************
929 *                                                                              *
930 *   Wrapper functions for float to int corner cases                            *
931 *                                                                              *
932 *******************************************************************************/
933
934 asm_builtin_f2i:
935         sub     $(ARG_CNT*8),sp
936         
937         SAVE_ARGUMENT_REGISTERS(0)
938         
939         movq    ftmp1,fa0
940         call    builtin_f2i@PLT
941         
942         RESTORE_ARGUMENT_REGISTERS(0)
943         
944         add     $(ARG_CNT*8),sp
945         ret
946
947
948 asm_builtin_f2l:
949         sub     $(ARG_CNT*8),sp
950         
951         SAVE_ARGUMENT_REGISTERS(0)
952         
953         movq    ftmp1,fa0
954         call    builtin_f2l@PLT
955         
956         RESTORE_ARGUMENT_REGISTERS(0)
957         
958         add     $(ARG_CNT*8),sp
959         ret
960
961
962 asm_builtin_d2i:
963         sub     $(ARG_CNT*8),sp
964         
965         SAVE_ARGUMENT_REGISTERS(0)
966         
967         movq    ftmp1,fa0
968         call    builtin_d2i@PLT
969         
970         RESTORE_ARGUMENT_REGISTERS(0)
971         
972         add     $(ARG_CNT*8),sp
973         ret
974
975
976 asm_builtin_d2l:
977         sub     $(ARG_CNT*8),sp
978         
979         SAVE_ARGUMENT_REGISTERS(0)
980         
981         movq    ftmp1,fa0
982         call    builtin_d2l@PLT
983         
984         RESTORE_ARGUMENT_REGISTERS(0)
985         
986         add     $(ARG_CNT*8),sp
987         ret
988
989 #endif /* if 0 */
990
991 /* TODO use move here ? */
992
993 asm_getclassvalues_atomic:
994 _crit_restart:
995 _crit_begin:
996         l       %r0,offbaseval(a0)
997         l       %r1,offdiffval(a0)
998         l       a3,offbaseval(a1)
999 _crit_end:
1000         st      %r0,offcast_super_baseval(a2)
1001         st      %r1,offcast_super_diffval(a2)
1002         st      a3,offcast_sub_baseval(a2)
1003         br      %r14
1004
1005         .data
1006                 
1007 asm_criticalsections:
1008 #if defined(ENABLE_THREADS)
1009         .long   _crit_begin
1010         .long   _crit_end
1011         .long   _crit_restart
1012 #endif
1013         .quad 0
1014
1015
1016 /* Disable exec-stacks, required for Gentoo ***********************************/
1017
1018 #if 0
1019
1020 #if defined(__GCC__) && defined(__ELF__)
1021         .section .note.GNU-stack,"",@progbits
1022 #endif
1023
1024
1025 #endif /* if 0 */
1026
1027 /*
1028  * These are local overrides for various environment variables in Emacs.
1029  * Please do not remove this and leave it at the end of the file, where
1030  * Emacs will automagically detect them.
1031  * ---------------------------------------------------------------------
1032  * Local variables:
1033  * mode: asm
1034  * indent-tabs-mode: t
1035  * c-basic-offset: 4
1036  * tab-width: 4
1037  * End:
1038  * vim:noexpandtab:sw=4:ts=4:
1039  */