* asm_calljavafunction2: keep stack 16-byte aligned
[cacao.git] / src / vm / jit / x86_64 / asmpart.S
1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    $Id: asmpart.S 2733 2005-06-17 12:18:29Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include "md-abi.h"
39 #include "md-asm.h"
40
41 #include "vm/jit/x86_64/arch.h"
42 #include "vm/jit/x86_64/asmoffsets.h"
43 #include "vm/jit/x86_64/offsets.h"
44
45
46         .text
47
48
49 /********************* exported functions and variables ***********************/
50
51         .globl asm_calljavafunction
52         .globl asm_calljavafunction_int
53
54         .globl asm_calljavafunction2
55         .globl asm_calljavafunction2int
56         .globl asm_calljavafunction2long
57         .globl asm_calljavafunction2float
58         .globl asm_calljavafunction2double
59
60         .globl asm_call_jit_compiler
61         .globl asm_handle_exception
62         .globl asm_handle_nat_exception
63
64         .globl asm_wrapper_patcher
65
66         .globl asm_builtin_arraycheckcast
67         .globl asm_builtin_aastore
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_perform_threadswitch
75         .globl asm_initialize_thread_stack
76         .globl asm_switchstackandcall
77         .globl asm_criticalsections
78         .globl asm_getclassvalues_atomic
79
80         .globl asm_prepare_native_stackinfo
81         .globl asm_remove_native_stackinfo
82         .globl asm_throw_and_handle_exception
83         .globl asm_throw_and_handle_hardware_arithmetic_exception               
84
85
86 /********************* function asm_calljavafunction ***************************
87 *                                                                              *
88 *   This function calls a Java-method (which possibly needs compilation)       *
89 *   with up to 4 address parameters.                                           *
90 *                                                                              *
91 *   This functions calls the JIT-compiler which eventually translates the      *
92 *   method into machine code.                                                  *
93 *                                                                              *
94 *   C-prototype:                                                               *
95 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
96 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
97 *                                                                              *
98 *******************************************************************************/
99
100 call_name:
101         .align  8
102
103         .quad   0                         /* catch type all                       */
104         .quad   calljava_xhandler         /* handler pc                           */
105         .quad   calljava_xhandler         /* end pc                               */
106         .quad   asm_calljavafunction      /* start pc                             */
107         .long   1                         /* extable size                         */
108         .long   0
109         .quad   0                         /* line number table start              */
110         .quad   0                         /* line number table size               */
111         .long   0
112         .long   0                         /* fltsave                              */
113         .long   0                         /* intsave                              */
114         .long   0                         /* isleaf                               */
115         .long   0                         /* IsSync                               */
116         .long   8                         /* frame size                           */
117         .quad   0                         /* method pointer (pointer to name)     */
118
119 asm_calljavafunction:
120 asm_calljavafunction_int:
121         sub     $(3*8),%rsp               /* keep stack 16-byte aligned           */
122         mov     %rbp,0*8(%rsp)
123         mov     %rbx,1*8(%rsp)            /* %rbx is not a callee saved in cacao  */
124         mov     %rdi,%rax                 /* move function pointer to %rax        */
125                                                                           /* compilerstub uses this               */
126
127         mov     %rsi,%rdi                 /* pass remaining parameters            */
128         mov     %rdx,%rsi
129         mov     %rcx,%rdx
130         mov     %r8,%rcx
131         
132         lea     asm_call_jit_compiler,%r11
133         call    *%r11                     /* call JIT compiler                    */
134
135         mov     0*8(%rsp),%rbp
136         mov             1*8(%rsp),%rbx
137         add     $(3*8),%rsp               /* free stack space                     */
138         ret
139
140 calljava_xhandler:
141         mov     %rax,%rdi                 /* pass exception pointer               */
142         call    builtin_throw_exception
143         mov     0*8(%rsp),%rbp
144         mov             1*8(%rsp),%rbx
145         add     $(3*8),%rsp
146         xor     %rax,%rax                 /* return NULL                          */
147         ret
148
149
150 /********************* function asm_calljavafunction ***************************
151 *                                                                              *
152 *   This function calls a Java-method (which possibly needs compilation)       *
153 *   with up to 4 address parameters.                                           *
154 *                                                                              *
155 *   This functions calls the JIT-compiler which eventually translates the      *
156 *   method into machine code.                                                  *
157 *                                                                              *
158 *   C-prototype:                                                               *
159 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
160 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
161 *                                                                              *
162 *******************************************************************************/
163
164 call_name2:
165         .align  8
166
167         .quad   0                         /* catch type all                       */
168         .quad   calljava_xhandler2        /* handler pc                           */
169         .quad   calljava_xhandler2        /* end pc                               */
170         .quad   asm_calljavafunction2     /* start pc                             */
171         .long   1                         /* extable size                         */
172         .long   0
173         .quad   0                         /* line number table  start             */
174         .quad   0                         /* line number table  size              */
175         .long   0
176         .long   0                         /* fltsave                              */
177         .long   0                         /* intsave                              */
178         .long   0                         /* isleaf                               */
179         .long   0                         /* IsSync                               */
180         .long   24                        /* frame size                           */
181         .quad   0                         /* method pointer (pointer to name)     */
182
183 asm_calljavafunction2:
184 asm_calljavafunction2int:
185 asm_calljavafunction2long:
186 asm_calljavafunction2float:
187 asm_calljavafunction2double:
188         sub     $(7*8),%rsp               /* keep stack 16-byte aligned           */
189         mov     %rbx,0*8(%rsp)            /* %rbx is not a callee saved in cacao  */
190         mov     %rbp,1*8(%rsp)
191         mov     %r12,2*8(%rsp)
192         mov     %r13,3*8(%rsp)
193         mov     %r14,4*8(%rsp)
194         mov     %r15,5*8(%rsp)
195
196         mov     %rdi,%rax                 /* move method pointer for compiler     */
197         xor     %rbp,%rbp                 /* set argument stack frame to zero     */
198
199         test    %rsi,%rsi                 /* maybe we have no args...             */
200         jle     L_copy_done
201
202         mov     %rsi,itmp3                /* arg count                            */
203         mov     %rcx,itmp2                /* pointer to arg block                 */
204
205         mov     itmp2,%r14                /* save argument block pointer          */
206         mov     itmp3,%r15                /* save argument count                  */
207
208         sub     $sizejniblock,itmp2       /* initialize pointer (smaller code)    */
209         add     $1,itmp3                  /* initialize argument count            */
210         xor     %r12,%r12                 /* initialize integer argument counter  */
211         xor     %r13,%r13                 /* initialize float argument counter    */
212
213 L_register_copy:
214         add     $sizejniblock,itmp2       /* goto next argument block             */
215         dec     itmp3                     /* argument count - 1                   */
216         jz      L_register_copy_done
217         andb    $0x02,offjniitemtype(itmp2) /* is this a float/double type?       */
218         jnz     L_register_handle_float   /* yes, handle it                       */
219
220         cmp     $INT_ARG_CNT,%r12         /* are we out of integer argument       */
221         je      L_register_copy           /* register? yes, next loop             */
222
223         lea     jumptable_integer,%rbp
224         mov     0(%rbp,%r12,8),%rbx
225         inc     %r12                      /* integer argument counter + 1         */
226         jmp     *%rbx
227
228 L_register_handle_float:
229         cmp     $FLT_ARG_CNT,%r13         /* are we out of float argument         */
230         je      L_register_copy           /* register? yes, next loop             */
231
232         lea     jumptable_float,%rbp
233         mov     0(%rbp,%r13,8),%rbx
234         inc     %r13                      /* float argument counter + 1           */
235         jmp     *%rbx
236         
237 L_register_copy_done:
238         mov     %r15,%rbp                 /* calculate remaining arguments        */
239         sub     %r12,%rbp                 /* - integer arguments in registers     */
240         sub     %r13,%rbp                 /* - float arguments in registers       */
241         jle     L_copy_done               /* are all assigned to registers?       */
242
243         and     $0xfffffffffffffffe,%rbp  /* keep stack 16-byte aligned           */
244         shl     $3,%rbp                   /* calculate stack size                 */
245         sub     %rbp,%rsp                 /* stack frame for arguments            */
246         mov     %rsp,%rbx                 /* use %rbx as temp sp                  */
247
248         sub     $sizejniblock,%r14        /* initialize pointer (smaller code)    */
249         add     $1,%r15                   /* initialize argument count            */
250                 
251 L_stack_copy_loop:
252         add     $sizejniblock,%r14        /* goto next argument block             */
253         dec     %r15                      /* are there any arguments left?        */
254         jz      L_copy_done               /* no test needed after dec             */
255
256         andb    $0x02,offjniitemtype(%r14) /* is this a float/double type?        */
257         jnz     L_stack_handle_float
258         dec     %r12                      /* arguments assigned to registers      */
259         jge     L_stack_copy_loop
260         jmp     L_stack_copy
261
262 L_stack_handle_float:
263         dec     %r13                      /* arguments assigned to registers      */
264         jge     L_stack_copy_loop
265
266 L_stack_copy:
267     mov     offjniitem(%r14),itmp3    /* copy s8 argument onto stack          */
268     mov     itmp3,0(%rbx)
269     add     $8,%rbx                   /* increase sp to next argument         */
270         jmp     L_stack_copy_loop
271
272 L_copy_done:
273         lea     asm_call_jit_compiler,%r11/* %rax still contains method pointer   */
274         call    *%r11                     /* call JIT compiler                    */
275
276         add     %rbp,%rsp                 /* remove argument stack frame if any   */
277
278         mov     5*8(%rsp),%r15            /* restore callee saved registers       */
279         mov     4*8(%rsp),%r14
280         mov     3*8(%rsp),%r13
281         mov     2*8(%rsp),%r12
282         mov     1*8(%rsp),%rbp
283         mov     0*8(%rsp),%rbx
284         add     $(7*8),%rsp               /* free stack space                     */
285         ret
286                 
287 calljava_xhandler2:
288         mov     %rax,%rdi                 /* pass exception pointer               */
289         call    builtin_throw_exception
290
291         mov     5*8(%rsp),%r15            /* restore callee saved registers       */
292         mov     4*8(%rsp),%r14
293         mov     3*8(%rsp),%r13
294         mov     2*8(%rsp),%r12
295         mov     1*8(%rsp),%rbp
296         mov     0*8(%rsp),%rbx
297         add     $(7*8),%rsp               /* free stack space                     */
298         xor     %rax,%rax                 /* return NULL                          */
299         ret
300
301
302 jumptable_integer:
303         .quad   handle_a0
304         .quad   handle_a1
305         .quad   handle_a2
306         .quad   handle_a3
307         .quad   handle_a4
308         .quad   handle_a5
309
310 handle_a0:
311         mov     offjniitem(itmp2),a0
312         jmp     L_register_copy
313 handle_a1:
314         mov     offjniitem(itmp2),a1
315         jmp     L_register_copy
316 handle_a2:
317         mov     offjniitem(itmp2),a2
318         jmp     L_register_copy
319 handle_a3:
320         mov     offjniitem(itmp2),a3
321         jmp     L_register_copy
322 handle_a4:
323         mov     offjniitem(itmp2),a4
324         jmp     L_register_copy
325 handle_a5:
326         mov     offjniitem(itmp2),a5
327         jmp     L_register_copy
328
329
330 jumptable_float:
331         .quad   handle_fa0
332         .quad   handle_fa1
333         .quad   handle_fa2
334         .quad   handle_fa3
335         .quad   handle_fa4
336         .quad   handle_fa5
337         .quad   handle_fa6
338         .quad   handle_fa7
339
340 handle_fa0:
341         movq    offjniitem(itmp2),fa0
342         jmp     L_register_copy
343 handle_fa1:
344         movq    offjniitem(itmp2),fa1
345         jmp     L_register_copy
346 handle_fa2:
347         movq    offjniitem(itmp2),fa2
348         jmp     L_register_copy
349 handle_fa3:
350         movq    offjniitem(itmp2),fa3
351         jmp     L_register_copy
352 handle_fa4:
353         movq    offjniitem(itmp2),fa4
354         jmp     L_register_copy
355 handle_fa5:
356         movq    offjniitem(itmp2),fa5
357         jmp     L_register_copy
358 handle_fa6:
359         movq    offjniitem(itmp2),fa6
360         jmp     L_register_copy
361 handle_fa7:
362         movq    offjniitem(itmp2),fa7
363         jmp     L_register_copy
364
365
366 /****************** function asm_call_jit_compiler *****************************
367 *                                                                              *
368 *   invokes the compiler for untranslated JavaVM methods.                      *
369 *                                                                              *
370 *   Register R0 contains a pointer to the method info structure (prepared      *
371 *   by createcompilerstub). Using the return address in R26 and the            *
372 *   offset in the LDA instruction or using the value in methodptr R28 the      *
373 *   patching address for storing the method address can be computed:           *
374 *                                                                              *
375 *   method address was either loaded using                                     *
376 *                                                                              *
377 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
378 *   i386_call_reg(REG_ITMP2)                                                   *
379 *                                                                              *
380 *   or                                                                         *
381 *                                                                              *
382 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
383 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
384 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
385 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
386 *   i386_call_reg(REG_ITMP1)                                                   *
387 *                                                                              *
388 *   in the static case the method pointer can be computed using the            *
389 *   return address and the lda function following the jmp instruction          *
390 *                                                                              *
391 *******************************************************************************/
392
393 asm_call_jit_compiler:
394         sub     $8,%rsp                 /* keep stack 16-byte aligned             */
395
396         mov     %rbx,(%rsp)             /* save register                          */
397         
398         mov     8(%rsp),%r11        /* get return address                         */
399         mov     -1(%r11),%bl        /* get function code                          */
400         cmp     $0xd2,%bl           /* called with `call *REG_ITMP2' (%r10)?      */
401         jne     L_not_static_special
402
403         sub     $11,%r11            /* calculate address of immediate             */
404         jmp     L_call_jit_compile
405                 
406 L_not_static_special:
407         cmp     $0xd0,%bl           /* called with `call *REG_ITMP1' (%rax)       */
408         jne     L_not_virtual_interface
409                 
410         sub     $7,%r11             /* calculate address of offset                */
411         mov     (%r11),%r11d        /* get offset (32-bit)                        */
412         add     %r10,%r11           /* add base address to get method address     */
413         jmp     L_call_jit_compile
414
415 L_not_virtual_interface:        /* a call from asm_calljavamethod             */
416         xor     %r11,%r11
417                 
418 L_call_jit_compile:
419         mov     (%rsp),%rbx         /* restore register                           */
420         
421         sub     $(24*8),%rsp        /* 8 + 6*8 + 8*8 + 8*8                        */
422         
423         mov     %r11,0*8(%rsp)      /* save address for method pointer            */
424
425         SAVE_ARGUMENT_REGISTERS(1)
426
427         mov     %rax,%rdi           /* pass method pointer                        */
428         call    jit_compile
429
430         mov     0*8(%rsp),%r11      /* restore address for method pointer         */
431
432         RESTORE_ARGUMENT_REGISTERS(1)
433
434         add     $(24*8),%rsp
435         add     $8,%rsp                 /* keep stack 16-byte aligned             */
436
437         test    %rax,%rax               /* check for exception                    */
438         je      L_asm_call_jit_compiler_exception
439
440         test    %r11,%r11               /* is address == 0 (asm_calljavamethod)   */
441         je      L_call_method
442
443         mov     %rax,(%r11)             /* and now save the new pointer           */
444
445 L_call_method:
446         jmp     *%rax                   /* ...and now call the new method         */
447
448 L_asm_call_jit_compiler_exception:
449 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
450         call    builtin_asm_get_exceptionptrptr
451         mov     %rax,itmp2
452 #else
453         lea     _exceptionptr,itmp2
454 #endif
455         mov     (itmp2),xptr                /* get the exception pointer          */
456         movl    $0,(itmp2)                  /* clear the exception pointer        */
457
458         pop     xpc                         /* delete return address              */
459         sub     $5,xpc                      /* faulting address is ra - 5         */
460
461         jmp     asm_handle_exception
462
463
464 /********************* function asm_handle_exception ***************************
465 *                                                                              *
466 *   This function handles an exception. It does not use the usual calling      *
467 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
468 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
469 *   the local exception table for a handler. If no one is found, it unwinds    *
470 *   stacks and continues searching the callers.                                *
471 *                                                                              *
472 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
473 *                                                                              *
474 *******************************************************************************/
475
476 asm_handle_nat_exception:
477         add     $8,%rsp                     /* clear return address of native stub*/
478                 
479 asm_handle_exception:
480         sub     $(4*8),%rsp
481         mov     xptr,0*8(%rsp)              /* save exception pointer             */
482         mov     xpc,1*8(%rsp)               /* save exception pc                  */
483         
484         mov     xpc,%rdi                    /* exception pc                       */
485         call    codegen_findmethod
486         mov     %rax,itmp3
487         mov     %rax,2*8(%rsp)              /* save data segment pointer          */
488         
489         mov     0*8(%rsp),%rax              /* restore exception pointer          */
490         mov     1*8(%rsp),%r10              /* restore exception pc               */
491         
492 ex_stack_loop:
493         mov     %rax,%rdi                   /* exception pointer                  */
494         mov     MethodPointer(itmp3),%rsi   /* method pointer                     */
495         mov     xpc,%rdx                    /* exception pc                       */
496         mov     $0,%rcx
497         mov     $1,%r8                      /* set noindent flag                  */
498         call    builtin_trace_exception
499
500         mov     2*8(%rsp),itmp3             /* %r11 = data segment pointer        */
501         mov     ExTableSize(itmp3),%rcx     /* %rcx = exception table size        */
502         test    %rcx,%rcx                                       /* if empty table skip                */
503         je      empty_table
504
505         lea     ExTableStart(itmp3),%rdi    /* %rdi = start of exception table    */
506         mov     0*8(%rsp),xptr              /* get xptr                           */
507                 
508 ex_table_loop:
509         mov     1*8(%rsp),xpc               /* get xpc                            */
510                 
511         mov     ExStartPC(%rdi),%rdx        /* %rdx = exception start pc          */
512         cmp     xpc,%rdx                    /* %rdx = (startpc <= xpc)            */
513         jg      ex_table_cont               /* if (false) continue                */
514         mov     ExEndPC(%rdi),%rdx          /* %rdx = exception end pc            */
515         cmp     %rdx,xpc                    /* %rdx = (xpc < endpc)               */
516         jge     ex_table_cont               /* if (false) continue                */
517         mov     ExCatchType(%rdi),%rdx      /* %rdx = exception catch type        */
518         test    %rdx,%rdx                   /* NULL catches everything            */
519         je      ex_handle_it
520
521         cmpl    $0,offclassloaded(%rdx)     /* check if class is loaded           */
522         jne     L_class_loaded
523
524         sub     $(4*8),%rsp
525         mov     %rax,0*8(%rsp)
526         mov     %rcx,1*8(%rsp)
527         mov     %rdx,2*8(%rsp)
528         mov     %rdi,3*8(%rsp)
529
530         mov     %rdx,%rdi
531         call    load_class_bootstrap
532
533         mov     0*8(%rsp),%rax
534         mov     1*8(%rsp),%rcx
535         mov     2*8(%rsp),%rdx
536         mov     3*8(%rsp),%rdi
537         add     $(4*8),%rsp
538
539 L_class_loaded:
540         cmpl    $0,offclasslinked(%rdx)     /* check if class is linked           */
541         jne     L_class_linked
542
543         sub     $(4*8),%rsp
544         mov     %rax,0*8(%rsp)
545         mov     %rcx,1*8(%rsp)
546         mov     %rdx,2*8(%rsp)
547         mov     %rdi,3*8(%rsp)
548
549         mov     %rdx,%rdi
550         call    link_class
551
552         mov     0*8(%rsp),%rax
553         mov     1*8(%rsp),%rcx
554         mov     2*8(%rsp),%rdx
555         mov     3*8(%rsp),%rdi
556         add     $(4*8),%rsp
557
558 L_class_linked:
559 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
560         push    %rdx
561
562 _crit_restart1:
563         mov     0(%rsp),%rdx
564 #endif
565
566 _crit_begin1:
567         mov     offobjvftbl(%rax),%rsi      /* %rsi = vftblptr(xptr)              */
568         mov     offclassvftbl(%rdx),%rdx    /* %rdx = vftblptr(catchtype) class (not obj) */
569         mov     offbaseval(%rsi),%esi       /* %esi = baseval(xptr)               */
570         mov     offbaseval(%rdx),%r10d      /* %r10d = baseval(catchtype)         */
571         mov     offdiffval(%rdx),%edx       /* %edx = diffval(catchtype)          */
572 _crit_end1:
573         sub     %r10d,%esi                  /* %esi = baseval(xptr) - baseval(catchtype) */
574
575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
576         add     $8,%rsp
577 #endif
578
579         cmp     %edx,%esi                   /* xptr is instanceof catchtype       */
580         ja      ex_table_cont
581                 
582 ex_handle_it:
583                 mov     ExHandlerPC(%rdi),xpc       /* xpc = exception handler pc     */
584
585         mov     0*8(%rsp),%rax              /* restore exception pointer      */
586         add     $(4*8),%rsp                 /* free stack frame               */
587
588         jmp             *xpc                        /* jump to the handler            */
589
590 ex_table_cont:
591         lea             ExEntrySize(%rdi),%rdi      /* next exception table entry     */
592         dec     %rcx                        /* decrement entry counter        */
593         test    %rcx,%rcx                   /* if (t0 > 0) next entry         */
594         jg              ex_table_loop
595                 
596 empty_table:
597         mov     0*8(%rsp),%rax              /* restore exception pointer      */
598         mov     1*8(%rsp),%r10              /* restore exception pc           */
599         mov     2*8(%rsp),%r11                          /* restore data segment pointer   */
600         add     $(4*8),%rsp
601         
602                 mov     %rax,%rcx                                       /* save exception pointer         */
603                                 
604 ex_already_cleared:             
605                 movl    IsSync(%r11),%eax                       /* %rax = SyncOffset              */
606                 test    %rax,%rax                                       /* if zero no monitorexit         */
607                 je              no_monitor_exit
608
609 #if defined(USE_THREADS)                
610                 add     %rsp,%rax
611                 mov     -8(%rax),%rdi
612
613         sub     $(4*8),%rsp
614         mov     %rcx,0*8(%rsp)
615         mov     %r10,1*8(%rsp)
616         mov     %r11,2*8(%rsp)
617         
618                 call    builtin_monitorexit
619
620         mov     0*8(%rsp),%rcx
621         mov     1*8(%rsp),%r10
622         mov     2*8(%rsp),%r11
623         add     $(4*8),%rsp
624 #endif
625
626 no_monitor_exit:
627                 mov             FrameSize(%r11),%eax        /* %eax = frame size              */
628                 add             %rax,%rsp                   /* unwind stack                   */
629                 mov             %rsp,%rax                   /* %rax = pointer to save area    */
630
631                 mov             IntSave(%r11),%edx          /* %edx = saved int register count*/
632         test    %edx,%edx
633         je              noint
634         
635                 cmp     $1,%edx
636                 je              int1
637                 cmp             $2,%edx
638                 je              int2
639                 cmp             $3,%edx
640                 je              int3
641                 cmp             $4,%edx
642                 je              int4
643                 cmp             $5,%edx
644                 je              int5
645         
646         mov     -48(%rax),%rbx
647 int5:   
648         mov     -40(%rax),%rbp
649 int4:   
650         mov     -32(%rax),%r12
651 int3:   
652         mov     -24(%rax),%r13
653 int2:   
654                 mov     -16(%rax),%r14
655 int1:   
656                 mov     -8(%rax),%r15
657
658                 shl             $3,%edx                     /* multiply by 8 bytes            */
659                 sub     %rdx,%rax
660                 
661 noint:
662                 mov     FltSave(%r11),%edx          /* %edx = saved flt register count*/
663                 test    %edx,%edx
664                 je      noflt
665
666         cmpl    $1,%edx
667         je      flt1
668         cmpl    $2,%edx
669         je      flt2
670         cmpl    $3,%edx
671         je      flt3
672         cmpl    $4,%edx
673         je      flt4
674         cmpl    $5,%edx
675         je      flt5
676         cmpl    $6,%edx
677         je      flt7
678         cmpl    $7,%edx
679         je      flt7
680
681         movq    -64(%rax),%xmm8
682 flt7:   
683         movq    -56(%rax),%xmm9
684 flt6:   
685         movq    -48(%rax),%xmm10
686 flt5:   
687         movq    -40(%rax),%xmm11
688 flt4:   
689         movq    -32(%rax),%xmm12
690 flt3:   
691         movq    -24(%rax),%xmm13
692 flt2:   
693         movq    -16(%rax),%xmm14
694 flt1:   
695         movq    -8(%rax),%xmm15
696                 
697 noflt:                                  
698                 pop     %r10                                            /* the new xpc is return address  */
699                 sub     $3,%r10                     /* subtract 3 bytes for call      */
700
701         sub     $(2*8),%rsp
702         mov     %rcx,0*8(%rsp)
703         mov     %r10,1*8(%rsp)
704
705         mov     %r10,%rdi
706         call    codegen_findmethod          /* get the new data segment ptr   */
707         mov     %rax,%r11
708         
709         mov     0*8(%rsp),%rcx
710         mov     1*8(%rsp),%r10
711         add     $(2*8),%rsp
712
713         mov     %rcx,%rax                                       /* restore saved exception pointer*/
714
715         sub     $(4*8),%rsp
716                                         
717         mov     %rax,0*8(%rsp)              /* save exception pointer         */
718         mov     %r10,1*8(%rsp)              /* save exception pc              */
719                 mov     %r11,2*8(%rsp)                          /* save data segment pointer      */
720                 
721                 jmp             ex_stack_loop
722
723
724 /* asm_wrapper_patcher *********************************************************
725
726    XXX
727
728    Stack layout:
729      32   return address
730          24   pointer to virtual java_objectheader
731      16   machine code (which is patched back later)
732       8   unresolved class/method/field reference
733       0   pointer to patcher function
734
735 *******************************************************************************/
736
737 asm_wrapper_patcher:
738         sub     $(17*8),%rsp                /* stack frame (16-byte aligned)      */
739
740         SAVE_ARGUMENT_REGISTERS(0)
741         SAVE_TEMPORARY_REGISTERS(14)
742
743         mov     itmp1,15*8(%rsp)            /* save itmp1 and itmp2               */
744         mov     itmp2,16*8(%rsp)            /* can be used by some instructions   */
745
746         mov     %rsp,a0                     /* pass stack pointer                 */
747         add     $(18*8),a0                  /* skip patcher function pointer      */
748         mov     17*8(%rsp),itmp3            /* get function pointer               */
749         call    *itmp3                      /* call the patcher function          */
750         mov     v0,itmp3                    /* save return value                  */
751
752         RESTORE_ARGUMENT_REGISTERS(0)
753         RESTORE_TEMPORARY_REGISTERS(14)
754
755         mov     15*8(%rsp),itmp1            /* restore itmp1 and itmp2            */
756         mov     16*8(%rsp),itmp2            /* can be used by some instructions   */
757
758         add     $((4+17)*8),%rsp            /* remove stack frame, keep ra        */
759
760         test    itmp3,itmp3                 /* exception thrown?                  */
761         jz      L_asm_wrapper_patcher_exception
762         ret                                 /* call new patched code              */
763
764 L_asm_wrapper_patcher_exception:
765         /*stack bottom is xpc and it is directly below the last java stackframe*/
766         push $0
767         push $0
768         push $0 /*padding*/
769         call asm_prepare_native_stackinfo /* be aware of the stack effect and calling convention explained above*/
770
771 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
772         call    builtin_asm_get_exceptionptrptr
773         mov     v0,itmp2
774 #else
775         lea     _exceptionptr,itmp2
776 #endif
777         mov     (itmp2),a0                  /* get the exception pointer          */
778         movl    $0,(itmp2)                  /* clear exception pointer            */
779         call    helper_fillin_stacktrace
780
781         mov     v0,xptr
782
783         call    asm_remove_native_stackinfo /* be aware of the stack effect and calling convention explained above*/
784         add     $8,%rsp
785
786         pop     xpc                         /* get and remove return address      */
787         jmp     asm_handle_exception
788
789
790 /* asm_builtin_x2x *************************************************************
791 *                                                                              *
792 *   Wrapper functions for float to int corner cases                            *
793 *                                                                              *
794 *******************************************************************************/
795
796 asm_builtin_f2i:
797         sub     $(14*8),%rsp
798         
799         SAVE_ARGUMENT_REGISTERS(0)
800         
801         movq    %xmm8,%xmm0
802         call    builtin_f2i
803         
804         RESTORE_ARGUMENT_REGISTERS(0)
805         
806         add     $(14*8),%rsp
807         ret
808
809
810 asm_builtin_f2l:
811         sub     $(14*8),%rsp
812         
813         SAVE_ARGUMENT_REGISTERS(0)
814         
815         movq    %xmm8,%xmm0
816         call    builtin_f2l
817         
818         RESTORE_ARGUMENT_REGISTERS(0)
819         
820         add     $(14*8),%rsp
821         ret
822
823
824 asm_builtin_d2i:
825         sub     $(14*8),%rsp
826         
827         SAVE_ARGUMENT_REGISTERS(0)
828         
829         movq    %xmm8,%xmm0
830         call    builtin_d2i
831         
832         RESTORE_ARGUMENT_REGISTERS(0)
833         
834         add     $(14*8),%rsp
835         ret
836
837
838 asm_builtin_d2l:
839         sub     $(14*8),%rsp
840         
841         SAVE_ARGUMENT_REGISTERS(0)
842         
843         movq    %xmm8,%xmm0
844         call    builtin_d2l
845         
846         RESTORE_ARGUMENT_REGISTERS(0)
847         
848         add     $(14*8),%rsp
849         ret
850
851
852 /* asm_builtin_arraycheckcast **************************************************
853
854    Does the cast check and eventually throws an exception.
855
856 *******************************************************************************/
857
858 asm_builtin_arraycheckcast:
859         sub     $24,%rsp                    /* keep stack 16-byte aligned         */
860         mov     %rdi,(%rsp)                 /* save object pointer                */
861         call    builtin_arraycheckcast
862         test    %rax,%rax                   /* if (false) throw exception         */
863         je      nb_carray_throw
864         mov     (%rsp),%rax                 /* return object pointer              */
865         add     $24,%rsp                    /* free stack space                   */
866         ret
867
868 nb_carray_throw:
869         /*call    new_classcastexception*/
870         add     $24,%rsp
871         pop     xpc                        /* delete return address              */
872         sub     $3,xpc                     /* faulting address is ra - 3         */
873         mov     string_java_lang_ClassCastException,xptr
874         jmp     asm_throw_and_handle_exception
875
876                 
877 /* asm_builtin_aastore *********************************************************
878
879    Checks if the object can be stored in the given array and stores the
880    address if it's possible. This function can also throw some exceptions.
881
882 *******************************************************************************/
883
884 asm_builtin_aastore:
885         sub     $(3*8),%rsp             /* allocate stack space                   */
886         test    %rdi,%rdi               /* if null pointer throw exception        */
887         je      nb_aastore_null
888
889         movl    offarraysize(%rdi),%eax /* load size                              */
890         cmpl    %eax,%esi               /* do bound check                         */
891         jae     nb_aastore_bound        /* if out of bounds throw exception       */
892
893         shl     $3,%rsi                 /* index * 8                              */
894         mov     %rdi,%r10
895         add     %rsi,%r10               /* add index * 8 to arrayref              */
896
897         mov     %r10,(%rsp)             /* save store position                    */
898         mov     %rdx,8(%rsp)            /* save object                            */
899
900         mov     %rdx,%rsi               /* object is second argument              */
901         call    builtin_canstore        /* builtin_canstore(arrayref,object)      */
902         test    %rax,%rax               /* if (false) throw exception             */
903         je      nb_aastore_throw
904
905         mov     (%rsp),%r10             /* restore store position                 */
906         mov     8(%rsp),%rdx            /* restore object                         */
907         mov     %rdx,offobjarrdata(%r10)/* store objectptr in array               */
908         add     $(3*8),%rsp             /* free stack space                       */
909         ret
910
911 nb_aastore_null:
912         add     $24,%rsp
913         pop     xpc                    /* delete return address from stack       */
914         sub     $3,xpc                 /* faulting address is return adress - 3  */
915         mov     string_java_lang_NullPointerException,xptr
916         jmp    asm_throw_and_handle_exception
917
918 nb_aastore_bound:
919         add     $24,%rsp
920         push    $0 /*directly below return address*/
921         push    $0 /*internal*/
922         push    $0 /*padding*/
923         mov     %rsi,itmp1
924         
925         call    asm_prepare_native_stackinfo
926
927         mov     itmp1,%rdi               /* move index into a0                     */
928         call    new_arrayindexoutofboundsexception
929
930         call    asm_remove_native_stackinfo
931
932         pop     xpc                    /* just remove one quadword                  */
933         pop     xpc                    /* delete return address                  */
934         sub     $3,xpc                 /* faulting address is return adress - 3  */
935         jmp     asm_handle_exception
936                 
937 nb_aastore_throw:
938         /*call    new_arraystoreexception*/
939         add     $24,%rsp
940         pop     xpc                    /* delete return address                  */
941         sub     $3,xpc                 /* faulting address is return adress - 3  */
942         mov     string_java_lang_ArrayStoreException,xptr
943         jmp     asm_throw_and_handle_exception
944
945                 
946 /******************* function asm_initialize_thread_stack **********************
947 *                                                                              *
948 * initialized a thread stack                                                   *
949 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
950 *                                                                              *
951 *******************************************************************************/
952
953 asm_initialize_thread_stack:
954         sub     $(7*8),%rsi
955
956         xor     %r10,%r10
957         mov     %r10,0*8(%rsi)
958         mov     %r10,1*8(%rsi)
959         mov     %r10,2*8(%rsi)
960         mov     %r10,3*8(%rsi)
961         mov     %r10,4*8(%rsi)
962         mov     %r10,5*8(%rsi)
963
964         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
965         mov     %rsi,%rax               /* return restorepoint in %rax        */
966         ret
967
968
969 /******************* function asm_perform_threadswitch *************************
970 *                                                                              *
971 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
972 *                                                                              *
973 *   performs a threadswitch                                                    *
974 *                                                                              *
975 *******************************************************************************/
976
977 asm_perform_threadswitch:
978         sub     $(7*8),%rsp             /* allocate stack frame               */
979
980         mov     %rbx,0*8(%rsp)
981         mov     %rbp,1*8(%rsp)
982         mov     %r12,2*8(%rsp)
983         mov     %r13,3*8(%rsp)
984         mov     %r14,4*8(%rsp)
985         mov     %r15,5*8(%rsp)
986
987         mov     7*8(%rsp),%rax                  /* save current return address        */
988         mov     %rax,6*8(%rsp)
989
990         mov     %rsp,(%rdi)                     /* first argument **from              */
991         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
992
993         mov     (%rsi),%rsp                     /* load new stack pointer             */
994
995         mov     0*8(%rsp),%rbx
996         mov     1*8(%rsp),%rbp
997         mov     2*8(%rsp),%r12
998         mov     3*8(%rsp),%r13
999         mov     4*8(%rsp),%r14
1000         mov     5*8(%rsp),%r15
1001
1002         mov     6*8(%rsp),%rax          /* restore return address             */
1003         add     $(7*8),%rsp             /* free stack frame                   */
1004         mov     %rax,(%rsp)
1005         ret
1006                 
1007
1008 /********************* function asm_switchstackandcall *************************
1009 *                                                                              *
1010 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
1011 *                                      void *p);                                       *
1012 *                                                                              *
1013 *   Switches to a new stack, calls a function and switches back.               *
1014 *       a0 (%rdi)     new stack pointer                                        *
1015 *       a1 (%rsi)     function pointer                                         *
1016 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
1017 *       a3 (%rcx)     pointer to user data, is passed to the function          *
1018 *                                                                              *
1019 *******************************************************************************/
1020
1021 asm_switchstackandcall:
1022         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
1023         sub     $16,%rdi                                /* allocate new stack                 */
1024
1025         mov     8(%rsp),%rax                    /* save return address on new stack   */
1026         mov     %rax,(%rdi)
1027         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
1028         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
1029
1030         mov     %rdi,%rsp                               /* switch to new stack                */
1031
1032         mov     %rcx,%rdi                       /* pass pointer                       */
1033         call    *%rsi                                   /* and call function                  */
1034
1035         mov     (%rsp),%r10                             /* load return address                */
1036         mov     8(%rsp),%rsp                    /* switch to old stack                */
1037         add     $(1*8),%rsp             /* free stack space                   */
1038         mov     %r10,(%rsp)             /* write return adress                */
1039         ret
1040
1041
1042
1043
1044 /************************ function asm_prepare_native_stackinfo ****************************
1045 *                                                                                          *
1046 *    creates a stackfame for the begin of a native function (either builtin or not )       *
1047 *    expected stack at begin of function                                                   *
1048 *                                        ....                                              *
1049 *                   address of the jit call which invokes the native                       *
1050 *                   begin address of stack frame of the java method                        *
1051 *                   method pointer or 0 (for built ins)                                    *
1052 *                   padding for stackframesize 16*n+8                                      *
1053 *                   return address                                                         *
1054 *                                                                                          *
1055 *    at end of function:                                                                   *
1056 *                                          ...                                             *
1057 *                   address of the jit call which invokes the native                       *
1058 *                   begin address of stack frame of the java method                        *
1059 *                   method pointer or 0 (for built ins)                                    *
1060 *                   address of thread specific top of native list                          *
1061 *                   old value of thread specific head                                      *
1062 *                   padding for stackframesize 16*n+8)                                     *
1063 *                   return address                                                         *
1064 *                                                                                          *
1065 *                                        ....                                              *
1066 * This thing is less efficient than the original #define (callerside)                      *
1067 * destroyes REG_ITMP2, keeps REG_ITMP1                                                     *
1068 ********************************************************************************************/
1069
1070
1071 asm_prepare_native_stackinfo:
1072         sub $16,%rsp  /*space for the 2 new pointers*/
1073         mov 16(%rsp),itmp2
1074         mov itmp2,(%rsp)
1075         push itmp1
1076         call builtin_asm_get_stackframeinfo
1077
1078         mov itmp1, 32(%rsp)
1079         mov (itmp1),itmp2
1080         mov itmp2,24(%rsp)
1081         mov %rsp,itmp2
1082         add $24,itmp2
1083         mov itmp2,(itmp1)
1084         pop itmp1
1085         ret
1086
1087                 
1088
1089 /************************ function asm_remove _native_stackinfo *******************************************
1090 *                                                                                                         *
1091 *    removes a stackfame for the begin of a native function (either builtin or not)                       *
1092 *    expected stack at begin of function                                                                  *
1093 *                   address of the jit call which invokes the native                                      *
1094 *                   begin address of stack frame of the java method                                       *
1095 *                   method pointer or 0 (for built ins)                                                   *
1096 *                   address thread specific top of native list                                            *
1097 *                   old value of thread specific head                                                     *
1098 *                   padding                                                                               *
1099 *                   return address                                                                        *
1100 *                                                                                                         *
1101 *    at end of function:                                                                                  *
1102 *                             ....                                                                        *
1103 *                   return adresss of the jit call which invokes the native                               *
1104 *                   padding                                                                               *
1105 *                   return address                                                                        *
1106 *                                                                                                         *
1107 *                                                                                                         *
1108 *                                                                                                         *
1109 * This thing is less efficient than the original #define (callerside), uses ITMP2,uses ITMP3,keeps ITMP1  *
1110 ***********************************************************************************************************/
1111
1112 asm_remove_native_stackinfo:
1113         mov 16(%rsp),itmp2
1114         mov 24(%rsp),itmp3
1115         mov itmp2,(itmp3)
1116         pop itmp3
1117         add $32,%rsp
1118         push itmp3
1119         ret
1120
1121
1122
1123 asm_throw_and_handle_exception:
1124         push xpc /* the pushed XPC is directly below the java frame*/
1125         push $0 
1126         push $0
1127         push $0 /*padding*/
1128         call asm_prepare_native_stackinfo /* be aware of the stack effect and calling convention explained above*/
1129         mov itmp1,%rdi
1130
1131         call new_exception
1132
1133         call asm_remove_native_stackinfo /* be aware of the stack effect and calling convention explained above*/
1134
1135         pop xpc
1136         pop xpc
1137
1138         jmp asm_handle_exception
1139         ret /*should never be reached */
1140
1141
1142 asm_throw_and_handle_hardware_arithmetic_exception:
1143
1144         push xpc
1145         push $0 /* the pushed XPC is directly below the java frame*/
1146         push $0
1147         push $0 /*padding*/
1148         call asm_prepare_native_stackinfo /* be aware of the stack effect and calling convention explained above*/
1149
1150         mov string_java_lang_ArithmeticException_message,%rsi
1151         mov string_java_lang_ArithmeticException,%rdi
1152
1153         call new_exception_message
1154
1155         call asm_remove_native_stackinfo /* be aware of the stack effect and calling convention explained above*/
1156         pop xpc
1157         pop xpc
1158
1159         jmp asm_handle_exception
1160         ret /*should never be reached */
1161
1162
1163 asm_getclassvalues_atomic:
1164 _crit_restart2:
1165 _crit_begin2:
1166         movl    offbaseval(a0),itmp1l
1167         movl    offdiffval(a0),itmp2l
1168         movl    offbaseval(a1),itmp3l
1169 _crit_end2:
1170         movl    itmp1l,offcast_super_baseval(a2)
1171         movl    itmp2l,offcast_super_diffval(a2)
1172         movl    itmp3l,offcast_sub_baseval(a2)
1173         ret
1174
1175         .data
1176                 
1177 asm_criticalsections:
1178 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1179         .quad   _crit_begin1
1180         .quad   _crit_end1
1181         .quad   _crit_restart1
1182         .quad   _crit_begin2
1183         .quad   _crit_end2
1184         .quad   _crit_restart2
1185 #endif
1186         .quad 0
1187
1188                 
1189 /*
1190  * These are local overrides for various environment variables in Emacs.
1191  * Please do not remove this and leave it at the end of the file, where
1192  * Emacs will automagically detect them.
1193  * ---------------------------------------------------------------------
1194  * Local variables:
1195  * mode: asm
1196  * indent-tabs-mode: t
1197  * c-basic-offset: 4
1198  * tab-width: 4
1199  * End:
1200  */