Lazy checkcast and instanceof.
[cacao.git] / src / vm / jit / x86_64 / asmpart.S
1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    $Id: asmpart.S 2272 2005-04-11 15:49:51Z twisti $
32
33 */
34
35
36 #include "config.h"
37 #include "vm/jit/x86_64/arch.h"
38 #include "vm/jit/x86_64/offsets.h"
39 #include "vm/jit/x86_64/asmoffsets.h"
40
41
42 /* XXX Don't remove this!!! ***************************************************/
43
44 #if offobjvftbl != 0
45 #error OFFSET(java_objectheader, vftbl) != 0: this will break code patching!
46 #endif
47
48 #if offvftblinterfacetable != 0
49 #error OFFSET(vftbl_t, interfacetable[0]) != 0: this will break code patching!
50 #endif
51
52 /******************************************************************************/
53
54
55 /* define it like the risc way */
56
57 #define v0       %rax
58 #define v0l      %eax
59
60 #define a0       %rdi
61 #define a1       %rsi
62 #define a2       %rdx
63 #define a3       %rcx
64 #define a4       %r8
65 #define a5       %r9
66
67 #define fa0      %xmm0
68 #define fa1      %xmm1
69 #define fa2      %xmm2
70 #define fa3      %xmm3
71 #define fa4      %xmm4
72 #define fa5      %xmm5
73 #define fa6      %xmm6
74 #define fa7      %xmm7
75
76 #define itmp1    %rax
77 #define itmp2    %r10
78 #define itmp3    %r11
79
80 #define itmp1l   %eax
81 #define itmp2l   %r10d
82 #define itmp3l   %r11d
83
84 #define itmp1b   %al
85 #define itmp2b   %r10b
86 #define itmp3b   %r11b
87
88 #define xptr     itmp1
89 #define xpc      itmp2
90
91
92 /* save and restore macros ****************************************************/
93
94 #define SAVE_ARGUMENT_REGISTERS \
95         mov     a0,0*8(%rsp)            ; \
96         mov     a1,1*8(%rsp)            ; \
97         mov     a2,2*8(%rsp)            ; \
98         mov     a3,3*8(%rsp)            ; \
99         mov     a4,4*8(%rsp)            ; \
100         mov     a5,5*8(%rsp)            ; \
101         movq    fa0,6*8(%rsp)           ; \
102         movq    fa1,7*8(%rsp)           ; \
103         movq    fa2,8*8(%rsp)           ; \
104         movq    fa3,9*8(%rsp)           ; \
105         movq    fa4,10*8(%rsp)          ; \
106         movq    fa5,11*8(%rsp)          ; \
107         movq    fa6,12*8(%rsp)          ; \
108         movq    fa7,13*8(%rsp)          ;
109
110
111 #define RESTORE_ARGUMENT_REGISTERS \
112         mov     0*8(%rsp),a0            ; \
113         mov     1*8(%rsp),a1            ; \
114         mov     2*8(%rsp),a2            ; \
115         mov     3*8(%rsp),a3            ; \
116         mov     4*8(%rsp),a4            ; \
117         mov     5*8(%rsp),a5            ; \
118         movq    6*8(%rsp),fa0           ; \
119         movq    7*8(%rsp),fa1           ; \
120         movq    8*8(%rsp),fa2           ; \
121         movq    9*8(%rsp),fa3           ; \
122         movq    10*8(%rsp),fa4          ; \
123         movq    11*8(%rsp),fa5          ; \
124         movq    12*8(%rsp),fa6          ; \
125         movq    13*8(%rsp),fa7          ; 
126
127
128 #define SAVE_TEMPORARY_REGISTERS \
129         mov     %rbx,14*8(%rsp)
130
131
132 #define RESTORE_TEMPORARY_REGISTERS \
133         mov     14*8(%rsp),%rbx
134
135
136         .text
137
138
139 /********************* exported functions and variables ***********************/
140
141         .globl asm_calljavafunction
142         .globl asm_calljavafunction_int
143
144         .globl asm_calljavafunction2
145         .globl asm_calljavafunction2int
146         .globl asm_calljavafunction2long
147         .globl asm_calljavafunction2float
148         .globl asm_calljavafunction2double
149
150         .globl asm_call_jit_compiler
151         .globl asm_handle_exception
152         .globl asm_handle_nat_exception
153
154         .globl asm_get_putstatic
155         .globl asm_get_putfield
156         .globl asm_builtin_new
157         .globl asm_builtin_newarray
158         .globl asm_builtin_multianewarray
159         .globl asm_invokestatic_special
160         .globl asm_invokevirtual
161         .globl asm_invokeinterface
162         .globl asm_checkcast_instanceof_flags
163         .globl asm_checkcast_instanceof_interface
164         .globl asm_checkcast_class
165         .globl asm_instanceof_class
166         .globl asm_check_clinit
167
168         .globl asm_builtin_checkarraycast
169         .globl asm_builtin_aastore
170
171 #if defined(USE_THREADS)
172         .globl asm_builtin_monitorenter
173         .globl asm_builtin_monitorexit
174 #endif
175
176         .globl asm_builtin_f2i
177         .globl asm_builtin_f2l
178         .globl asm_builtin_d2i
179         .globl asm_builtin_d2l
180
181         .globl asm_perform_threadswitch
182         .globl asm_initialize_thread_stack
183         .globl asm_switchstackandcall
184         .globl asm_criticalsections
185         .globl asm_getclassvalues_atomic
186                 
187
188 /********************* function asm_calljavafunction ***************************
189 *                                                                              *
190 *   This function calls a Java-method (which possibly needs compilation)       *
191 *   with up to 4 address parameters.                                           *
192 *                                                                              *
193 *   This functions calls the JIT-compiler which eventually translates the      *
194 *   method into machine code.                                                  *
195 *                                                                              *
196 *   C-prototype:                                                               *
197 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
198 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
199 *                                                                              *
200 *******************************************************************************/
201
202 call_name:
203         .align  8
204
205         .quad   0                         /* catch type all                       */
206         .quad   calljava_xhandler         /* handler pc                           */
207         .quad   calljava_xhandler         /* end pc                               */
208         .quad   asm_calljavafunction      /* start pc                             */
209         .long   1                         /* extable size                         */
210         .long   0                         /* fltsave                              */
211         .long   0                         /* intsave                              */
212         .long   0                         /* isleaf                               */
213         .long   0                         /* IsSync                               */
214         .long   8                         /* frame size                           */
215         .quad   0                         /* method pointer (pointer to name)     */
216
217 asm_calljavafunction:
218 asm_calljavafunction_int:
219         sub     $(3*8),%rsp               /* keep stack 16-byte aligned           */
220         mov     %rbp,0*8(%rsp)
221         mov     %rbx,1*8(%rsp)            /* %rbx is not a callee saved in cacao  */
222         mov     %rdi,%rax                 /* move function pointer to %rax        */
223                                                                           /* compilerstub uses this               */
224
225         mov     %rsi,%rdi                 /* pass remaining parameters            */
226         mov     %rdx,%rsi
227         mov     %rcx,%rdx
228         mov     %r8,%rcx
229         
230         lea     asm_call_jit_compiler,%r11
231         call    *%r11                     /* call JIT compiler                    */
232
233         mov     0*8(%rsp),%rbp
234         mov             1*8(%rsp),%rbx
235         add     $(3*8),%rsp               /* free stack space                     */
236         ret
237
238 calljava_xhandler:
239         mov     %rax,%rdi                 /* pass exception pointer               */
240         call    builtin_throw_exception
241         mov     0*8(%rsp),%rbp
242         mov             1*8(%rsp),%rbx
243         add     $(3*8),%rsp
244         xor     %rax,%rax                 /* return NULL                          */
245         ret
246
247
248 /********************* function asm_calljavafunction ***************************
249 *                                                                              *
250 *   This function calls a Java-method (which possibly needs compilation)       *
251 *   with up to 4 address parameters.                                           *
252 *                                                                              *
253 *   This functions calls the JIT-compiler which eventually translates the      *
254 *   method into machine code.                                                  *
255 *                                                                              *
256 *   C-prototype:                                                               *
257 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
258 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
259 *                                                                              *
260 *******************************************************************************/
261
262 call_name2:
263         .align  8
264
265         .quad   0                         /* catch type all                       */
266         .quad   calljava_xhandler2        /* handler pc                           */
267         .quad   calljava_xhandler2        /* end pc                               */
268         .quad   asm_calljavafunction2     /* start pc                             */
269         .long   1                         /* extable size                         */
270         .long   0                         /* fltsave                              */
271         .long   0                         /* intsave                              */
272         .long   0                         /* isleaf                               */
273         .long   0                         /* IsSync                               */
274         .long   24                        /* frame size                           */
275         .quad   0                         /* method pointer (pointer to name)     */
276
277 asm_calljavafunction2:
278 asm_calljavafunction2int:
279 asm_calljavafunction2long:
280 asm_calljavafunction2float:
281 asm_calljavafunction2double:
282         sub     $(7*8),%rsp               /* keep stack 16-byte aligned           */
283         mov     %rbx,0*8(%rsp)            /* %rbx is not a callee saved in cacao  */
284         mov     %rbp,1*8(%rsp)
285         mov     %r12,2*8(%rsp)
286         mov     %r13,3*8(%rsp)
287         mov     %r14,4*8(%rsp)
288         mov     %r15,5*8(%rsp)
289
290         mov     %rdi,%rax                 /* move method pointer for compiler     */
291         xor     %rbp,%rbp                 /* set argument stack frame to zero     */
292
293         test    %rsi,%rsi                 /* maybe we have no args...             */
294         jle     L_copy_done
295
296         mov     %rsi,itmp3                /* arg count                            */
297         mov     %rcx,itmp2                /* pointer to arg block                 */
298
299         mov     itmp2,%r14                /* save argument block pointer          */
300         mov     itmp3,%r15                /* save argument count                  */
301
302         sub     $sizejniblock,itmp2       /* initialize pointer (smaller code)    */
303         add     $1,itmp3                  /* initialize argument count            */
304         xor     %r12,%r12                 /* initialize integer argument counter  */
305         xor     %r13,%r13                 /* initialize float argument counter    */
306
307 L_register_copy:
308         add     $sizejniblock,itmp2       /* goto next argument block             */
309         dec     itmp3                     /* argument count - 1                   */
310         jz      L_register_copy_done
311         andb    $0x02,offjniitemtype(itmp2) /* is this a float/double type?       */
312         jnz     L_register_handle_float   /* yes, handle it                       */
313
314         cmp     $INT_ARG_CNT,%r12         /* are we out of integer argument       */
315         je      L_register_copy           /* register? yes, next loop             */
316
317         lea     jumptable_integer,%rbp
318         mov     0(%rbp,%r12,8),%rbx
319         inc     %r12                      /* integer argument counter + 1         */
320         jmp     *%rbx
321
322 L_register_handle_float:
323         cmp     $FLT_ARG_CNT,%r13         /* are we out of float argument         */
324         je      L_register_copy           /* register? yes, next loop             */
325
326         lea     jumptable_float,%rbp
327         mov     0(%rbp,%r13,8),%rbx
328         inc     %r13                      /* float argument counter + 1           */
329         jmp     *%rbx
330         
331 L_register_copy_done:
332         mov     %r15,%rbp                 /* calculate remaining arguments        */
333         sub     %r12,%rbp                 /* - integer arguments in registers     */
334         sub     %r13,%rbp                 /* - float arguments in registers       */
335         jle     L_copy_done               /* are all assigned to registers?       */
336
337         shl     $3,%rbp                   /* calculate stack size                 */
338         sub     %rbp,%rsp                 /* stack frame for arguments            */
339         mov     %rsp,%rbx                 /* use %rbx as temp sp                  */
340
341         sub     $sizejniblock,%r14        /* initialize pointer (smaller code)    */
342         add     $1,%r15                   /* initialize argument count            */
343                 
344 L_stack_copy_loop:
345         add     $sizejniblock,%r14        /* goto next argument block             */
346         dec     %r15                      /* are there any arguments left?        */
347         jz      L_copy_done               /* no test needed after dec             */
348
349         andb    $0x02,offjniitemtype(%r14) /* is this a float/double type?        */
350         jnz     L_stack_handle_float
351         dec     %r12                      /* arguments assigned to registers      */
352         jge     L_stack_copy_loop
353         jmp     L_stack_copy
354
355 L_stack_handle_float:
356         dec     %r13                      /* arguments assigned to registers      */
357         jge     L_stack_copy_loop
358
359 L_stack_copy:
360     mov     offjniitem(%r14),itmp3    /* copy s8 argument onto stack          */
361     mov     itmp3,0(%rbx)
362     add     $8,%rbx                   /* increase sp to next argument         */
363         jmp     L_stack_copy_loop
364
365 L_copy_done:
366         lea     asm_call_jit_compiler,%r11/* %rax still contains method pointer   */
367         call    *%r11                     /* call JIT compiler                    */
368
369         add     %rbp,%rsp                 /* remove argument stack frame if any   */
370
371         mov     5*8(%rsp),%r15            /* restore callee saved registers       */
372         mov     4*8(%rsp),%r14
373         mov     3*8(%rsp),%r13
374         mov     2*8(%rsp),%r12
375         mov     1*8(%rsp),%rbp
376         mov     0*8(%rsp),%rbx
377         add     $(7*8),%rsp               /* free stack space                     */
378         ret
379                 
380 calljava_xhandler2:
381         mov     %rax,%rdi                 /* pass exception pointer               */
382         call    builtin_throw_exception
383
384         mov     5*8(%rsp),%r15            /* restore callee saved registers       */
385         mov     4*8(%rsp),%r14
386         mov     3*8(%rsp),%r13
387         mov     2*8(%rsp),%r12
388         mov     1*8(%rsp),%rbp
389         mov     0*8(%rsp),%rbx
390         add     $(7*8),%rsp               /* free stack space                     */
391         xor     %rax,%rax                 /* return NULL                          */
392         ret
393
394
395 jumptable_integer:
396         .quad   handle_a0
397         .quad   handle_a1
398         .quad   handle_a2
399         .quad   handle_a3
400         .quad   handle_a4
401         .quad   handle_a5
402
403 handle_a0:
404         mov     offjniitem(itmp2),a0
405         jmp     L_register_copy
406 handle_a1:
407         mov     offjniitem(itmp2),a1
408         jmp     L_register_copy
409 handle_a2:
410         mov     offjniitem(itmp2),a2
411         jmp     L_register_copy
412 handle_a3:
413         mov     offjniitem(itmp2),a3
414         jmp     L_register_copy
415 handle_a4:
416         mov     offjniitem(itmp2),a4
417         jmp     L_register_copy
418 handle_a5:
419         mov     offjniitem(itmp2),a5
420         jmp     L_register_copy
421
422
423 jumptable_float:
424         .quad   handle_fa0
425         .quad   handle_fa1
426         .quad   handle_fa2
427         .quad   handle_fa3
428         .quad   handle_fa4
429         .quad   handle_fa5
430         .quad   handle_fa6
431         .quad   handle_fa7
432
433 handle_fa0:
434         movq    offjniitem(itmp2),fa0
435         jmp     L_register_copy
436 handle_fa1:
437         movq    offjniitem(itmp2),fa1
438         jmp     L_register_copy
439 handle_fa2:
440         movq    offjniitem(itmp2),fa2
441         jmp     L_register_copy
442 handle_fa3:
443         movq    offjniitem(itmp2),fa3
444         jmp     L_register_copy
445 handle_fa4:
446         movq    offjniitem(itmp2),fa4
447         jmp     L_register_copy
448 handle_fa5:
449         movq    offjniitem(itmp2),fa5
450         jmp     L_register_copy
451 handle_fa6:
452         movq    offjniitem(itmp2),fa6
453         jmp     L_register_copy
454 handle_fa7:
455         movq    offjniitem(itmp2),fa7
456         jmp     L_register_copy
457
458
459 /****************** function asm_call_jit_compiler *****************************
460 *                                                                              *
461 *   invokes the compiler for untranslated JavaVM methods.                      *
462 *                                                                              *
463 *   Register R0 contains a pointer to the method info structure (prepared      *
464 *   by createcompilerstub). Using the return address in R26 and the            *
465 *   offset in the LDA instruction or using the value in methodptr R28 the      *
466 *   patching address for storing the method address can be computed:           *
467 *                                                                              *
468 *   method address was either loaded using                                     *
469 *                                                                              *
470 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
471 *   i386_call_reg(REG_ITMP2)                                                   *
472 *                                                                              *
473 *   or                                                                         *
474 *                                                                              *
475 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
476 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
477 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
478 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
479 *   i386_call_reg(REG_ITMP1)                                                   *
480 *                                                                              *
481 *   in the static case the method pointer can be computed using the            *
482 *   return address and the lda function following the jmp instruction          *
483 *                                                                              *
484 *******************************************************************************/
485
486 asm_call_jit_compiler:
487         sub     $8,%rsp                 /* keep stack 16-byte aligned             */
488
489         mov     %rbx,(%rsp)             /* save register                          */
490         
491         mov     8(%rsp),%r11    /* get return address                         */
492         mov     -1(%r11),%bl    /* get function code                          */
493         cmp     $0xd2,%bl               /* called with `call *REG_ITMP2' (%r10)?      */
494         jne     L_not_static_special
495
496         sub     $11,%r11        /* calculate address of immediate             */
497         jmp             L_call_jit_compile
498                 
499 L_not_static_special:
500                 cmp     $0xd0,%bl               /* called with `call *REG_ITMP1' (%rax)       */
501                 jne     L_not_virtual_interface
502                 
503                 sub     $7,%r11         /* calculate address of offset                */
504                 mov     (%r11),%r11d    /* get offset (32-bit)                        */
505                 add     %r10,%r11       /* add base address to get method address     */
506                 jmp     L_call_jit_compile
507
508 L_not_virtual_interface:        /* a call from asm_calljavamethod             */
509                 xor     %r11,%r11
510                 
511 L_call_jit_compile:
512         mov     (%rsp),%rbx     /* restore register                           */
513         
514         sub     $(24*8),%rsp    /* 8 + 6*8 + 8*8 + 8*8                        */
515         
516                 mov     %r11,0*8(%rsp)  /* save address for method pointer            */
517
518         mov     a0,1*8(%rsp)    /* save arguments                             */
519         mov     a1,2*8(%rsp)
520         mov     a2,3*8(%rsp)
521         mov     a3,4*8(%rsp)
522         mov     a4,5*8(%rsp)
523         mov     a5,6*8(%rsp)
524
525         movq    fa0,7*8(%rsp)
526         movq    fa1,8*8(%rsp)
527         movq    fa2,9*8(%rsp)
528         movq    fa3,10*8(%rsp)
529         movq    fa4,11*8(%rsp)
530         movq    fa5,12*8(%rsp)
531         movq    fa6,13*8(%rsp)
532         movq    fa7,14*8(%rsp)
533
534         movq    %xmm8,15*8(%rsp)/* we use them as callee saved registers      */
535         movq    %xmm9,16*8(%rsp)
536         movq    %xmm10,17*8(%rsp)
537         movq    %xmm11,18*8(%rsp)
538         movq    %xmm12,19*8(%rsp)
539         movq    %xmm13,20*8(%rsp)
540         movq    %xmm14,21*8(%rsp)
541         movq    %xmm15,22*8(%rsp)
542
543         mov     %rax,%rdi       /* pass method pointer                        */
544                 call    jit_compile
545
546         mov     0*8(%rsp),%r11
547         
548         mov     1*8(%rsp),a0
549         mov     2*8(%rsp),a1
550         mov     3*8(%rsp),a2
551         mov     4*8(%rsp),a3
552         mov     5*8(%rsp),a4
553         mov     6*8(%rsp),a5
554
555         movq    7*8(%rsp),fa0
556         movq    8*8(%rsp),fa1
557         movq    9*8(%rsp),fa2
558         movq    10*8(%rsp),fa3
559         movq    11*8(%rsp),fa4
560         movq    12*8(%rsp),fa5
561         movq    13*8(%rsp),fa6
562         movq    14*8(%rsp),fa7
563
564         movq    15*8(%rsp),%xmm8
565         movq    16*8(%rsp),%xmm9
566         movq    17*8(%rsp),%xmm10
567         movq    18*8(%rsp),%xmm11
568         movq    19*8(%rsp),%xmm12
569         movq    20*8(%rsp),%xmm13
570         movq    21*8(%rsp),%xmm14
571         movq    22*8(%rsp),%xmm15
572
573         add     $(24*8),%rsp
574         add     $8,%rsp                 /* keep stack 16-byte aligned             */
575
576         test    %rax,%rax               /* check for exception                    */
577         je      L_asm_call_jit_compiler_exception
578
579         test    %r11,%r11               /* is address == 0 (asm_calljavamethod)   */
580         je      L_call_method
581
582         mov     %rax,(%r11)             /* and now save the new pointer           */
583
584 L_call_method:
585         jmp     *%rax                   /* ...and now call the new method         */
586
587 L_asm_call_jit_compiler_exception:
588 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
589         call    builtin_asm_get_exceptionptrptr
590         mov     %rax,itmp2
591 #else
592         lea     _exceptionptr,itmp2
593 #endif
594         mov     (itmp2),xptr                /* get the exception pointer          */
595         movl    $0,(itmp2)                  /* clear the exception pointer        */
596
597         pop     xpc                         /* delete return address              */
598         sub     $5,xpc                      /* faulting address is ra - 5         */
599
600         jmp     asm_handle_exception
601
602
603 /********************* function asm_handle_exception ***************************
604 *                                                                              *
605 *   This function handles an exception. It does not use the usual calling      *
606 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
607 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
608 *   the local exception table for a handler. If no one is found, it unwinds    *
609 *   stacks and continues searching the callers.                                *
610 *                                                                              *
611 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
612 *                                                                              *
613 *******************************************************************************/
614
615 asm_handle_nat_exception:
616         add     $8,%rsp                     /* clear return address of native stub*/
617                 
618 asm_handle_exception:
619         sub     $(4*8),%rsp
620         mov     xptr,0*8(%rsp)              /* save exception pointer             */
621         mov     xpc,1*8(%rsp)               /* save exception pc                  */
622         
623         mov     xpc,%rdi                    /* exception pc                       */
624         call    codegen_findmethod
625         mov     %rax,itmp3
626         mov     %rax,2*8(%rsp)              /* save data segment pointer          */
627         
628         mov     0*8(%rsp),%rax              /* restore exception pointer          */
629         mov     1*8(%rsp),%r10              /* restore exception pc               */
630         
631 ex_stack_loop:
632         mov     %rax,%rdi                   /* exception pointer                  */
633         mov     MethodPointer(itmp3),%rsi   /* method pointer                     */
634         mov     xpc,%rdx                    /* exception pc                       */
635         mov     $0,%rcx
636         mov     $1,%r8                      /* set noindent flag                  */
637         call    builtin_trace_exception
638
639         mov     2*8(%rsp),itmp3             /* %r11 = data segment pointer        */
640         mov     ExTableSize(itmp3),%rcx     /* %rcx = exception table size        */
641         test    %rcx,%rcx                                       /* if empty table skip                */
642         je      empty_table
643
644         lea     ExTableStart(itmp3),%rdi    /* %rdi = start of exception table    */
645         mov     0*8(%rsp),xptr              /* get xptr                           */
646                 
647 ex_table_loop:
648         mov     1*8(%rsp),xpc               /* get xpc                            */
649                 
650         mov     ExStartPC(%rdi),%rdx        /* %rdx = exception start pc          */
651         cmp     xpc,%rdx                    /* %rdx = (startpc <= xpc)            */
652         jg      ex_table_cont               /* if (false) continue                */
653         mov     ExEndPC(%rdi),%rdx          /* %rdx = exception end pc            */
654         cmp     %rdx,xpc                    /* %rdx = (xpc < endpc)               */
655         jge     ex_table_cont               /* if (false) continue                */
656         mov     ExCatchType(%rdi),%rdx      /* %rdx = exception catch type        */
657         test    %rdx,%rdx                   /* NULL catches everything            */
658         je      ex_handle_it
659
660         cmpl    $0,offclassloaded(%rdx)     /* check if class is loaded           */
661         jne     L_class_loaded
662
663         sub     $(4*8),%rsp
664         mov     %rax,0*8(%rsp)
665         mov     %rcx,1*8(%rsp)
666         mov     %rdx,2*8(%rsp)
667         mov     %rdi,3*8(%rsp)
668
669         mov     %rdx,%rdi
670         call    load_class_bootstrap
671
672         mov     0*8(%rsp),%rax
673         mov     1*8(%rsp),%rcx
674         mov     2*8(%rsp),%rdx
675         mov     3*8(%rsp),%rdi
676         add     $(4*8),%rsp
677
678 L_class_loaded:
679         cmpl    $0,offclasslinked(%rdx)     /* check if class is linked           */
680         jne     L_class_linked
681
682         sub     $(4*8),%rsp
683         mov     %rax,0*8(%rsp)
684         mov     %rcx,1*8(%rsp)
685         mov     %rdx,2*8(%rsp)
686         mov     %rdi,3*8(%rsp)
687
688         mov     %rdx,%rdi
689         call    link_class
690
691         mov     0*8(%rsp),%rax
692         mov     1*8(%rsp),%rcx
693         mov     2*8(%rsp),%rdx
694         mov     3*8(%rsp),%rdi
695         add     $(4*8),%rsp
696
697 L_class_linked:
698 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
699         push    %rdx
700
701 _crit_restart1:
702         mov     0(%rsp),%rdx
703 #endif
704
705 _crit_begin1:
706         mov     offobjvftbl(%rax),%rsi      /* %rsi = vftblptr(xptr)              */
707         mov     offclassvftbl(%rdx),%rdx    /* %rdx = vftblptr(catchtype) class (not obj) */
708         mov     offbaseval(%rsi),%esi       /* %esi = baseval(xptr)               */
709         mov     offbaseval(%rdx),%r10d      /* %r10d = baseval(catchtype)         */
710         mov     offdiffval(%rdx),%edx       /* %edx = diffval(catchtype)          */
711 _crit_end1:
712         sub     %r10d,%esi                  /* %esi = baseval(xptr) - baseval(catchtype) */
713
714 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
715         add     $8,%rsp
716 #endif
717
718         cmp     %edx,%esi                   /* xptr is instanceof catchtype       */
719         ja      ex_table_cont
720                 
721 ex_handle_it:
722                 mov     ExHandlerPC(%rdi),xpc       /* xpc = exception handler pc     */
723
724         mov     0*8(%rsp),%rax              /* restore exception pointer      */
725         add     $(4*8),%rsp                 /* free stack frame               */
726
727         jmp             *xpc                        /* jump to the handler            */
728
729 ex_table_cont:
730         lea             ExEntrySize(%rdi),%rdi      /* next exception table entry     */
731         dec     %rcx                        /* decrement entry counter        */
732         test    %rcx,%rcx                   /* if (t0 > 0) next entry         */
733         jg              ex_table_loop
734                 
735 empty_table:
736         mov     0*8(%rsp),%rax              /* restore exception pointer      */
737         mov     1*8(%rsp),%r10              /* restore exception pc           */
738         mov     2*8(%rsp),%r11                          /* restore data segment pointer   */
739         add     $(4*8),%rsp
740         
741                 mov     %rax,%rcx                                       /* save exception pointer         */
742                                 
743 ex_already_cleared:             
744                 movl    IsSync(%r11),%eax                       /* %rax = SyncOffset              */
745                 test    %rax,%rax                                       /* if zero no monitorexit         */
746                 je              no_monitor_exit
747
748 #if defined(USE_THREADS)                
749                 add     %rsp,%rax
750                 mov     -8(%rax),%rdi
751
752         sub     $(4*8),%rsp
753         mov     %rcx,0*8(%rsp)
754         mov     %r10,1*8(%rsp)
755         mov     %r11,2*8(%rsp)
756         
757                 call    builtin_monitorexit
758
759         mov     0*8(%rsp),%rcx
760         mov     1*8(%rsp),%r10
761         mov     2*8(%rsp),%r11
762         add     $(4*8),%rsp
763 #endif
764
765 no_monitor_exit:
766                 mov             FrameSize(%r11),%eax        /* %eax = frame size              */
767                 add             %rax,%rsp                   /* unwind stack                   */
768                 mov             %rsp,%rax                   /* %rax = pointer to save area    */
769
770                 mov             IntSave(%r11),%edx          /* %edx = saved int register count*/
771         test    %edx,%edx
772         je              noint
773         
774                 cmp     $1,%edx
775                 je              int1
776                 cmp             $2,%edx
777                 je              int2
778                 cmp             $3,%edx
779                 je              int3
780                 cmp             $4,%edx
781                 je              int4
782                 cmp             $5,%edx
783                 je              int5
784         
785         mov     -48(%rax),%rbx
786 int5:   
787         mov     -40(%rax),%rbp
788 int4:   
789         mov     -32(%rax),%r12
790 int3:   
791         mov     -24(%rax),%r13
792 int2:   
793                 mov     -16(%rax),%r14
794 int1:   
795                 mov     -8(%rax),%r15
796
797                 shl             $3,%edx                     /* multiply by 8 bytes            */
798                 sub     %rdx,%rax
799                 
800 noint:
801                 mov     FltSave(%r11),%edx          /* %edx = saved flt register count*/
802                 test    %edx,%edx
803                 je      noflt
804
805         cmpl    $1,%edx
806         je      flt1
807         cmpl    $2,%edx
808         je      flt2
809         cmpl    $3,%edx
810         je      flt3
811         cmpl    $4,%edx
812         je      flt4
813         cmpl    $5,%edx
814         je      flt5
815         cmpl    $6,%edx
816         je      flt7
817         cmpl    $7,%edx
818         je      flt7
819
820         movq    -64(%rax),%xmm8
821 flt7:   
822         movq    -56(%rax),%xmm9
823 flt6:   
824         movq    -48(%rax),%xmm10
825 flt5:   
826         movq    -40(%rax),%xmm11
827 flt4:   
828         movq    -32(%rax),%xmm12
829 flt3:   
830         movq    -24(%rax),%xmm13
831 flt2:   
832         movq    -16(%rax),%xmm14
833 flt1:   
834         movq    -8(%rax),%xmm15
835                 
836 noflt:                                  
837                 pop     %r10                                            /* the new xpc is return address  */
838                 sub     $3,%r10                     /* subtract 3 bytes for call      */
839
840         sub     $(2*8),%rsp
841         mov     %rcx,0*8(%rsp)
842         mov     %r10,1*8(%rsp)
843
844         mov     %r10,%rdi
845         call    codegen_findmethod          /* get the new data segment ptr   */
846         mov     %rax,%r11
847         
848         mov     0*8(%rsp),%rcx
849         mov     1*8(%rsp),%r10
850         add     $(2*8),%rsp
851
852         mov     %rcx,%rax                                       /* restore saved exception pointer*/
853
854         sub     $(4*8),%rsp
855                                         
856         mov     %rax,0*8(%rsp)              /* save exception pointer         */
857         mov     %r10,1*8(%rsp)              /* save exception pc              */
858                 mov     %r11,2*8(%rsp)                          /* save data segment pointer      */
859                 
860                 jmp             ex_stack_loop
861
862
863 /* asm_get_putstatic ***********************************************************
864
865    XXX
866
867    Stack layout:
868      16   return address
869       8   machine code (which is patched back later)
870       0   unresolved field reference
871
872 *******************************************************************************/
873
874 asm_get_putstatic:
875         sub     $(15*8),%rsp                /* stack frame (16-byte aligned)      */
876
877         SAVE_ARGUMENT_REGISTERS
878         SAVE_TEMPORARY_REGISTERS
879
880         mov     (0+15)*8(%rsp),a0           /* pass unresolved_field pointer      */
881         call    helper_resolve_fieldinfo_value_address /* call the helper function*/
882
883         RESTORE_ARGUMENT_REGISTERS
884         RESTORE_TEMPORARY_REGISTERS
885
886         mov     (1+15)*8(%rsp),itmp3        /* get machine code                   */
887         add     $((2+15)*8),%rsp            /* remove stack frame, keep ra        */
888
889         test    v0,v0                       /* exception thrown?                  */
890         jz      L_asm_codepatcher_exception
891
892         pop     itmp2                       /* get return address                 */
893         sub     $5,itmp2                    /* remove size of `call rel32'        */
894         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
895
896         movswq  3(itmp2),itmp3              /* get %rip offset                    */
897         add     itmp2,itmp3                 /* add return address (%rip)          */
898         add     $7,itmp3                    /* add mov instruction size           */
899         mov     v0,(itmp3)                  /* move field address to data segment */
900         jmp     *itmp2                      /* call new patched code              */
901
902 L_asm_codepatcher_exception:
903 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
904         call    builtin_asm_get_exceptionptrptr
905         mov     v0,itmp2
906 #else
907         lea     _exceptionptr,itmp2
908 #endif
909         mov     (itmp2),xptr                /* get the exception pointer          */
910         movl    $0,(itmp2)                  /* clear the exception pointer        */
911
912         pop     xpc                         /* get and remove return address      */
913         sub     $5,xpc                      /* faulting address is ra - 5         */
914         jmp     asm_handle_exception
915
916
917 /* asm_get_putfield ************************************************************
918
919    XXX
920
921    Stack layout:
922      16   return address
923       8   machine code (which is patched back later)
924       0   unresolved field reference
925
926 *******************************************************************************/
927
928 asm_get_putfield:
929         sub     $(17*8),%rsp                /* stack frame (16-byte aligned)      */
930
931         SAVE_ARGUMENT_REGISTERS
932         SAVE_TEMPORARY_REGISTERS
933
934         mov     itmp1,15*8(%rsp)            /* save itmp1 and itmp2               */
935         mov     itmp2,16*8(%rsp)            /* can be used by field instructions  */
936
937         mov     (0+17)*8(%rsp),a0           /* pass unresolved_method pointer     */
938         call    helper_resolve_fieldinfo_offset /* call the helper function       */
939
940         RESTORE_ARGUMENT_REGISTERS
941         RESTORE_TEMPORARY_REGISTERS
942
943         cmp     $-1,v0l                     /* exception thrown? test for -1,     */
944                                             /* because field offset can be 0      */
945         jz      L_asm_codepatcher_exception_with_stack_frame
946
947         mov     (1+17)*8(%rsp),itmp3        /* get machine code                   */
948         mov     (2+17)*8(%rsp),itmp2        /* get return address                 */
949         sub     $5,itmp2                    /* remove size of `call rel32'        */
950         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
951
952         cmpb    $0xf2,(itmp2)               /* test for movsd                     */
953         je      L_asm_get_putfield_float
954         cmpb    $0xf3,(itmp2)               /* test for movss                     */
955         je      L_asm_get_putfield_float
956         cmpb    $0x24,3(itmp2)              /* check for (%rsp) or (%r12)         */
957         je      L_asm_get_putfield_r12_membase
958
959         mov     v0l,3(itmp2)                /* patch field offset                 */
960         jmp     L_asm_get_putfield_normal
961
962 L_asm_get_putfield_float:
963         mov     v0l,5(itmp2)                /* patch field offset (position + 2)  */
964         jmp     L_asm_get_putfield_normal
965                 
966 L_asm_get_putfield_r12_membase:
967         mov     v0l,4(itmp2)                /* patch field offset (position + 1)  */
968
969 L_asm_get_putfield_normal:
970         mov     itmp2,itmp3
971
972         mov     15*8(%rsp),itmp1            /* restore itmp1 and itmp2            */
973         mov     16*8(%rsp),itmp2            /* can be used by field instructions  */
974
975         add     $((3+17)*8),%rsp            /* remove stack frame                 */
976         jmp     *itmp3                      /* call new patched code              */
977
978 L_asm_codepatcher_exception_with_stack_frame:
979 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
980         call    builtin_asm_get_exceptionptrptr
981         mov     %rax,itmp2
982 #else
983         lea     _exceptionptr,itmp2
984 #endif
985         mov     (itmp2),xptr                /* get the exception pointer          */
986         movl    $0,(itmp2)                  /* clear the exception pointer        */
987
988         mov     (2+17)*8(%rsp),xpc          /* get return address                 */
989         sub     $5,xpc                      /* faulting address is ra - 5         */
990         add     $((3+17)*8),%rsp            /* remove stack frame                 */
991         jmp     asm_handle_exception
992
993
994 /* asm_builtin_new *************************************************************
995
996    XXX
997
998    Arguments:
999      a0   contains the class reference
1000
1001 *******************************************************************************/
1002
1003 asm_builtin_new:
1004         sub     $(8*1),%rsp                 /* stack frame (16-byte aligned)      */
1005         call    helper_resolve_classinfo    /* call the helper function           */
1006         add     $(8*1),%rsp                 /* remove stack frame                 */
1007         test    v0,v0                       /* exception thrown?                  */
1008         jz      L_asm_codepatcher_exception
1009
1010         pop     itmp2                       /* get return address                 */
1011         sub     $(3+10+10),itmp2            /* 3 (callq) + 10 (movi) + 10 (movi)  */
1012         mov     v0,2(itmp2)                 /* patch in new classinfo*: 2 (mov)   */
1013
1014         lea     builtin_new,itmp1           /* get address from builtin_new       */
1015         mov     itmp1,12(itmp2)             /* patch back function address        */
1016         jmp     *itmp2                      /* call new patched code              */
1017
1018
1019 /* asm_builtin_newarray ********************************************************
1020
1021    XXX
1022
1023    Arguments:
1024      a1   contains the class reference
1025
1026 *******************************************************************************/
1027
1028 asm_builtin_newarray:
1029         sub     $(8*1),%rsp                 /* stack frame (16-byte aligned)      */
1030         mov     a0,0*8(%rsp)                /* save argument                      */
1031         mov     a1,a0                       /* pass class reference               */
1032         call    helper_resolve_classinfo_vftbl /* call the helper function        */
1033         mov     0*8(%rsp),a0                /* restore argument                   */
1034         add     $(8*1),%rsp                 /* remove stack frame                 */
1035         test    v0,v0                       /* exception thrown?                  */
1036         jz      L_asm_codepatcher_exception
1037
1038         pop     itmp2                       /* get return address                 */
1039         sub     $(3+10+10),itmp2            /* 3 (callq) + 10 (movi) + 10 (movi)  */
1040         mov     v0,2(itmp2)                 /* patch in new vftbl*: 2 (mov)       */
1041
1042         lea     builtin_newarray,itmp1      /* get address from builtin_newarray  */
1043         mov     itmp1,12(itmp2)             /* patch back function address        */
1044         jmp     *itmp2                      /* call new patched code              */
1045
1046
1047 /* asm_builtin_multianewarray **************************************************
1048
1049    XXX
1050
1051    Arguments:
1052      a1   contains the class reference
1053
1054 *******************************************************************************/
1055
1056 asm_builtin_multianewarray:
1057         sub     $(1*8),%rsp                 /* stack frame (16-byte aligned)      */
1058         mov     a1,a0                       /* pass class reference               */
1059         call    helper_resolve_classinfo_vftbl /* call the helper function        */
1060         add     $(1*8),%rsp                 /* remove stack frame                 */
1061         test    v0,v0                       /* exception thrown?                  */
1062         jz      L_asm_codepatcher_exception
1063
1064         pop     itmp2                       /* get return address                 */
1065         sub     $(3+10+3+10+10),itmp2       /* go back to a0 mov                  */
1066         mov     v0,10+2(itmp2)              /* patch in new vftbl*: 10 (movi) + 2 */
1067
1068         lea     builtin_nmultianewarray,itmp1 /* get function address             */
1069         mov     itmp1,10+10+3+2(itmp2)      /* patch back function address        */
1070         jmp     *itmp2                      /* call new patched code              */
1071
1072
1073 /* asm_invokestatic_special ****************************************************
1074
1075    XXX
1076
1077    Stack layout:
1078      16   return address
1079       8   machine code (which is patched back later)
1080       0   unresolved method reference
1081
1082 *******************************************************************************/
1083
1084 asm_invokestatic_special:
1085         sub     $(15*8),%rsp                /* stack frame (16-byte aligned)      */
1086
1087         SAVE_ARGUMENT_REGISTERS
1088
1089         mov     (0+15)*8(%rsp),a0           /* pass unresolved_method pointer     */
1090         call    helper_resolve_methodinfo_stubroutine /* call the helper function */
1091
1092         RESTORE_ARGUMENT_REGISTERS
1093
1094         mov     (1+15)*8(%rsp),itmp3        /* get machine code                   */
1095         add     $((2+15)*8),%rsp            /* remove stack frame, keep ra        */
1096
1097         test    v0,v0                       /* exception thrown?                  */
1098         jz      L_asm_codepatcher_exception
1099
1100         pop     itmp2                       /* get return address                 */
1101         sub     $5,itmp2                    /* remove size of `call rel32'        */
1102         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1103
1104         mov     v0,2(itmp2)                 /* patch stubroutine: 2 (mov)         */
1105         jmp     *itmp2                      /* call new patched code              */
1106
1107
1108 /* asm_invokevirtual ***********************************************************
1109
1110    XXX
1111
1112    Stack layout:
1113      16   return address
1114       8   machine code (which is patched back later)
1115       0   unresolved method reference
1116
1117 *******************************************************************************/
1118
1119 asm_invokevirtual:
1120         sub     $(15*8),%rsp                /* stack frame (16-byte aligned)      */
1121
1122         SAVE_ARGUMENT_REGISTERS
1123
1124         mov     (0+15)*8(%rsp),a0           /* pass unresolved_method pointer     */
1125         call    helper_resolve_methodinfo_vftblindex /* call the helper function  */
1126
1127         RESTORE_ARGUMENT_REGISTERS
1128
1129         mov     (1+15)*8(%rsp),itmp3        /* get machine code                   */
1130         add     $((2+15)*8),%rsp            /* remove stack frame, keep ra        */
1131
1132         cmp     $-1,v0l                     /* exception thrown? test for -1,     */
1133                                             /* because vftblindex can be 0        */
1134         je      L_asm_codepatcher_exception
1135
1136         pop     itmp2                       /* get return address                 */
1137         sub     $5,itmp2                    /* remove size of `call rel32'        */
1138         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1139
1140         shl     $3,v0l                      /* sizeof(methodptr) * lm->vftblindex */
1141         add     $offvftbltable,v0l          /* + OFFSET(vftbl_t, table[0])        */
1142         movl    v0l,3+3(itmp2)              /* patch 32 bit offset: 3 (mov) + 3   */
1143         jmp     *itmp2                      /* call new patched code              */
1144
1145
1146 /* asm_invokeinterface *********************************************************
1147
1148    XXX
1149
1150    Stack layout:
1151      16   return address
1152       8   machine code (which is patched back later)
1153       0   unresolved method reference
1154
1155 *******************************************************************************/
1156
1157 asm_invokeinterface:
1158         sub     $(15*8),%rsp                /* stack frame (16-byte aligned)      */
1159
1160         SAVE_ARGUMENT_REGISTERS
1161
1162         mov     (0+15)*8(%rsp),a0           /* pass unresolved_method pointer     */
1163         call    helper_resolve_methodinfo   /* call the helper function           */
1164
1165         RESTORE_ARGUMENT_REGISTERS
1166
1167         mov     (1+15)*8(%rsp),itmp3        /* get machine code                   */
1168         add     $((2+15)*8),%rsp            /* remove stack frame, keep ra        */
1169
1170         test    v0,v0                       /* exception thrown?                  */
1171         jz      L_asm_codepatcher_exception
1172
1173         pop     itmp2                       /* get return address                 */
1174         sub     $5,itmp2                    /* remove size of `call rel32'        */
1175         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1176
1177         mov     offmethodclass(v0),itmp3    /* ci = lm->class                     */
1178         mov     offclassindex(itmp3),itmp3l /* ci->index (s4)                     */
1179         shl     $3,itmp3l                   /* * sizeof(methodptr)                */
1180         neg     itmp3l                      /* OFFSET(vftbl_t, interfacetable[0]) */
1181                                             /* XXX the offset is always 0!!!      */
1182         mov     itmp3l,3+3(itmp2)           /* patch 32 bit offset: 3 (mov) + 3   */
1183
1184         mov     offmethodclass(v0),itmp3    /* ci = lm->class                     */
1185         sub     offclassmethods(itmp3),v0   /* lm - ci->methods                   */
1186
1187         push    %rdx
1188         xor     %rdx,%rdx
1189         mov     $sizemethodinfo,itmp3l
1190         idiv    itmp3l
1191         pop     %rdx
1192
1193         shl     $3,v0                       /*  * sizeof(methodptr)               */
1194         mov     v0l,3+7+3(itmp2)            /* patch 32bit offset: 3 + 7 (mov) + 3*/
1195         jmp     *itmp2                      /* call new patched code              */
1196
1197
1198 /* asm_checkcast_instanceof_flags **********************************************
1199
1200    XXX
1201
1202    Stack layout:
1203      16   return address
1204       8   machine code (which is patched back later)
1205       0   unresolved field reference
1206
1207 *******************************************************************************/
1208
1209 asm_checkcast_instanceof_flags:
1210         sub     $(17*8),%rsp                /* stack frame (16-byte aligned)      */
1211
1212         SAVE_ARGUMENT_REGISTERS
1213         SAVE_TEMPORARY_REGISTERS
1214
1215         mov     itmp1,15*8(%rsp)            /* save itmp1 and itmp2               */
1216         mov     itmp2,16*8(%rsp)            /* can be used by CHECKCAST           */
1217
1218         mov     (0+17)*8(%rsp),a0           /* pass unresolved_method pointer     */
1219         call    helper_resolve_classinfo_flags /* call the helper function        */
1220
1221         RESTORE_ARGUMENT_REGISTERS
1222         RESTORE_TEMPORARY_REGISTERS
1223
1224         cmp     $-1,v0l                     /* exception thrown? test for -1,     */
1225                                             /* because class flags can be 0       */
1226         jz      L_asm_codepatcher_exception_with_stack_frame
1227
1228         mov     (1+17)*8(%rsp),itmp3        /* get machine code                   */
1229         mov     (2+17)*8(%rsp),itmp2        /* get return address                 */
1230         sub     $5,itmp2                    /* remove size of `call rel32'        */
1231         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1232
1233         mov     v0l,2(itmp2)                /* patch super->flags                 */
1234
1235         mov     itmp2,itmp3                 /* move return address                */
1236         mov     15*8(%rsp),itmp1            /* restore itmp1 and itmp2            */
1237         mov     16*8(%rsp),itmp2            /* can be used by field instructions  */
1238         add     $((3+17)*8),%rsp            /* remove stack frame                 */
1239         jmp     *itmp3                      /* call new patched code              */
1240
1241
1242 /* asm_checkcast_instanceof_interface ******************************************
1243
1244    XXX
1245
1246    Stack layout:
1247      16   return address
1248       8   machine code (which is patched back later)
1249       0   unresolved field reference
1250
1251 *******************************************************************************/
1252
1253 asm_checkcast_instanceof_interface:
1254         sub     $(17*8),%rsp                /* stack frame (16-byte aligned)      */
1255
1256         SAVE_ARGUMENT_REGISTERS
1257         SAVE_TEMPORARY_REGISTERS
1258
1259         mov     itmp1,15*8(%rsp)            /* save itmp1 and itmp2               */
1260         mov     itmp2,16*8(%rsp)            /* can be used by CHECKCAST           */
1261
1262         mov     (0+17)*8(%rsp),a0           /* pass unresolved_method pointer     */
1263         call    helper_resolve_classinfo_index /* call the helper function        */
1264
1265         RESTORE_ARGUMENT_REGISTERS
1266         RESTORE_TEMPORARY_REGISTERS
1267
1268         cmp     $-1,v0l                     /* exception thrown? test for -1,     */
1269                                             /* because class index can be 0       */
1270         jz      L_asm_codepatcher_exception_with_stack_frame
1271
1272         mov     (1+17)*8(%rsp),itmp3        /* get machine code                   */
1273         mov     (2+17)*8(%rsp),itmp2        /* get return address                 */
1274         sub     $5,itmp2                    /* remove size of `call rel32'        */
1275         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1276
1277         mov     v0l,7+3(itmp2)              /* patch super->index                 */
1278
1279         shl     $3,v0l                      /* super->index * sizeof(methodptr)   */
1280         neg     v0l                         /* OFFSET(vftbl_t, interfacetable[0]) */
1281                                             /* XXX the offset is always 0!!!      */
1282         mov     v0l,7+7+3+6+3(itmp2)        /* patch calculated value             */
1283
1284         mov     itmp2,itmp3                 /* move return address                */
1285         mov     15*8(%rsp),itmp1            /* restore itmp1 and itmp2            */
1286         mov     16*8(%rsp),itmp2            /* can be used by field instructions  */
1287         add     $((3+17)*8),%rsp            /* remove stack frame                 */
1288         jmp     *itmp3                      /* call new patched code              */
1289
1290
1291 /* asm_checkcast_class *********************************************************
1292
1293    XXX
1294
1295    Stack layout:
1296      16   return address
1297       8   machine code (which is patched back later)
1298       0   unresolved field reference
1299
1300 *******************************************************************************/
1301
1302 asm_checkcast_class:
1303         sub     $(17*8),%rsp                /* stack frame (16-byte aligned)      */
1304
1305         SAVE_ARGUMENT_REGISTERS
1306         SAVE_TEMPORARY_REGISTERS
1307
1308         mov     itmp1,15*8(%rsp)            /* save itmp1 and itmp2               */
1309         mov     itmp2,16*8(%rsp)            /* can be used by CHECKCAST           */
1310
1311         mov     (0+17)*8(%rsp),a0           /* pass unresolved_method pointer     */
1312         call    helper_resolve_classinfo_vftbl /* call the helper function        */
1313
1314         RESTORE_ARGUMENT_REGISTERS
1315         RESTORE_TEMPORARY_REGISTERS
1316
1317         test    v0,v0                       /* exception thrown?                  */
1318         jz      L_asm_codepatcher_exception_with_stack_frame
1319
1320         mov     (1+17)*8(%rsp),itmp3        /* get machine code                   */
1321         mov     (2+17)*8(%rsp),itmp2        /* get return address                 */
1322         sub     $5,itmp2                    /* remove size of `call rel32'        */
1323         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1324
1325         mov     v0,2(itmp2)                 /* patch super->vftbl                 */
1326         mov     v0,10+7+7+3+2(itmp2)        /* patch super->vftbl                 */
1327
1328         mov     itmp2,itmp3                 /* move return address                */
1329         mov     15*8(%rsp),itmp1            /* restore itmp1 and itmp2            */
1330         mov     16*8(%rsp),itmp2
1331         add     $((3+17)*8),%rsp            /* remove stack frame                 */
1332         jmp     *itmp3                      /* call new patched code              */
1333
1334
1335 /* asm_instanceof_class ********************************************************
1336
1337    XXX
1338
1339    Stack layout:
1340      16   return address
1341       8   machine code (which is patched back later)
1342       0   unresolved field reference
1343
1344 *******************************************************************************/
1345
1346 asm_instanceof_class:
1347         sub     $(17*8),%rsp                /* stack frame (16-byte aligned)      */
1348
1349         SAVE_ARGUMENT_REGISTERS
1350         SAVE_TEMPORARY_REGISTERS
1351
1352         mov     itmp1,15*8(%rsp)            /* save itmp1 and itmp2               */
1353         mov     itmp2,16*8(%rsp)            /* can be used by INSTANCEOF          */
1354
1355         mov     (0+17)*8(%rsp),a0           /* pass unresolved_method pointer     */
1356         call    helper_resolve_classinfo_vftbl /* call the helper function        */
1357
1358         RESTORE_ARGUMENT_REGISTERS
1359         RESTORE_TEMPORARY_REGISTERS
1360
1361         test    v0,v0                       /* exception thrown?                  */
1362         jz      L_asm_codepatcher_exception_with_stack_frame
1363
1364         mov     (1+17)*8(%rsp),itmp3        /* get machine code                   */
1365         mov     (2+17)*8(%rsp),itmp2        /* get return address                 */
1366         sub     $5,itmp2                    /* remove size of `call rel32'        */
1367         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
1368
1369         mov     v0,2(itmp2)                 /* patch super->vftbl                 */
1370
1371         mov     itmp2,itmp3                 /* move return address                */
1372         mov     15*8(%rsp),itmp1            /* restore itmp1 and itmp2            */
1373         mov     16*8(%rsp),itmp2
1374         add     $((3+17)*8),%rsp            /* remove stack frame                 */
1375         jmp     *itmp3                      /* call new patched code              */
1376
1377
1378 /* asm_check_clinit ************************************************************
1379
1380    DOCUMENT ME!!!
1381
1382    Stack layout:
1383      16   return address
1384       8   machine code (which is patched back later)
1385       0   classinfo pointer
1386
1387 *******************************************************************************/
1388
1389 asm_check_clinit:
1390         mov     0*8(%rsp),itmp1             /* get classinfo pointer              */
1391         mov     offclassinit(itmp1),itmp2l  /* get initialized flag (int)         */
1392         test    itmp2l,itmp2l
1393         jnz     L_asm_check_clinit_is_initialized
1394
1395         sub     $(15*8),%rsp                /* keep stack 16-byte aligned         */
1396
1397         SAVE_ARGUMENT_REGISTERS
1398         SAVE_TEMPORARY_REGISTERS
1399
1400         mov     (0+15)*8(%rsp),a0           /* pass classinfo pointer             */
1401         call    initialize_class            /* call class initialize function     */
1402         
1403         RESTORE_ARGUMENT_REGISTERS
1404         RESTORE_TEMPORARY_REGISTERS
1405
1406         add     $(15*8),%rsp                /* remove stack frame, keep ra        */
1407
1408         test    v0,v0                       /* exception thrown?                  */
1409         je      L_asm_check_clinit_exception
1410
1411 L_asm_check_clinit_is_initialized:
1412         add     $(1*8),%rsp                 /* remove classinfo pointer           */
1413         pop     itmp3                       /* get machine code                   */
1414         pop     itmp2                       /* get return address                 */
1415         sub     $5,itmp2                    /* remove size of `call rel32'        */
1416         mov     itmp3,(itmp2)               /* patch back in 8 bytes              */
1417         jmp     *itmp2                      /* jump to patched code an execute it */
1418
1419 L_asm_check_clinit_exception:
1420 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1421         call    builtin_asm_get_exceptionptrptr
1422         mov     v0,itmp2
1423 #else
1424         lea     _exceptionptr,itmp2
1425 #endif
1426         mov     (itmp2),xptr                /* get the exception pointer          */
1427         movl    $0,(itmp2)                  /* clear the exception pointer        */
1428
1429         add     $(2*8),%rsp                 /* remove stack frame, keep ra        */
1430         pop     xpc                         /* delete return address              */
1431         sub     $5,xpc                      /* faulting address is ra - 5         */
1432         jmp     asm_handle_exception
1433                 
1434
1435 /********************* function asm_builtin_monitorenter ***********************
1436 *                                                                              *
1437 *   Does null check and calls monitorenter or throws an exception              *
1438 *                                                                              *
1439 *******************************************************************************/
1440
1441 #if defined(USE_THREADS)
1442 asm_builtin_monitorenter:
1443         test    %rdi,%rdi
1444         je      nb_monitorenter             /* if (null) throw exception          */
1445         jmp     builtin_monitorenter        /* else call builtin_monitorenter     */
1446
1447 nb_monitorenter:
1448         call    new_nullpointerexception
1449         pop     %r10                        /* delete return address              */
1450         sub     $3,%r10                     /* faulting address is ra - 3         */
1451         jmp     asm_handle_exception
1452 #endif
1453                 
1454
1455 /********************* function asm_builtin_monitorexit ************************
1456 *                                                                              *
1457 *   Does null check and calls monitorexit or throws an exception               *
1458 *                                                                              *
1459 *******************************************************************************/
1460
1461 #if defined(USE_THREADS)
1462 asm_builtin_monitorexit:
1463         test    %rdi,%rdi
1464         je      nb_monitorexit              /* if (null) throw exception          */
1465         jmp     builtin_monitorexit         /* else call builtin_monitorenter     */
1466
1467 nb_monitorexit:
1468         call    new_nullpointerexception
1469         pop     %r10                        /* delete return address              */
1470         sub     $3,%r10                     /* faulting address is ra - 3         */
1471         jmp     asm_handle_exception
1472 #endif
1473
1474
1475 /********************* function asm_builtin_x2x ********************************
1476 *                                                                              *
1477 *   Wrapper functions for float to int corner cases                            *
1478 *                                                                              *
1479 *******************************************************************************/
1480
1481 asm_builtin_f2i:
1482         sub     $(14*8),%rsp
1483         
1484         SAVE_ARGUMENT_REGISTERS
1485         
1486         movq    %xmm8,%xmm0
1487         call    builtin_f2i
1488         
1489         RESTORE_ARGUMENT_REGISTERS
1490         
1491         add     $(14*8),%rsp
1492         ret
1493
1494
1495 asm_builtin_f2l:
1496         sub     $(14*8),%rsp
1497         
1498         SAVE_ARGUMENT_REGISTERS
1499         
1500         movq    %xmm8,%xmm0
1501         call    builtin_f2l
1502         
1503         RESTORE_ARGUMENT_REGISTERS
1504         
1505         add     $(14*8),%rsp
1506         ret
1507
1508
1509 asm_builtin_d2i:
1510         sub     $(14*8),%rsp
1511         
1512         SAVE_ARGUMENT_REGISTERS
1513         
1514         movq    %xmm8,%xmm0
1515         call    builtin_d2i
1516         
1517         RESTORE_ARGUMENT_REGISTERS
1518         
1519         add     $(14*8),%rsp
1520         ret
1521
1522
1523 asm_builtin_d2l:
1524         sub     $(14*8),%rsp
1525         
1526         SAVE_ARGUMENT_REGISTERS
1527         
1528         movq    %xmm8,%xmm0
1529         call    builtin_d2l
1530         
1531         RESTORE_ARGUMENT_REGISTERS
1532         
1533         add     $(14*8),%rsp
1534         ret
1535
1536
1537 /* asm_builtin_checkarraycast **************************************************
1538
1539    Does the cast check and eventually throws an exception.
1540
1541 *******************************************************************************/
1542
1543 asm_builtin_checkarraycast:
1544         sub     $24,%rsp                    /* keep stack 16-byte aligned         */
1545         mov     %rdi,(%rsp)                 /* save object pointer                */
1546         call    builtin_checkarraycast      /* builtin_checkarraycast             */
1547         test    %rax,%rax                   /* if (false) throw exception         */
1548         je      nb_carray_throw
1549         mov     (%rsp),%rax                 /* return object pointer              */
1550         add     $24,%rsp                    /* free stack space                   */
1551         ret
1552
1553 nb_carray_throw:
1554         call    new_classcastexception
1555         add     $24,%rsp
1556         pop     %r10                        /* delete return address              */
1557         sub     $3,%r10                     /* faulting address is ra - 3         */
1558         jmp     asm_handle_exception
1559
1560                 
1561 /* asm_builtin_aastore *********************************************************
1562
1563    Checks if the object can be stored in the given array and stores the
1564    address if it's possible. This function can also throw some exceptions.
1565
1566 *******************************************************************************/
1567
1568 asm_builtin_aastore:
1569         sub     $(3*8),%rsp             /* allocate stack space                   */
1570         test    %rdi,%rdi               /* if null pointer throw exception        */
1571         je      nb_aastore_null
1572
1573         movl    offarraysize(%rdi),%eax /* load size                              */
1574         cmpl    %eax,%esi               /* do bound check                         */
1575         jae     nb_aastore_bound        /* if out of bounds throw exception       */
1576
1577         shl     $3,%rsi                 /* index * 8                              */
1578         mov     %rdi,%r10
1579         add     %rsi,%r10               /* add index * 8 to arrayref              */
1580
1581         mov     %r10,(%rsp)             /* save store position                    */
1582         mov     %rdx,8(%rsp)            /* save object                            */
1583
1584         mov     %rdx,%rsi               /* object is second argument              */
1585         call    builtin_canstore        /* builtin_canstore(arrayref,object)      */
1586         test    %rax,%rax               /* if (false) throw exception             */
1587         je      nb_aastore_throw
1588
1589         mov     (%rsp),%r10             /* restore store position                 */
1590         mov     8(%rsp),%rdx            /* restore object                         */
1591         mov     %rdx,offobjarrdata(%r10)/* store objectptr in array               */
1592         add     $(3*8),%rsp             /* free stack space                       */
1593         ret
1594
1595 nb_aastore_null:
1596         call    new_nullpointerexception
1597         add     $24,%rsp
1598         pop     %r10                    /* delete return address                  */
1599         sub     $3,%r10                 /* faulting address is return adress - 3  */
1600         jmp     asm_handle_exception
1601
1602 nb_aastore_bound:
1603         mov     %rsi,%rdi               /* move index into a0                     */
1604         call    new_arrayindexoutofboundsexception
1605         add     $24,%rsp
1606         pop     %r10                    /* delete return address                  */
1607         sub     $3,%r10                 /* faulting address is return adress - 3  */
1608         jmp     asm_handle_exception
1609                 
1610 nb_aastore_throw:
1611         call    new_arraystoreexception
1612         add     $24,%rsp
1613         pop     %r10                    /* delete return address                  */
1614         sub     $3,%r10                 /* faulting address is return adress - 3  */
1615         jmp     asm_handle_exception
1616
1617                 
1618 /******************* function asm_initialize_thread_stack **********************
1619 *                                                                              *
1620 * initialized a thread stack                                                   *
1621 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
1622 *                                                                              *
1623 *******************************************************************************/
1624
1625 asm_initialize_thread_stack:
1626         sub     $(7*8),%rsi
1627
1628         xor     %r10,%r10
1629         mov     %r10,0*8(%rsi)
1630         mov     %r10,1*8(%rsi)
1631         mov     %r10,2*8(%rsi)
1632         mov     %r10,3*8(%rsi)
1633         mov     %r10,4*8(%rsi)
1634         mov     %r10,5*8(%rsi)
1635
1636         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
1637         mov     %rsi,%rax               /* return restorepoint in %rax        */
1638         ret
1639
1640
1641 /******************* function asm_perform_threadswitch *************************
1642 *                                                                              *
1643 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
1644 *                                                                              *
1645 *   performs a threadswitch                                                    *
1646 *                                                                              *
1647 *******************************************************************************/
1648
1649 asm_perform_threadswitch:
1650         sub     $(7*8),%rsp             /* allocate stack frame               */
1651
1652         mov     %rbx,0*8(%rsp)
1653         mov     %rbp,1*8(%rsp)
1654         mov     %r12,2*8(%rsp)
1655         mov     %r13,3*8(%rsp)
1656         mov     %r14,4*8(%rsp)
1657         mov     %r15,5*8(%rsp)
1658
1659         mov     7*8(%rsp),%rax                  /* save current return address        */
1660         mov     %rax,6*8(%rsp)
1661
1662         mov     %rsp,(%rdi)                     /* first argument **from              */
1663         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
1664
1665         mov     (%rsi),%rsp                     /* load new stack pointer             */
1666
1667         mov     0*8(%rsp),%rbx
1668         mov     1*8(%rsp),%rbp
1669         mov     2*8(%rsp),%r12
1670         mov     3*8(%rsp),%r13
1671         mov     4*8(%rsp),%r14
1672         mov     5*8(%rsp),%r15
1673
1674         mov     6*8(%rsp),%rax          /* restore return address             */
1675         add     $(7*8),%rsp             /* free stack frame                   */
1676         mov     %rax,(%rsp)
1677         ret
1678                 
1679
1680 /********************* function asm_switchstackandcall *************************
1681 *                                                                              *
1682 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
1683 *                                      void *p);                                       *
1684 *                                                                              *
1685 *   Switches to a new stack, calls a function and switches back.               *
1686 *       a0 (%rdi)     new stack pointer                                        *
1687 *       a1 (%rsi)     function pointer                                         *
1688 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
1689 *       a3 (%rcx)     pointer to user data, is passed to the function          *
1690 *                                                                              *
1691 *******************************************************************************/
1692
1693 asm_switchstackandcall:
1694         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
1695         sub     $16,%rdi                                /* allocate new stack                 */
1696
1697         mov     8(%rsp),%rax                    /* save return address on new stack   */
1698         mov     %rax,(%rdi)
1699         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
1700         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
1701
1702         mov     %rdi,%rsp                               /* switch to new stack                */
1703
1704         mov     %rcx,%rdi                       /* pass pointer                       */
1705         call    *%rsi                                   /* and call function                  */
1706
1707         mov     (%rsp),%r10                             /* load return address                */
1708         mov     8(%rsp),%rsp                    /* switch to old stack                */
1709         add     $(1*8),%rsp             /* free stack space                   */
1710         mov     %r10,(%rsp)             /* write return adress                */
1711         ret
1712
1713
1714 asm_getclassvalues_atomic:
1715 _crit_restart2:
1716 _crit_begin2:
1717         movl    offbaseval(a0),itmp1l
1718         movl    offdiffval(a0),itmp2l
1719         movl    offbaseval(a1),itmp3l
1720 _crit_end2:
1721         movl    itmp1l,offcast_super_baseval(a2)
1722         movl    itmp2l,offcast_super_diffval(a2)
1723         movl    itmp3l,offcast_sub_baseval(a2)
1724         ret
1725
1726         .data
1727                 
1728 asm_criticalsections:
1729 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1730         .quad   _crit_begin1
1731         .quad   _crit_end1
1732         .quad   _crit_restart1
1733         .quad   _crit_begin2
1734         .quad   _crit_end2
1735         .quad   _crit_restart2
1736 #endif
1737         .quad 0
1738
1739                                 
1740 /*
1741  * These are local overrides for various environment variables in Emacs.
1742  * Please do not remove this and leave it at the end of the file, where
1743  * Emacs will automagically detect them.
1744  * ---------------------------------------------------------------------
1745  * Local variables:
1746  * mode: asm
1747  * indent-tabs-mode: t
1748  * c-basic-offset: 4
1749  * tab-width: 4
1750  * End:
1751  */