Merged revisions 8245-8298 via svnmerge from
[cacao.git] / src / vm / jit / s390 / asmpart.S
1 /* src/vm/jit/s390/asmpart.S - Java-C interface functions for s390
2
3    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: asmpart.S 8298 2007-08-12 18:49:16Z 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
36 #include "vm/jit/abi-asm.h"
37 #include "vm/jit/methodheader.h"
38
39         .text
40
41
42 /* export functions ***********************************************************/
43
44         .globl asm_vm_call_method
45         .globl asm_vm_call_method_int
46         .globl asm_vm_call_method_long
47         .globl asm_vm_call_method_float
48         .globl asm_vm_call_method_double
49         .globl asm_vm_call_method_exception_handler
50         .globl asm_vm_call_method_end
51
52         .globl asm_call_jit_compiler
53
54         .globl asm_handle_exception
55         .globl asm_handle_nat_exception
56
57         .globl asm_abstractmethoderror
58
59         .globl asm_replacement_out
60         .globl asm_replacement_in
61
62         .globl asm_builtin_f2i
63         .globl asm_builtin_f2l
64         .globl asm_builtin_d2i
65         .globl asm_builtin_d2l
66
67
68 asm_abstractmethoderror:
69         .long 0
70 asm_replacement_out:
71         .long 0
72 asm_replacement_in:
73         .long 0
74 asm_builtin_f2i:
75         .long 0
76 asm_builtin_f2l:
77         .long 0
78 asm_builtin_d2i:
79         .long 0
80 asm_builtin_d2l:
81         .long 0
82
83 /********************* function asm_calljavafunction ***************************
84 *                                                                              *
85 *   This function calls a Java-method (which possibly needs compilation)       *
86 *   with up to 4 address parameters.                                           *
87 *                                                                              *
88 *   This functions calls the JIT-compiler which eventually translates the      *
89 *   method into machine code.                                                  *
90 *                                                                              *
91 *   C-prototype:                                                               *
92 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
93 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
94 *                                                                              *
95 *******************************************************************************/
96
97         .long   0                         /* catch type all                       */
98         .long   0                         /* exception handler pc                 */
99         .long   0                         /* end pc                               */
100         .long   0                         /* start pc                             */
101         .long   1                         /* extable size                         */
102         .long   0                         /* line number table start              */
103         .long   0                         /* line number table size               */
104         .long   0                         /* fltsave                              */
105         .long   0                         /* intsave                              */
106         .long   0                         /* IsLeaf                               */
107         .long   0                         /* IsSync                               */
108         .long   0                         /* frame size                           */
109         .long   0                         /* codeinfo pointer                     */
110
111 asm_vm_call_method:
112 asm_vm_call_method_int:
113 asm_vm_call_method_long:
114 asm_vm_call_method_float:
115 asm_vm_call_method_double:
116
117         ahi sp, -8*4                /* allocate stack frame */
118
119         /* a0: PV */
120         /* a1: data structure */
121         /* a2: number of stack arguments */
122
123         st    s0, 0*4(sp)           /* store used calle saved registers */
124         st    s1, 1*4(sp)
125         st    a0, 2*4(sp)
126         st    mptr, 3*4(sp)         /* mptr/itmp2 is callee saved in terms of C abi */
127         st    pv, 4*4(sp)
128         st    a4, 5*4(sp)           /* a4 is callee saved in terms of C abi */
129         st    ra, 6*4(sp)
130
131         lr    s0, a1                /* data structure */
132         lr    %r0, a2               /* number of stack arguments */
133
134         l     a0, 0*8+4(s0)         /* big endian */
135         l     a1, 1*8+4(s0)
136         l     a2, 2*8+4(s0)
137         l     a3, 3*8+4(s0)
138         l     a4, 4*8+4(s0)         
139
140         ld    fa0, 5*8(s0)
141         ld    fa1, 6*8(s0)
142
143         lr    s1, sp                /* backup stack pointer */
144
145         ltr   %r0, %r0              /* are there any stack arguments ? */
146         je    L_asm_vm_call_method_stack_copy_done
147         lr    %r1, %r0              /* copy number of stack arguments */
148         sll   %r1, 3                /* calculate stackframe size */ 
149         sr    sp, %r1               /* allocate stack frame */
150         lr    %r1, sp               /* temporary stack pointer */
151
152 L_asm_vm_call_method_stack_copy_loop:
153
154         mvc   0(8, %r1), 7*8(s0)    /* copy argument */
155         ahi   %r1, 8                /* increase sp */
156         ahi   s0, 8                 /* set address of next argument */
157         ahi   %r0, -1               /* substract 1 argument */
158         jh    L_asm_vm_call_method_stack_copy_loop
159
160 L_asm_vm_call_method_stack_copy_done:
161
162         la    mptr, 2*4(s1)         /* load method pointer */
163         l     pv, 0(mptr)           /* load procedure vector from method pointer */
164         basr  ra, pv                /* call method */
165         lr    sp, s1                /* restore stack pointer */
166
167 L_asm_vm_call_method_return:
168
169         l     s0, 0*4(sp)           /* restore used callee saved registers */
170         l     s1, 1*4(sp)
171         l     mptr, 3*4(sp)
172         l     pv, 4*4(sp)
173         l     a4, 5*4(sp)
174         l     ra, 6*4(sp)
175
176         ahi   sp, 8*4               /* remove stackframe */
177         br    ra                    /* return */
178
179
180 asm_vm_call_method_exception_handler:
181         lr    a0, xptr
182
183         bras  %r14, L_avcmeh_bras
184         .long builtin_throw_exception
185 L_avcmeh_bras:
186         l     %r14, 0(%r14)
187         ahi   sp, -96
188         basr  %r14, %r14
189         ahi   sp, 96
190         j     L_asm_vm_call_method_return
191
192 asm_vm_call_method_end:
193         brc   0,0       
194
195 /****************** function asm_call_jit_compiler *****************************
196 *                                                                              *
197 *   invokes the compiler for untranslated JavaVM methods.                      *
198 *                                                                              *
199 *   itmp1: methodinfo pointer                                                  *
200 *   itmp2: method pointer                                                      *
201 *                                                                              *
202 *******************************************************************************/
203
204 /*
205
206 argument registers: arguments (like in JIT)
207
208         arguments on stack (like in JIT)
209 ------------------------------------------------------------- <- SP on entry
210
211         saved return address                                           \
212         stored volatile (in terms of C ABI) floag argument registers   | 
213 96      stored volatile (in terms of C ABI) integer argument registers | ACJC_STACKFRAME
214 0 - 96  register save area (C ABI)                                     /
215 -------------------------------------------------- <- SP for jit_asm_compile
216 */
217
218 /* This is called from a compiler stub.
219  * Arguments are already in registers and the stack is setup like in CACAO.
220  */
221
222 asm_call_jit_compiler:
223 L_asm_call_jit_compiler:
224
225 #       define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96)
226
227         ahi     sp,-ACJC_STACKFRAME        /* allocate stack space */
228
229         stm         %r2,%r5,96(sp)             /* store volatile int arg regs */
230         std     %f0,96+16(sp)              /* store volatile float arg regs */
231         std     %f2,96+24(sp)              
232         st      %r14,96+32(sp)             /* store return address */
233
234         /* load arguments */
235
236         lr      a0,itmp1                   /* pass methodinfo pointer            */
237         lr      a1,itmp2                   /* pass method pointer                */
238         la      a2,ACJC_STACKFRAME(sp)     /* pass java sp                       */
239         la      a3,0(%r14)                 /* pass return address, make sure bit 32 is 0 */
240
241         /* call jit_asm_compile in a PIC way */
242
243         bras    itmp2, L_bras_jac
244         .long   jit_asm_compile
245 L_bras_jac:
246         l       itmp2, 0(itmp2)
247         basr    %r14, itmp2
248
249         lr      pv, v0                     /* save return value */
250
251         lm      %r2,%r5,96(sp)             /* restore volatile int arg regs */
252         ld      %f0,96+16(sp)              /* restore volatile float arg regs */
253         ld      %f2,96+24(sp)              /* restore volatile float arg regs */
254
255         ltr     pv,pv
256         je      L_asm_call_jit_compiler_exception
257
258         l       %r14,96+32(sp)             /* restore return address */
259         ahi     sp, ACJC_STACKFRAME        /* remove stack frame */
260
261 jit_code_entry:                        /* label to set breakpoint on */
262         br      pv                         /* call the method, it will return to the caller */
263
264
265 L_asm_call_jit_compiler_exception:
266         bras    itmp2, L_bras_acjce
267         .long exceptions_get_and_clear_exception
268 L_bras_acjce:
269         l       itmp2, 0(itmp2)
270         basr    %r14, itmp2
271         lr      xptr, %r2
272         l       xpc,96+32(sp)              /* restore return address */
273         ahi     sp, ACJC_STACKFRAME        /* remove stack frame */
274         j       L_asm_handle_nat_exception
275
276
277 /* asm_handle_exception ********************************************************
278 *                                                                              *
279 *   This function handles an exception. It does not use the usual calling      *
280 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
281 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
282 *   the local exception table for a handler. If no one is found, it unwinds    *
283 *   stacks and continues searching the callers.                                *
284 *                                                                              *
285 *******************************************************************************/
286
287 asm_handle_nat_exception:
288 L_asm_handle_nat_exception:
289         /* TODO really nothing here ? */
290 asm_handle_exception:
291 L_asm_handle_exception:
292
293         /* a wrapper for md_handle_exception */
294
295 #       define STACKFRAMESIZE (96 + (16 * 4) + (16 * 8) + (4 * 4))
296 #       define REGS 96
297 #       define FREGS (96 + (16 * 4))
298 #       define OUT (96 + (16 * 4) + (16 * 8))
299
300         ahi   sp, -STACKFRAMESIZE   /* allocate stack frame containing the arrays */
301
302         /* store special registers to array */
303
304         st    xptr, REGS+(1*4)(sp)
305         st    xpc, REGS+(12*4)(sp)
306         st    pv, REGS+(13*4)(sp)
307         la    itmp3, STACKFRAMESIZE(sp)
308         st    itmp3, REGS+(15*4)(sp)
309
310         /* store temporary and argument registers */
311
312         stm   a0, a4, REGS+(2*4)(sp)
313         std   %f0, FREGS+(0*8)(sp)
314         std   %f1, FREGS+(1*8)(sp)
315         std   %f2, FREGS+(2*8)(sp)
316         std   %f3, FREGS+(3*8)(sp)
317         std   %f5, FREGS+(5*8)(sp)
318         std   %f7, FREGS+(7*8)(sp)
319         std   %f8, FREGS+(8*8)(sp)
320         std   %f9, FREGS+(9*8)(sp)
321         std   %f10, FREGS+(10*8)(sp)
322         std   %f11, FREGS+(11*8)(sp)
323         std   %f12, FREGS+(12*8)(sp)
324         std   %f13, FREGS+(13*8)(sp)
325         std   %f14, FREGS+(14*8)(sp)
326         std   %f15, FREGS+(15*8)(sp)
327
328         /* call md_handle_exception */
329
330         la    a0, REGS(sp)
331         la    a1, FREGS(sp)
332         la    a2, OUT(sp)
333
334         bras    %r14,L_ahe_bras
335         .long   md_handle_exception
336 L_ahe_bras:
337         l       %r14,0(%r14)
338         basr    %r14,%r14
339
340         l     itmp3, OUT+(2*4)(sp)  /* out[2] contains maybe leaf flag */
341         ltr   itmp3, itmp3           
342         je    L_restore_saved
343
344 L_restore_temporary_and_argument:
345
346         /* if we are maybe leaf,
347          * we have to restore argument and temporary registers
348          */
349
350         lm    a0, a4, REGS+(2*4)(sp)
351         ld    %f0, FREGS+(0*8)(sp)
352         ld    %f1, FREGS+(1*8)(sp)
353         ld    %f2, FREGS+(2*8)(sp)
354         ld    %f3, FREGS+(3*8)(sp)
355         ld    %f5, FREGS+(5*8)(sp)
356         ld    %f7, FREGS+(7*8)(sp)
357         ld    %f8, FREGS+(8*8)(sp)
358         ld    %f9, FREGS+(9*8)(sp)
359         ld    %f10, FREGS+(10*8)(sp)
360         ld    %f11, FREGS+(11*8)(sp)
361         ld    %f12, FREGS+(12*8)(sp)
362         ld    %f13, FREGS+(13*8)(sp)
363         ld    %f14, FREGS+(14*8)(sp)
364         ld    %f15, FREGS+(15*8)(sp)
365
366         j     L_restore_done
367
368 L_restore_saved:
369
370         /* if we are not a maybe leaf,
371          * we have to restore callee saved registers of the callee
372          */
373
374         l     itmp3, OUT+(0*4)(sp)  /* out[0] contains IntSav */
375
376         ahi   itmp3, -1
377         jl    L_int_done
378         l     s4, REGS+(11*4)(sp)
379
380         ahi   itmp3, -1
381         jl    L_int_done
382         l     s3, REGS+(10*4)(sp)
383
384         ahi   itmp3, -1
385         jl    L_int_done
386         l     s2, REGS+(9*4)(sp)
387
388         ahi   itmp3, -1
389         jl    L_int_done
390         l     s1, REGS+(8*4)(sp)
391
392         ahi   itmp3, -1
393         jl    L_int_done
394         l     s0, REGS+(7*4)(sp)
395
396 L_int_done:
397
398         /* restore callee saved float registers */
399
400         l     itmp3, OUT+(1*4)(sp)   /* out[1] contains FltSav */
401
402         ahi   itmp3, -1
403         jl    L_flt_done
404         ld    %f6, FREGS+(6*8)(sp)
405
406         ahi   itmp3, -1
407         jl    L_flt_done
408         ld    %f4, FREGS+(4*8)(sp)
409
410 L_flt_done:
411
412 L_restore_done:
413
414         /* write new values for special registers */
415
416         l     xptr, REGS+(1*4)(sp)
417         l     xpc, REGS+(12*4)(sp)
418         l     pv, REGS+(13*4)(sp)  
419         l     sp, REGS+(15*4)(sp)   
420
421         br    xpc                   /* jump to handler */
422
423 #       undef STACKFRAMESIZE
424 #       undef REGS
425 #       undef FREGS
426 #       undef OUT
427
428 #if 0
429
430 /* asm_abstractmethoderror *****************************************************
431
432    Creates and throws an AbstractMethodError.
433
434 *******************************************************************************/
435
436 asm_abstractmethoderror:
437         mov     sp,a0                       /* pass java sp                       */
438         add     $1*8,a0
439         mov     0*8(sp),a1                  /* pass exception address             */
440         sub     $3,a1
441         call    exceptions_asm_new_abstractmethoderror@PLT
442                                             /* exception pointer is return value  */
443         pop     xpc                         /* get exception address              */
444         sub     $3,xpc                      /* exception address is ra - 3        */
445         jmp     L_asm_handle_exception
446
447 #endif
448
449 #if 0
450
451 /* asm_replacement_out *********************************************************
452
453    This code is jumped to from the replacement-out stubs that are executed
454    when a thread reaches an activated replacement point.
455
456    The purpose of asm_replacement_out is to read out the parts of the
457    execution state that cannot be accessed from C code, store this state,
458    and then call the C function replace_me.
459
460    Stack layout:
461       8                 start of stack inside method to replace
462       0   rplpoint *    info on the replacement point that was reached
463
464 *******************************************************************************/
465
466 /* some room to accomodate changes of the stack frame size during replacement */
467         /* XXX we should find a cleaner solution here */
468 #define REPLACEMENT_ROOM  512
469
470 asm_replacement_out:
471     /* create stack frame */
472         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
473
474         /* save registers in execution state */
475         mov     %rax,(RAX*8+offes_intregs)(sp)
476         mov     %rbx,(RBX*8+offes_intregs)(sp)
477         mov     %rcx,(RCX*8+offes_intregs)(sp)
478         mov     %rdx,(RDX*8+offes_intregs)(sp)
479         mov     %rsi,(RSI*8+offes_intregs)(sp)
480         mov     %rdi,(RDI*8+offes_intregs)(sp)
481         mov     %rbp,(RBP*8+offes_intregs)(sp)
482         movq    $0  ,(RSP*8+offes_intregs)(sp) /* not used */
483         mov     %r8 ,(R8 *8+offes_intregs)(sp)
484         mov     %r9 ,(R9 *8+offes_intregs)(sp)
485         mov     %r10,(R10*8+offes_intregs)(sp)
486         mov     %r11,(R11*8+offes_intregs)(sp)
487         mov     %r12,(R12*8+offes_intregs)(sp)
488         mov     %r13,(R13*8+offes_intregs)(sp)
489         mov     %r14,(R14*8+offes_intregs)(sp)
490         mov     %r15,(R15*8+offes_intregs)(sp)
491
492         movq    %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
493         movq    %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
494         movq    %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
495         movq    %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
496         movq    %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
497         movq    %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
498         movq    %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
499         movq    %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
500         movq    %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
501         movq    %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
502         movq    %xmm10,(XMM10*8+offes_fltregs)(sp)
503         movq    %xmm11,(XMM11*8+offes_fltregs)(sp)
504         movq    %xmm12,(XMM12*8+offes_fltregs)(sp)
505         movq    %xmm13,(XMM13*8+offes_fltregs)(sp)
506         movq    %xmm14,(XMM14*8+offes_fltregs)(sp)
507         movq    %xmm15,(XMM15*8+offes_fltregs)(sp)
508
509         /* calculate sp of method */
510         mov     sp,itmp1
511         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
512         mov     itmp1,(offes_sp)(sp)
513
514         /* pv must be looked up via AVL tree */
515         movq    $0,(offes_pv)(sp)
516
517         /* call replace_me */
518         mov     -8(itmp1),a0                /* rplpoint *                         */
519     mov     sp,a1                       /* arg1: execution state              */
520     call    replace_me@PLT              /* call C function replace_me         */
521     call    abort@PLT                   /* NEVER REACHED                      */
522
523 /* asm_replacement_in **********************************************************
524
525    This code writes the given execution state and jumps to the replacement
526    code.
527
528    This function never returns!
529
530    C prototype:
531       void asm_replacement_in(executionstate *es);
532
533 *******************************************************************************/
534
535 asm_replacement_in:
536         mov     a0,%rbp                     /* executionstate *es                 */
537
538         /* set new sp */
539         mov     (offes_sp)(%rbp),%rsp
540         
541         /* store address of new code */
542         push    (offes_pc)(%rbp)
543         
544         /* copy registers from execution state */
545         movq    (XMM0 *8+offes_fltregs)(%rbp),%xmm0
546         movq    (XMM1 *8+offes_fltregs)(%rbp),%xmm1
547         movq    (XMM2 *8+offes_fltregs)(%rbp),%xmm2
548         movq    (XMM3 *8+offes_fltregs)(%rbp),%xmm3
549         movq    (XMM4 *8+offes_fltregs)(%rbp),%xmm4
550         movq    (XMM5 *8+offes_fltregs)(%rbp),%xmm5
551         movq    (XMM6 *8+offes_fltregs)(%rbp),%xmm6
552         movq    (XMM7 *8+offes_fltregs)(%rbp),%xmm7
553         movq    (XMM8 *8+offes_fltregs)(%rbp),%xmm8
554         movq    (XMM9 *8+offes_fltregs)(%rbp),%xmm9
555         movq    (XMM10*8+offes_fltregs)(%rbp),%xmm10
556         movq    (XMM11*8+offes_fltregs)(%rbp),%xmm11
557         movq    (XMM12*8+offes_fltregs)(%rbp),%xmm12
558         movq    (XMM13*8+offes_fltregs)(%rbp),%xmm13
559         movq    (XMM14*8+offes_fltregs)(%rbp),%xmm14
560         movq    (XMM15*8+offes_fltregs)(%rbp),%xmm15
561
562         mov     (RAX*8+offes_intregs)(%rbp),%rax
563         mov     (RBX*8+offes_intregs)(%rbp),%rbx
564         mov     (RCX*8+offes_intregs)(%rbp),%rcx
565         mov     (RDX*8+offes_intregs)(%rbp),%rdx
566         mov     (RSI*8+offes_intregs)(%rbp),%rsi
567         mov     (RDI*8+offes_intregs)(%rbp),%rdi
568         mov     (R8 *8+offes_intregs)(%rbp),%r8
569         mov     (R9 *8+offes_intregs)(%rbp),%r9
570         mov     (R10*8+offes_intregs)(%rbp),%r10
571         mov     (R11*8+offes_intregs)(%rbp),%r11
572         mov     (R12*8+offes_intregs)(%rbp),%r12
573         mov     (R13*8+offes_intregs)(%rbp),%r13
574         mov     (R14*8+offes_intregs)(%rbp),%r14
575         mov     (R15*8+offes_intregs)(%rbp),%r15
576
577         mov     (RBP*8+offes_intregs)(%rbp),%rbp
578
579         /* jump to new code */
580         ret
581 #endif
582
583
584 /*
585  * These are local overrides for various environment variables in Emacs.
586  * Please do not remove this and leave it at the end of the file, where
587  * Emacs will automagically detect them.
588  * ---------------------------------------------------------------------
589  * Local variables:
590  * mode: asm
591  * indent-tabs-mode: t
592  * c-basic-offset: 4
593  * tab-width: 4
594  * End:
595  * vim:noexpandtab:sw=4:ts=4:
596  */