- removed builtin trace functions
[cacao.git] / src / vm / jit / x86_64 / asmpart.S
1 /* jit/x86_64/asmpart.S - Java-C interface functions for x86_64
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6    S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
7    J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29             Reinhard Grafl
30             Christian Thalinger
31
32    $Id: asmpart.S 926 2004-02-26 00:16:50Z twisti $
33
34 */
35
36
37 #include "offsets.h"
38
39         .text
40
41
42 /********************* exported functions and variables ***********************/
43
44         .globl asm_calljavafunction
45         .globl asm_calljavafunction2
46         .globl asm_calljavafunction2long
47         .globl asm_calljavafunction2double
48         .globl asm_call_jit_compiler
49         .globl asm_dumpregistersandcall
50         .globl asm_handle_exception
51         .globl asm_handle_nat_exception
52         .globl asm_check_clinit
53         .globl asm_builtin_checkcast    
54         .globl asm_builtin_checkarraycast
55         .globl asm_builtin_anewarray
56         .globl asm_builtin_newarray_array
57         .globl asm_builtin_aastore
58         .globl asm_builtin_monitorenter
59         .globl asm_builtin_monitorexit
60     .globl asm_builtin_f2i
61     .globl asm_builtin_f2l
62     .globl asm_builtin_d2i
63     .globl asm_builtin_d2l
64         .globl asm_builtin_arrayinstanceof
65         .globl asm_perform_threadswitch
66         .globl asm_initialize_thread_stack
67         .globl asm_switchstackandcall
68         .globl asm_getcallingmethod
69     .globl asm_builtin_trace
70     .globl asm_builtin_exittrace
71     
72 /*************************** imported functions *******************************/
73
74         .globl jit_compile
75         .globl builtin_monitorexit
76         .globl builtin_throw_exception
77         .globl builtin_trace_exception
78         .globl findmethod
79
80         
81
82 #define         MethodPointer   -8
83 #define         FrameSize       -12
84 #define     IsSync          -16
85 #define     IsLeaf          -20
86 #define     IntSave         -24
87 #define     FltSave         -28
88 #define     ExTableSize     -32
89 #define     ExTableStart    -32
90
91 #define     ExEntrySize     -32
92 #define     ExStartPC       -8
93 #define     ExEndPC         -16
94 #define     ExHandlerPC     -24
95 #define     ExCatchType     -32
96
97
98 /********************* function asm_calljavafunction ***************************
99 *                                                                              *
100 *   This function calls a Java-method (which possibly needs compilation)       *
101 *   with up to 4 address parameters.                                           *
102 *                                                                              *
103 *   This functions calls the JIT-compiler which eventually translates the      *
104 *   method into machine code.                                                  *
105 *                                                                              *
106 *   C-prototype:                                                               *
107 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
108 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
109 *                                                                              *
110 *******************************************************************************/
111
112 call_name:
113         .ascii  "calljavafunction\0\0"
114
115         .align  8
116         .quad   0                         /* catch type all                       */
117         .quad   calljava_xhandler         /* handler pc                           */
118         .quad   calljava_xhandler         /* end pc                               */
119         .quad   asm_calljavafunction      /* start pc                             */
120         .long   1                         /* extable size                         */
121         .long   0                         /* fltsave                              */
122         .long   0                         /* intsave                              */
123         .long   0                         /* isleaf                               */
124         .long   0                         /* IsSync                               */
125         .long   8                         /* frame size                           */
126         .quad   0                         /* method pointer (pointer to name)     */
127
128 asm_calljavafunction:
129         sub     $(3*8),%rsp           /* keep stack 16-byte aligned           */
130         mov     %rbp,0*8(%rsp)
131         mov     %rbx,1*8(%rsp)        /* %rbx is not a callee saved in cacao  */
132         mov     %rdi,%rax             /* move function pointer to %rax        */
133                                       /* compilerstub uses this               */
134
135         mov     %rsi,%rdi             /* pass remaining parameters            */
136         mov     %rdx,%rsi
137         mov     %rcx,%rdx
138         mov     %r8,%rcx
139         
140         lea     asm_call_jit_compiler,%r11
141         call    *%r11                 /* call JIT compiler                    */
142         
143 calljava_jit:
144 calljava_return:
145 calljava_ret:
146         mov     0*8(%rsp),%rbp
147                 mov             1*8(%rsp),%rbx
148         add     $(3*8),%rsp           /* free stack space                     */
149         ret
150
151 calljava_xhandler:
152         mov     %rax,%rdi                 /* pass exception pointer               */
153         call    builtin_throw_exception
154         mov     0*8(%rsp),%rbp
155                 mov             1*8(%rsp),%rbx
156         add     $(3*8),%rsp
157         ret
158                                                 
159
160 /********************* function asm_calljavafunction ***************************
161 *                                                                              *
162 *   This function calls a Java-method (which possibly needs compilation)       *
163 *   with up to 4 address parameters.                                           *
164 *                                                                              *
165 *   This functions calls the JIT-compiler which eventually translates the      *
166 *   method into machine code.                                                  *
167 *                                                                              *
168 *   C-prototype:                                                               *
169 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
170 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
171 *                                                                              *
172 *******************************************************************************/
173
174 call_name2:
175         .ascii  "calljavafunction2\0\0"
176
177         .align  8
178         .quad   0                         /* catch type all                       */
179         .quad   calljava_xhandler2        /* handler pc                           */
180         .quad   calljava_xhandler2        /* end pc                               */
181         .quad   asm_calljavafunction2     /* start pc                             */
182         .long   1                         /* extable size                         */
183         .long   0                         /* fltsave                              */
184         .long   0                         /* intsave                              */
185         .long   0                         /* isleaf                               */
186         .long   0                         /* IsSync                               */
187         .long   8                         /* frame size                           */
188         .quad   0                         /* method pointer (pointer to name)     */
189
190 asm_calljavafunction2:
191 asm_calljavafunction2double:
192 asm_calljavafunction2long:
193         sub     $8,%rsp               /* keep stack 16-byte aligned           */
194
195         mov     %rdi,%rax             /* save method pointer for compiler     */
196         mov     %rcx,%r10             /* pointer to arg block                 */
197         
198         mov     offjniitem(%r10),%rdi /* move args into registers             */
199         mov     offjniitem + sizejniblock * 1(%r10),%rsi
200         mov     offjniitem + sizejniblock * 2(%r10),%rdx
201         mov     offjniitem + sizejniblock * 3(%r10),%rcx
202         
203         lea     asm_call_jit_compiler,%r11
204         call    *%r11                 /* call JIT compiler                    */
205         
206 calljava_jit2:
207 calljava_return2:
208 calljava_ret2:
209         add     $8,%rsp               /* free stack space                     */
210         ret
211
212 calljava_xhandler2:
213         mov     %rax,%rdi                 /* pass exception pointer               */
214         call    builtin_throw_exception
215         add     $8,%rsp
216         ret
217                                                 
218
219 /****************** function asm_call_jit_compiler *****************************
220 *                                                                              *
221 *   invokes the compiler for untranslated JavaVM methods.                      *
222 *                                                                              *
223 *   Register R0 contains a pointer to the method info structure (prepared      *
224 *   by createcompilerstub). Using the return address in R26 and the            *
225 *   offset in the LDA instruction or using the value in methodptr R28 the      *
226 *   patching address for storing the method address can be computed:           *
227 *                                                                              *
228 *   method address was either loaded using                                     *
229 *                                                                              *
230 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
231 *   i386_call_reg(REG_ITMP2)                                                   *
232 *                                                                              *
233 *   or                                                                         *
234 *                                                                              *
235 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
236 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
237 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
238 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
239 *   i386_call_reg(REG_ITMP1)                                                   *
240 *                                                                              *
241 *   in the static case the method pointer can be computed using the            *
242 *   return address and the lda function following the jmp instruction          *
243 *                                                                              *
244 *******************************************************************************/
245
246 asm_call_jit_compiler:
247         sub     $8,%rsp         /* keep stack 16-byte aligned                 */
248
249         mov     %rbx,(%rsp)     /* save register                              */
250         
251         mov     8(%rsp),%r11    /* get return address                         */
252         mov     -1(%r11),%bl    /* get function code                          */
253         cmp     $0xd2,%bl               /* called with `call *REG_ITMP2' (%r10)?      */
254         jne     L_not_static_special
255
256         sub     $11,%r11        /* calculate address of immediate             */
257         jmp             L_call_jit_compile
258                 
259 L_not_static_special:
260                 cmp     $0xd0,%bl               /* called with `call *REG_ITMP1' (%rax)       */
261                 jne     L_not_virtual_interface
262                 
263                 sub     $7,%r11         /* calculate address of offset                */
264                 mov     (%r11),%r11d    /* get offset (32-bit)                        */
265                 add     %r10,%r11       /* add base address to get method address     */
266                 jmp     L_call_jit_compile
267
268 L_not_virtual_interface:        /* a call from asm_calljavamethod             */
269                 xor     %r11,%r11
270                 
271 L_call_jit_compile:
272         mov     (%rsp),%rbx     /* restore register                           */
273         
274         sub     $(24*8),%rsp    /* 8 + 48 + 64 + 64                           */
275         
276                 mov     %r11,0*8(%rsp)  /* save address for method pointer            */
277
278         mov     %rdi,1*8(%rsp)  /* save arguments                             */
279         mov     %rsi,2*8(%rsp)
280         mov     %rdx,3*8(%rsp)
281         mov     %rcx,4*8(%rsp)
282         mov     %r8,5*8(%rsp)
283         mov     %r9,6*8(%rsp)
284
285         movq    %xmm0,7*8(%rsp)
286         movq    %xmm1,8*8(%rsp)
287         movq    %xmm2,9*8(%rsp)
288         movq    %xmm3,10*8(%rsp)
289         movq    %xmm4,11*8(%rsp)
290         movq    %xmm5,12*8(%rsp)
291         movq    %xmm6,13*8(%rsp)
292         movq    %xmm7,14*8(%rsp)
293
294         movq    %xmm8,15*8(%rsp)/* we use them as callee saved registers      */
295         movq    %xmm9,16*8(%rsp)
296         movq    %xmm10,17*8(%rsp)
297         movq    %xmm11,18*8(%rsp)
298         movq    %xmm12,19*8(%rsp)
299         movq    %xmm13,20*8(%rsp)
300         movq    %xmm14,21*8(%rsp)
301         movq    %xmm15,22*8(%rsp)
302
303         mov     %rax,%rdi       /* pass method pointer                        */
304                 call    jit_compile
305
306         mov     0*8(%rsp),%r11
307         
308         mov     1*8(%rsp),%rdi
309         mov     2*8(%rsp),%rsi
310         mov     3*8(%rsp),%rdx
311         mov     4*8(%rsp),%rcx
312         mov     5*8(%rsp),%r8
313         mov     6*8(%rsp),%r9
314
315         movq    7*8(%rsp),%xmm0
316         movq    8*8(%rsp),%xmm1
317         movq    9*8(%rsp),%xmm2
318         movq    10*8(%rsp),%xmm3
319         movq    11*8(%rsp),%xmm4
320         movq    12*8(%rsp),%xmm5
321         movq    13*8(%rsp),%xmm6
322         movq    14*8(%rsp),%xmm7
323
324         movq    15*8(%rsp),%xmm8
325         movq    16*8(%rsp),%xmm9
326         movq    17*8(%rsp),%xmm10
327         movq    18*8(%rsp),%xmm11
328         movq    19*8(%rsp),%xmm12
329         movq    20*8(%rsp),%xmm13
330         movq    21*8(%rsp),%xmm14
331         movq    22*8(%rsp),%xmm15
332
333         add     $(24*8),%rsp
334
335                 test    %r11,%r11               /* is address == 0 (asm_calljavamethod)       */
336                 je              L_call_method
337                 
338                 mov     %rax,(%r11)             /* and now save the new pointer               */
339
340 L_call_method:
341         add     $8,%rsp         /* keep stack 16-byte aligned                 */
342                 jmp             *%rax                   /* ...and now call the new method             */
343
344
345
346 /****************** function asm_dumpregistersandcall **************************
347 *                                                                              *
348 *   This funtion saves all callee saved registers and calls the function       *
349 *   which is passed as parameter.                                              *
350 *                                                                              *
351 *   This function is needed by the garbage collector, which needs to access    *
352 *   all registers which are stored on the stack. Unused registers are          *
353 *   cleared to avoid interferances with the GC.                                *
354 *                                                                              *
355 *   void asm_dumpregistersandcall (functionptr f);                             *
356 *                                                                              *
357 *******************************************************************************/
358
359 asm_dumpregistersandcall:
360         sub     $(7*8),%rsp             /* allocate stack space               */
361
362         mov     %rbx,0*8(%rsp)          /* save all callee saved registers    */
363         mov     %rsp,1*8(%rsp)
364         mov     %rbp,2*8(%rsp)
365         mov     %r12,3*8(%rsp)
366         mov     %r13,4*8(%rsp)
367         mov     %r14,5*8(%rsp)
368         mov     %r15,6*8(%rsp)
369
370         xor     %rax,%rax               /* intialize the remaining registers  */
371         xor     %rcx,%rcx
372         xor     %rdx,%rdx
373         xor     %rsi,%rsi
374         xor     %r8,%r8
375         xor     %r9,%r9
376         xor     %r10,%r10
377         xor     %r11,%r11
378         
379         call    *%rdi                   /* call function                      */
380
381         mov     0*8(%rsp),%rbx
382         mov     1*8(%rsp),%rsp
383         mov     2*8(%rsp),%rbp
384         mov     3*8(%rsp),%r12
385         mov     4*8(%rsp),%r13
386         mov     5*8(%rsp),%r14
387         mov     6*8(%rsp),%r15
388
389         add     $(7*8),%rsp        
390         ret
391
392
393 /********************* function asm_handle_exception ***************************
394 *                                                                              *
395 *   This function handles an exception. It does not use the usual calling      *
396 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
397 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
398 *   the local exception table for a handler. If no one is found, it unwinds    *
399 *   stacks and continues searching the callers.                                *
400 *                                                                              *
401 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
402 *                                                                              *
403 *******************************************************************************/
404
405 asm_handle_nat_exception:
406         add     $8,%rsp                                         /* clear return address of native stub */
407                 
408 asm_handle_exception:
409         sub     $(4*8),%rsp
410         mov     %rax,0*8(%rsp)              /* save exception pointer         */
411         mov     %r10,1*8(%rsp)              /* save exception pc              */
412         
413         mov     %r10,%rdi                   /* exception pc                   */
414         call    findmethod
415         mov     %rax,%r11
416         mov     %rax,2*8(%rsp)                          /* save data segment pointer      */
417         
418         mov     0*8(%rsp),%rax              /* restore exception pointer      */
419         mov     1*8(%rsp),%r10              /* restore exception pc           */
420         
421 ex_stack_loop:
422         mov     %rax,%rdi                                       /* exception pointer              */
423         mov     MethodPointer(%r11),%rsi        /* method pointer                 */
424         mov     %r10,%rdx                   /* exception pc                   */
425         mov     $1,%rcx                                         /* set noindent flag              */
426         call    builtin_trace_exception
427
428                 mov     2*8(%rsp),%r11                          /* %r11 = data segment pointer    */
429                 mov     ExTableSize(%r11),%rcx          /* %rcx = exception table size    */
430                 test    %rcx,%rcx                                       /* if empty table skip            */
431                 je              empty_table
432
433                 lea             ExTableStart(%r11),%rdi         /* %rdi = start of exception table*/
434                 mov     0*8(%rsp),%rax                          /* get xptr                       */
435                 
436 ex_table_loop:
437                 mov     1*8(%rsp),%r10              /* get xpc                        */
438                 
439                 mov     ExStartPC(%rdi),%rdx        /* %rdx = exception start pc      */
440                 cmp     %r10,%rdx                   /* %rdx = (startpc <= xpc)        */
441                 jg              ex_table_cont               /* if (false) continue            */
442                 mov     ExEndPC(%rdi),%rdx          /* %rdx = exception end pc        */
443                 cmp     %rdx,%r10                   /* %rdx = (xpc < endpc)           */
444                 jge             ex_table_cont               /* if (false) continue            */
445                 mov     ExCatchType(%rdi),%rdx      /* %rdx = exception catch type    */
446                 test    %rdx,%rdx                   /* NULL catches everything        */
447                 je              ex_handle_it
448
449                 mov     offobjvftbl(%rax),%rsi      /* %rsi = vftblptr(xptr)          */
450                 mov     offclassvftbl(%rdx),%rdx    /* %rdx = vftblptr(catchtype) class (not obj) */
451                 mov     offbaseval(%rsi),%esi       /* %esi = baseval(xptr)           */
452                 mov     offbaseval(%rdx),%r10d      /* %r10d = baseval(catchtype)     */
453                 mov     offdiffval(%rdx),%edx       /* %edx = diffval(catchtype)      */
454                 sub     %r10d,%esi                  /* %esi = baseval(xptr) - baseval(catchtype) */
455                 cmp     %edx,%esi                   /* xptr is instanceof catchtype   */
456                 ja              ex_table_cont
457                 
458 ex_handle_it:
459                 mov     ExHandlerPC(%rdi),%r10      /* xpc = exception handler pc     */
460
461         mov     0*8(%rsp),%rax              /* restore exception pointer      */
462         add     $(4*8),%rsp                 /* free stack frame               */
463
464         jmp             *%r10                       /* jump to the handler            */
465
466 ex_table_cont:
467         lea             ExEntrySize(%rdi),%rdi      /* next exception table entry     */
468         dec     %rcx                        /* decrement entry counter        */
469         test    %rcx,%rcx                   /* if (t0 > 0) next entry         */
470         jg              ex_table_loop
471                 
472 empty_table:
473         mov     0*8(%rsp),%rax              /* restore exception pointer      */
474         mov     1*8(%rsp),%r10              /* restore exception pc           */
475         mov     2*8(%rsp),%r11                          /* restore data segment pointer   */
476         add     $(4*8),%rsp
477         
478                 mov     %rax,%rcx                                       /* save exception pointer         */
479                                 
480 ex_already_cleared:             
481                 movl    IsSync(%r11),%eax                       /* %rax = SyncOffset              */
482                 test    %rax,%rax                                       /* if zero no monitorexit         */
483                 je              no_monitor_exit
484                 
485                 add     %rsp,%rax
486                 mov     -8(%rax),%rdi
487
488         sub     $(4*8),%rsp
489         mov     %rcx,0*8(%rsp)
490         mov     %r10,1*8(%rsp)
491         mov     %r11,2*8(%rsp)
492         
493                 call    builtin_monitorexit
494
495         mov     0*8(%rsp),%rcx
496         mov     1*8(%rsp),%r10
497         mov     2*8(%rsp),%r11
498         add     $(4*8),%rsp
499                 
500 no_monitor_exit:
501                 mov             FrameSize(%r11),%eax        /* %eax = frame size              */
502                 add             %rax,%rsp                   /* unwind stack                   */
503                 mov             %rsp,%rax                   /* %rax = pointer to save area    */
504
505                 mov             IntSave(%r11),%edx          /* %edx = saved int register count*/
506         test    %edx,%edx
507         je              noint
508         
509                 cmp     $1,%edx
510                 je              int1
511                 cmp             $2,%edx
512                 je              int2
513                 cmp             $3,%edx
514                 je              int3
515                 cmp             $4,%edx
516                 je              int4
517                 cmp             $5,%edx
518                 je              int5
519         
520         mov     -48(%rax),%rbx
521 int5:   
522         mov     -40(%rax),%rbp
523 int4:   
524         mov     -32(%rax),%r12
525 int3:   
526         mov     -24(%rax),%r13
527 int2:   
528                 mov     -16(%rax),%r14
529 int1:   
530                 mov     -8(%rax),%r15
531
532                 shl             $3,%edx                     /* multiply by 8 bytes            */
533                 sub     %rdx,%rax
534                 
535 noint:
536                 mov     FltSave(%r11),%edx          /* %edx = saved flt register count*/
537                 test    %edx,%edx
538                 je      noflt
539
540         cmpl    $1,%edx
541         je      flt1
542         cmpl    $2,%edx
543         je      flt2
544         cmpl    $3,%edx
545         je      flt3
546         cmpl    $4,%edx
547         je      flt4
548         cmpl    $5,%edx
549         je      flt5
550         cmpl    $6,%edx
551         je      flt7
552         cmpl    $7,%edx
553         je      flt7
554
555         movq    -64(%rax),%xmm8
556 flt7:   
557         movq    -56(%rax),%xmm9
558 flt6:   
559         movq    -48(%rax),%xmm10
560 flt5:   
561         movq    -40(%rax),%xmm11
562 flt4:   
563         movq    -32(%rax),%xmm12
564 flt3:   
565         movq    -24(%rax),%xmm13
566 flt2:   
567         movq    -16(%rax),%xmm14
568 flt1:   
569         movq    -8(%rax),%xmm15
570                 
571 noflt:                                  
572                 pop     %r10                                            /* the new xpc is return address  */
573                 sub     $3,%r10                     /* subtract 3 bytes for call      */
574
575         sub     $(2*8),%rsp
576         mov     %rcx,0*8(%rsp)
577         mov     %r10,1*8(%rsp)
578
579         mov     %r10,%rdi
580         call    findmethod                              /* get the new data segment ptr   */
581         mov     %rax,%r11
582         
583         mov     0*8(%rsp),%rcx
584         mov     1*8(%rsp),%r10
585         add     $(2*8),%rsp
586
587         mov     %rcx,%rax                                       /* restore saved exception pointer*/
588
589         sub     $(4*8),%rsp
590                                         
591         mov     %rax,0*8(%rsp)              /* save exception pointer         */
592         mov     %r10,1*8(%rsp)              /* save exception pc              */
593                 mov     %r11,2*8(%rsp)                          /* save data segment pointer      */
594                 
595                 jmp             ex_stack_loop
596
597
598 /********************* function asm_check_clinit *******************************
599 *                                                                              *
600 *   Does null check and calls monitorenter or throws an exception              *
601 *                                                                              *
602 *******************************************************************************/
603
604 asm_check_clinit:
605                 mov             offclassinit(%rax),%r10d    /* get initialized flag (int)     */
606                 test    %r10,%r10
607                 jnz             L_is_initialized
608
609                 sub             $(7*8),%rsp                 /* keep stack 16-byte aligned     */
610                 mov             %rdi,0*8(%rsp)              /* save argument registers        */
611                 mov             %rsi,1*8(%rsp)
612                 mov             %rdx,2*8(%rsp)
613                 mov             %rcx,3*8(%rsp)
614                 mov             %r8,4*8(%rsp)
615                 mov             %r9,5*8(%rsp)
616                 
617                 mov             %rax,%rdi                   /* pass classinfo pointer         */
618                 call    class_init                  /* call class_init function       */
619                 
620         mov     0*8(%rsp),%rdi              /* restore argument registers     */
621         mov     1*8(%rsp),%rsi
622         mov     2*8(%rsp),%rdx
623         mov     3*8(%rsp),%rcx
624         mov     4*8(%rsp),%r8
625         mov     5*8(%rsp),%r9
626                 add             $(7*8),%rsp
627                                 
628 L_is_initialized:
629                 mov     (%rsp),%rax                 /* get return address             */
630                 sub     $23,%rax                    /* asm_putstatic call code size   */
631                 movb    $0xeb,(%rax)                /* jmp rel8                       */
632                 movb    $21,1(%rax)                 /* 8-bit offset                   */
633                 ret
634
635
636 /********************* function asm_builtin_monitorenter ***********************
637 *                                                                              *
638 *   Does null check and calls monitorenter or throws an exception              *
639 *                                                                              *
640 *******************************************************************************/
641
642 asm_builtin_monitorenter:
643         test    %rdi,%rdi
644         je      nb_monitorenter                 /* if (null) throw exception          */
645         jmp     builtin_monitorenter    /* else call builtin_monitorenter     */
646
647 nb_monitorenter:
648         pop     %r10                                    /* delete return address */
649         sub     $3,%r10                                 /* faulting address is return adress - 3 */
650         mov     proto_java_lang_NullPointerException,%rax
651         jmp     asm_handle_exception
652                 
653
654 /********************* function asm_builtin_monitorexit ************************
655 *                                                                              *
656 *   Does null check and calls monitorexit or throws an exception               *
657 *                                                                              *
658 *******************************************************************************/
659
660 asm_builtin_monitorexit:
661         test    %rdi,%rdi
662         je      nb_monitorexit                  /* if (null) throw exception          */
663         jmp     builtin_monitorexit             /* else call builtin_monitorenter     */
664
665 nb_monitorexit:
666         pop     %r10                                    /* delete return address */
667         sub     $3,%r10                                 /* faulting address is return adress - 3 */
668         mov     proto_java_lang_NullPointerException,%rax
669         jmp     asm_handle_exception
670
671
672 /********************* function asm_builtin_x2x ********************************
673 *                                                                              *
674 *   Wrapper functions for float to int corner cases                            *
675 *                                                                              *
676 *******************************************************************************/
677
678 asm_builtin_f2i:
679         sub     $(14*8),%rsp
680
681         mov     %rdi,0*8(%rsp)
682         mov     %rsi,1*8(%rsp)
683         mov     %rdx,2*8(%rsp)
684         mov     %rcx,3*8(%rsp)
685         mov     %r8,4*8(%rsp)
686         mov     %r9,5*8(%rsp)
687         
688         movq    %xmm0,6*8(%rsp)
689         movq    %xmm1,7*8(%rsp)
690         movq    %xmm2,8*8(%rsp)
691         movq    %xmm3,9*8(%rsp)
692         movq    %xmm4,10*8(%rsp)
693         movq    %xmm5,11*8(%rsp)
694         movq    %xmm6,12*8(%rsp)
695         movq    %xmm7,13*8(%rsp)
696
697         movq    %xmm8,%xmm0
698         call    builtin_f2i
699         
700         mov     0*8(%rsp),%rdi
701         mov     1*8(%rsp),%rsi
702         mov     2*8(%rsp),%rdx
703         mov     3*8(%rsp),%rcx
704         mov     4*8(%rsp),%r8
705         mov     5*8(%rsp),%r9
706
707         movq    6*8(%rsp),%xmm0
708         movq    7*8(%rsp),%xmm1
709         movq    8*8(%rsp),%xmm2
710         movq    9*8(%rsp),%xmm3
711         movq    10*8(%rsp),%xmm4
712         movq    11*8(%rsp),%xmm5
713         movq    12*8(%rsp),%xmm6
714         movq    13*8(%rsp),%xmm7
715         
716         add     $(14*8),%rsp
717         ret
718
719 asm_builtin_f2l:
720         sub     $(14*8),%rsp
721
722         mov     %rdi,0*8(%rsp)
723         mov     %rsi,1*8(%rsp)
724         mov     %rdx,2*8(%rsp)
725         mov     %rcx,3*8(%rsp)
726         mov     %r8,4*8(%rsp)
727         mov     %r9,5*8(%rsp)
728         
729         movq    %xmm0,6*8(%rsp)
730         movq    %xmm1,7*8(%rsp)
731         movq    %xmm2,8*8(%rsp)
732         movq    %xmm3,9*8(%rsp)
733         movq    %xmm4,10*8(%rsp)
734         movq    %xmm5,11*8(%rsp)
735         movq    %xmm6,12*8(%rsp)
736         movq    %xmm7,13*8(%rsp)
737
738         movq    %xmm8,%xmm0
739         call    builtin_f2l
740         
741         mov     0*8(%rsp),%rdi
742         mov     1*8(%rsp),%rsi
743         mov     2*8(%rsp),%rdx
744         mov     3*8(%rsp),%rcx
745         mov     4*8(%rsp),%r8
746         mov     5*8(%rsp),%r9
747
748         movq    6*8(%rsp),%xmm0
749         movq    7*8(%rsp),%xmm1
750         movq    8*8(%rsp),%xmm2
751         movq    9*8(%rsp),%xmm3
752         movq    10*8(%rsp),%xmm4
753         movq    11*8(%rsp),%xmm5
754         movq    12*8(%rsp),%xmm6
755         movq    13*8(%rsp),%xmm7
756         
757         add     $(14*8),%rsp
758         ret
759
760                 
761 asm_builtin_d2i:
762         sub     $(14*8),%rsp
763
764         mov     %rdi,0*8(%rsp)
765         mov     %rsi,1*8(%rsp)
766         mov     %rdx,2*8(%rsp)
767         mov     %rcx,3*8(%rsp)
768         mov     %r8,4*8(%rsp)
769         mov     %r9,5*8(%rsp)
770         
771         movq    %xmm0,6*8(%rsp)
772         movq    %xmm1,7*8(%rsp)
773         movq    %xmm2,8*8(%rsp)
774         movq    %xmm3,9*8(%rsp)
775         movq    %xmm4,10*8(%rsp)
776         movq    %xmm5,11*8(%rsp)
777         movq    %xmm6,12*8(%rsp)
778         movq    %xmm7,13*8(%rsp)
779
780         movq    %xmm8,%xmm0
781         call    builtin_d2i
782         
783         mov     0*8(%rsp),%rdi
784         mov     1*8(%rsp),%rsi
785         mov     2*8(%rsp),%rdx
786         mov     3*8(%rsp),%rcx
787         mov     4*8(%rsp),%r8
788         mov     5*8(%rsp),%r9
789
790         movq    6*8(%rsp),%xmm0
791         movq    7*8(%rsp),%xmm1
792         movq    8*8(%rsp),%xmm2
793         movq    9*8(%rsp),%xmm3
794         movq    10*8(%rsp),%xmm4
795         movq    11*8(%rsp),%xmm5
796         movq    12*8(%rsp),%xmm6
797         movq    13*8(%rsp),%xmm7
798         
799         add     $(14*8),%rsp
800         ret
801
802
803 asm_builtin_d2l:
804         sub     $(14*8),%rsp
805
806         mov     %rdi,0*8(%rsp)
807         mov     %rsi,1*8(%rsp)
808         mov     %rdx,2*8(%rsp)
809         mov     %rcx,3*8(%rsp)
810         mov     %r8,4*8(%rsp)
811         mov     %r9,5*8(%rsp)
812         
813         movq    %xmm0,6*8(%rsp)
814         movq    %xmm1,7*8(%rsp)
815         movq    %xmm2,8*8(%rsp)
816         movq    %xmm3,9*8(%rsp)
817         movq    %xmm4,10*8(%rsp)
818         movq    %xmm5,11*8(%rsp)
819         movq    %xmm6,12*8(%rsp)
820         movq    %xmm7,13*8(%rsp)
821
822         movq    %xmm8,%xmm0
823         call    builtin_d2l
824         
825         mov     0*8(%rsp),%rdi
826         mov     1*8(%rsp),%rsi
827         mov     2*8(%rsp),%rdx
828         mov     3*8(%rsp),%rcx
829         mov     4*8(%rsp),%r8
830         mov     5*8(%rsp),%r9
831
832         movq    6*8(%rsp),%xmm0
833         movq    7*8(%rsp),%xmm1
834         movq    8*8(%rsp),%xmm2
835         movq    9*8(%rsp),%xmm3
836         movq    10*8(%rsp),%xmm4
837         movq    11*8(%rsp),%xmm5
838         movq    12*8(%rsp),%xmm6
839         movq    13*8(%rsp),%xmm7
840         
841         add     $(14*8),%rsp
842         ret
843
844         
845 /*********************** function new_builtin_checkcast ************************
846 *                                                                              *
847 *   Does the cast check and eventually throws an exception                     *
848 *                                                                              *
849 *******************************************************************************/
850
851 asm_builtin_checkcast:
852         xor     %rax,%rax
853         mov     %rax,(%rax)
854         ret
855
856                 
857 /******************* function asm_builtin_checkarraycast ***********************
858 *                                                                              *
859 *   Does the cast check and eventually throws an exception                     *
860 *                                                                              *
861 *******************************************************************************/
862
863 asm_builtin_checkarraycast:
864         sub     $24,%rsp                                /* keep stack 16-byte aligned         */
865         mov     %rdi,(%rsp)                             /* save object pointer                */
866         call    builtin_checkarraycast  /* builtin_checkarraycast             */
867         test    %rax,%rax               /* if (false) throw exception         */
868         je      nb_carray_throw
869         mov     (%rsp),%rax             /* return object pointer              */
870         add     $24,%rsp                /* free stack space                   */
871         ret
872
873 nb_carray_throw:
874         add     $24,%rsp
875         pop     %r10                                    /* delete return address              */
876         sub     $3,%r10                                 /* faulting address is return adress - 3 */
877         mov     proto_java_lang_ClassCastException,%rax
878         jmp     asm_handle_exception
879
880                 
881 /******************* function asm_builtin_aastore ******************************
882 *                                                                              *
883 *   Does the cast check and eventually throws an exception                     *
884 *                                                                              *
885 *******************************************************************************/
886
887 asm_builtin_aastore:
888         sub     $24,%rsp                        /* allocate stack space               */
889         test    %rdi,%rdi                               /* if null pointer throw exception    */
890         je      nb_aastore_null
891
892         movl    offarraysize(%rdi),%eax /* load size                          */
893         cmpl    %eax,%esi                               /* do bound check                     */
894         ja      nb_aastore_bound                /* if out of bounds throw exception   */
895
896         shl     $3,%rsi                                 /* index * 8                          */
897         mov     %rdi,%r10
898         add     %rsi,%r10                               /* add index * 8 to arrayref          */
899                 
900         mov     %r10,(%rsp)                     /* save store position                */
901         mov     %rdx,8(%rsp)            /* save object                        */
902         
903         mov     %rdx,%rsi               /* object is second argument          */
904         call    builtin_canstore                /* builtin_canstore(arrayref,object)  */
905         test    %rax,%rax                               /* if (false) throw exception         */
906         je      nb_aastore_throw
907
908         mov     (%rsp),%r10             /* restore store position             */
909         mov     8(%rsp),%rdx            /* restore object                     */
910         mov     %rdx,offobjarrdata(%r10)/* store objectptr in array           */
911         add     $24,%rsp                /* free stack space                   */
912         ret
913
914 nb_aastore_null:
915         add     $24,%rsp
916         pop     %r10                                    /* delete return address */
917         sub     $3,%r10                                 /* faulting address is return adress - 3 */
918                 
919         mov     proto_java_lang_NullPointerException,%rax
920         jmp     asm_handle_exception
921
922 nb_aastore_bound:
923         add     $24,%rsp
924         pop     %r10                                    /* delete return address */
925         sub     $3,%r10                                 /* faulting address is return adress - 3 */
926                 
927         mov     proto_java_lang_ArrayIndexOutOfBoundsException,%rax
928         jmp     asm_handle_exception
929                 
930 nb_aastore_throw:
931         add     $24,%rsp
932         pop     %r10                                    /* delete return address */
933         sub     $3,%r10                                 /* faulting address is return adress - 3 */
934                 
935         mov     proto_java_lang_ArrayStoreException,%rax
936         jmp             asm_handle_exception
937
938                 
939 /******************* function asm_initialize_thread_stack **********************
940 *                                                                              *
941 * initialized a thread stack                                                   *
942 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
943 *                                                                              *
944 *******************************************************************************/
945
946 asm_initialize_thread_stack:
947         sub     $(7*8),%rsi
948
949         xor     %r10,%r10
950         mov     %r10,0*8(%rsi)
951         mov     %r10,1*8(%rsi)
952         mov     %r10,2*8(%rsi)
953         mov     %r10,3*8(%rsi)
954         mov     %r10,4*8(%rsi)
955         mov     %r10,5*8(%rsi)
956
957         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
958         mov     %rsi,%rax               /* return restorepoint in %rax        */
959         ret
960
961
962 /******************* function asm_perform_threadswitch *************************
963 *                                                                              *
964 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
965 *                                                                              *
966 *   performs a threadswitch                                                    *
967 *                                                                              *
968 *******************************************************************************/
969
970 asm_perform_threadswitch:
971         sub     $(7*8),%rsp             /* allocate stack frame               */
972
973         mov     %rbx,0*8(%rsp)
974         mov     %rbp,1*8(%rsp)
975         mov     %r12,2*8(%rsp)
976         mov     %r13,3*8(%rsp)
977         mov     %r14,4*8(%rsp)
978         mov     %r15,5*8(%rsp)
979
980         mov     7*8(%rsp),%rax                  /* save current return address        */
981         mov     %rax,6*8(%rsp)
982
983         mov     %rsp,(%rdi)                     /* first argument **from              */
984         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
985
986         mov     (%rsi),%rsp                     /* load new stack pointer             */
987
988         mov     0*8(%rsp),%rbx
989         mov     1*8(%rsp),%rbp
990         mov     2*8(%rsp),%r12
991         mov     3*8(%rsp),%r13
992         mov     4*8(%rsp),%r14
993         mov     5*8(%rsp),%r15
994
995         mov     6*8(%rsp),%rax          /* restore return address             */
996         add     $(7*8),%rsp             /* free stack frame                   */
997         mov     %rax,(%rsp)
998         ret
999                 
1000
1001 /********************* function asm_switchstackandcall *************************
1002 *                                                                              *
1003 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
1004 *                                      void *p);                                       *
1005 *                                                                              *
1006 *   Switches to a new stack, calls a function and switches back.               *
1007 *       a0 (%rdi)     new stack pointer                                        *
1008 *       a1 (%rsi)     function pointer                                         *
1009 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
1010 *       a3 (%rcx)     pointer to user data, is passed to the function          *
1011 *                                                                              *
1012 *******************************************************************************/
1013
1014 asm_switchstackandcall:
1015         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
1016         sub     $16,%rdi                                /* allocate new stack                 */
1017
1018         mov     8(%rsp),%rax                    /* save return address on new stack   */
1019         mov     %rax,(%rdi)
1020         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
1021         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
1022
1023         mov     %rdi,%rsp                               /* switch to new stack                */
1024
1025         mov     %rcx,%rdi                       /* pass pointer                       */
1026         call    *%rsi                                   /* and call function                  */
1027
1028         mov     (%rsp),%r10                             /* load return address                */
1029         mov     8(%rsp),%rsp                    /* switch to old stack                */
1030         add     $(1*8),%rsp             /* free stack space                   */
1031         mov     %r10,(%rsp)             /* write return adress                */
1032         ret
1033
1034                 
1035 /********************* function asm_getcallingmethod ***************************
1036 *                                                                              *
1037 *   classinfo *asm_getcallingmethod ();                                                                    *
1038 *                                                                                                                                                          *    
1039 *   goes back stack frames to get the calling method                                               *
1040 *                                                                                                                                                          *
1041 *                               t2 .. sp                                                                                                       *
1042 *                               t3 .. ra                                                                                                       *
1043 *                               t4 .. pv                                                                                                       *
1044 *                                                                              *
1045 *   Stack:                                                                     *
1046 *       java function                                                          *
1047 *       native stub                                                            *
1048 *       Java_java_lang_System_getCallerClass                                   *
1049 *                                                                              *
1050 *******************************************************************************/
1051
1052 asm_getcallingmethod:
1053         mov     %rbp,%rax               /* return address of native function  */
1054         add     $(2*8),%rax             /* %rsp, return address               */
1055         add     $(7*8),%rax             /* native stub stackframe             */
1056         mov     (%rax),%rdi             /* return address to java function    */
1057         call    findmethod
1058         mov     MethodPointer(%rax),%rax
1059         ret
1060
1061
1062 asm_printf:
1063         push    %rbp
1064         mov     %rsp,%rbp
1065         
1066         push    %rax
1067         push    %rcx
1068         push    %rdx
1069         push    %rbx
1070         push    %rsi
1071         push    %rdi
1072         push    %r8
1073         push    %r9
1074         push    %r10
1075         push    %r11
1076         push    %r12
1077         push    %r13
1078         push    %r14
1079         push    %r15
1080
1081         mov     16(%rbp),%rdi
1082         call    asmprintf
1083
1084         pop     %r15
1085         pop     %r14
1086         pop     %r13
1087         pop     %r12
1088         pop     %r11
1089         pop     %r10
1090         pop     %r9
1091         pop     %r8
1092         pop     %rdi
1093         pop     %rsi
1094         pop     %rbx
1095         pop     %rdx
1096         pop     %rcx
1097         pop     %rax
1098         
1099         leave
1100         ret
1101         
1102 /*
1103  * These are local overrides for various environment variables in Emacs.
1104  * Please do not remove this and leave it at the end of the file, where
1105  * Emacs will automagically detect them.
1106  * ---------------------------------------------------------------------
1107  * Local variables:
1108  * mode: asm
1109  * indent-tabs-mode: t
1110  * c-basic-offset: 4
1111  * tab-width: 4
1112  * End:
1113  */