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