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