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