* src/vm/class.c: Don't initialize classes to NULL.
[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, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    Changes: Edwin Steiner
32
33    $Id: asmpart.S 4690 2006-03-27 11:37:46Z twisti $
34
35 */
36
37
38 #include "config.h"
39
40 #include "md-abi.h"
41 #include "md-asm.h"
42
43 #include "vm/jit/abi.h"
44 #include "vm/jit/x86_64/arch.h"
45 #include "vm/jit/x86_64/offsets.h"
46
47 #include "vm/jit/methodheader.h"
48
49
50         .text
51
52
53 /* exported functions and variables *******************************************/
54
55         .globl asm_vm_call_method
56         .globl asm_vm_call_method_int
57         .globl asm_vm_call_method_long
58         .globl asm_vm_call_method_float
59         .globl asm_vm_call_method_double
60
61         .globl asm_call_jit_compiler
62         .globl asm_handle_exception
63         .globl asm_handle_nat_exception
64
65         .globl asm_wrapper_patcher
66
67         .globl asm_replacement_out
68         .globl asm_replacement_in
69
70         .globl asm_builtin_f2i
71         .globl asm_builtin_f2l
72         .globl asm_builtin_d2i
73         .globl asm_builtin_d2l
74
75         .globl asm_perform_threadswitch
76         .globl asm_initialize_thread_stack
77         .globl asm_switchstackandcall
78         .globl asm_criticalsections
79         .globl asm_getclassvalues_atomic
80
81
82 /********************* function asm_calljavafunction ***************************
83 *                                                                              *
84 *   This function calls a Java-method (which possibly needs compilation)       *
85 *   with up to 4 address parameters.                                           *
86 *                                                                              *
87 *   This functions calls the JIT-compiler which eventually translates the      *
88 *   method into machine code.                                                  *
89 *                                                                              *
90 *   C-prototype:                                                               *
91 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
92 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
93 *                                                                              *
94 *******************************************************************************/
95
96         .align  8
97
98         .quad   0                           /* catch type all                     */
99         .quad   calljava_xhandler2          /* handler pc                         */
100         .quad   calljava_xhandler2          /* end pc                             */
101         .quad   L_asm_vm_call_method        /* start pc                           */
102         .long   1                           /* extable size                       */
103         .long   0                                                                                                                        
104         .quad   0                           /* line number table  start           */
105         .quad   0                           /* line number table  size            */
106         .long   0                                                                                                                        
107         .long   0                           /* fltsave                            */
108         .long   0                           /* intsave                            */
109         .long   0                           /* isleaf                             */
110         .long   0                           /* IsSync                             */
111         .long   24                          /* frame size                         */
112         .quad   0                           /* method pointer (pointer to name)   */
113
114 asm_vm_call_method:
115 asm_vm_call_method_int:
116 asm_vm_call_method_long:
117 asm_vm_call_method_float:
118 asm_vm_call_method_double:
119 L_asm_vm_call_method:                   /* required for PIC code              */
120         sub     $(7*8),sp                   /* keep stack 16-byte aligned         */
121         mov     %rbx,0*8(sp)                /* %rbx is not a callee saved in cacao*/
122         mov     s0,1*8(sp)
123         mov     s1,2*8(sp)
124         mov     s2,3*8(sp)
125         mov     s3,4*8(sp)
126         mov     s4,5*8(sp)
127
128         mov     a0,itmp1                    /* move method pointer for compiler   */
129         xor     %rbp,%rbp                   /* set argument stack frame to zero   */
130
131         test    a1,a1                       /* maybe we have no args...           */
132         jle     L_copy_done
133
134         mov     a1,itmp3                    /* arg count                          */
135         mov     a2,itmp2                    /* pointer to arg block               */
136
137         mov     itmp2,%r14                  /* save argument block pointer        */
138         mov     itmp3,%r15                  /* save argument count                */
139
140         sub     $sizevmarg,itmp2            /* initialize pointer (smaller code)  */
141         add     $1,itmp3                    /* initialize argument count          */
142         xor     %r12,%r12                   /* initialize integer argument counter*/
143         xor     %r13,%r13                   /* initialize float argument counter  */
144
145 L_register_copy:
146         add     $sizevmarg,itmp2            /* goto next argument block           */
147         dec     itmp3                       /* argument count - 1                 */
148         jz      L_register_copy_done
149         andb    $0x02,offvmargtype(itmp2)   /* is this a float/double type?       */
150         jnz     L_register_handle_float     /* yes, handle it                     */
151
152         cmp     $INT_ARG_CNT,%r12           /* are we out of integer argument     */
153         je      L_register_copy             /* register? yes, next loop           */
154
155         lea     jumptable_integer(%rip),%rbp
156         mov     0(%rbp,%r12,8),%rbx
157         inc     %r12                      /* integer argument counter + 1         */
158         jmp     *%rbx
159
160 L_register_handle_float:
161         cmp     $FLT_ARG_CNT,%r13         /* are we out of float argument         */
162         je      L_register_copy           /* register? yes, next loop             */
163
164         lea     jumptable_float(%rip),%rbp
165         mov     0(%rbp,%r13,8),%rbx
166         inc     %r13                      /* float argument counter + 1           */
167         jmp     *%rbx
168         
169 L_register_copy_done:
170         mov     %r15,%rbp                 /* calculate remaining arguments        */
171         sub     %r12,%rbp                 /* - integer arguments in registers     */
172         sub     %r13,%rbp                 /* - float arguments in registers       */
173         jle     L_copy_done               /* are all assigned to registers?       */
174
175         and     $0xfffffffffffffffe,%rbp  /* keep stack 16-byte aligned           */
176         shl     $3,%rbp                   /* calculate stack size                 */
177         sub     %rbp,sp                   /* stack frame for arguments            */
178         mov     sp,%rbx                   /* use %rbx as temp sp                  */
179
180         sub     $sizevmarg,%r14           /* initialize pointer (smaller code)    */
181         add     $1,%r15                   /* initialize argument count            */
182                 
183 L_stack_copy_loop:
184         add     $sizevmarg,%r14           /* goto next argument block             */
185         dec     %r15                      /* are there any arguments left?        */
186         jz      L_copy_done               /* no test needed after dec             */
187
188         andb    $0x02,offvmargtype(%r14)    /* is this a float/double type?       */
189         jnz     L_stack_handle_float
190         dec     %r12                        /* arguments assigned to registers    */
191         jge     L_stack_copy_loop
192         jmp     L_stack_copy
193
194 L_stack_handle_float:
195         dec     %r13                        /* arguments assigned to registers    */
196         jge     L_stack_copy_loop
197
198 L_stack_copy:
199         mov     offvmargdata(%r14),itmp3    /* copy s8 argument onto stack        */
200         mov     itmp3,0(%rbx)
201         add     $8,%rbx                     /* increase sp to next argument       */
202         jmp     L_stack_copy_loop
203
204 L_copy_done:
205                                             /* itmp1 still contains method pointer*/
206         lea     L_asm_call_jit_compiler(%rip),itmp3
207         call    *itmp3                      /* call JIT compiler                  */
208
209         add     bp,sp                       /* remove argument stack frame if any */
210
211 L_asm_vm_call_method_return:
212         mov     0*8(sp),%rbx                /* restore callee saved registers     */
213         mov     1*8(sp),s0
214         mov     2*8(sp),s1
215         mov     3*8(sp),s2
216         mov     4*8(sp),s3
217         mov     5*8(sp),s4
218         add     $(7*8),sp                   /* free stack space                   */
219         ret
220                 
221 calljava_xhandler2:
222 #if !defined(NDEBUG)
223         mov     xptr,a0                     /* pass exception pointer             */
224         call    builtin_throw_exception@PLT
225 #endif
226         xor     v0,v0                       /* return NULL                        */
227         jmp     L_asm_vm_call_method_return
228
229
230 jumptable_integer:
231         .quad   handle_a0
232         .quad   handle_a1
233         .quad   handle_a2
234         .quad   handle_a3
235         .quad   handle_a4
236         .quad   handle_a5
237
238 handle_a0:
239         mov     offvmargdata(itmp2),a0
240         jmp     L_register_copy
241 handle_a1:
242         mov     offvmargdata(itmp2),a1
243         jmp     L_register_copy
244 handle_a2:
245         mov     offvmargdata(itmp2),a2
246         jmp     L_register_copy
247 handle_a3:
248         mov     offvmargdata(itmp2),a3
249         jmp     L_register_copy
250 handle_a4:
251         mov     offvmargdata(itmp2),a4
252         jmp     L_register_copy
253 handle_a5:
254         mov     offvmargdata(itmp2),a5
255         jmp     L_register_copy
256
257
258 jumptable_float:
259         .quad   handle_fa0
260         .quad   handle_fa1
261         .quad   handle_fa2
262         .quad   handle_fa3
263         .quad   handle_fa4
264         .quad   handle_fa5
265         .quad   handle_fa6
266         .quad   handle_fa7
267
268 handle_fa0:
269         movq    offvmargdata(itmp2),fa0
270         jmp     L_register_copy
271 handle_fa1:
272         movq    offvmargdata(itmp2),fa1
273         jmp     L_register_copy
274 handle_fa2:
275         movq    offvmargdata(itmp2),fa2
276         jmp     L_register_copy
277 handle_fa3:
278         movq    offvmargdata(itmp2),fa3
279         jmp     L_register_copy
280 handle_fa4:
281         movq    offvmargdata(itmp2),fa4
282         jmp     L_register_copy
283 handle_fa5:
284         movq    offvmargdata(itmp2),fa5
285         jmp     L_register_copy
286 handle_fa6:
287         movq    offvmargdata(itmp2),fa6
288         jmp     L_register_copy
289 handle_fa7:
290         movq    offvmargdata(itmp2),fa7
291         jmp     L_register_copy
292
293
294 /****************** function asm_call_jit_compiler *****************************
295 *                                                                              *
296 *   invokes the compiler for untranslated JavaVM methods.                      *
297 *                                                                              *
298 *   Register R0 contains a pointer to the method info structure (prepared      *
299 *   by createcompilerstub). Using the return address in R26 and the            *
300 *   offset in the LDA instruction or using the value in methodptr R28 the      *
301 *   patching address for storing the method address can be computed:           *
302 *                                                                              *
303 *   method address was either loaded using                                     *
304 *                                                                              *
305 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
306 *   i386_call_reg(REG_ITMP2)                                                   *
307 *                                                                              *
308 *   or                                                                         *
309 *                                                                              *
310 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
311 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
312 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
313 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
314 *   i386_call_reg(REG_ITMP1)                                                   *
315 *                                                                              *
316 *   in the static case the method pointer can be computed using the            *
317 *   return address and the lda function following the jmp instruction          *
318 *                                                                              *
319 *******************************************************************************/
320
321 asm_call_jit_compiler:
322 L_asm_call_jit_compiler:                /* required for PIC code              */
323                                             /* keep stack 16-byte aligned         */
324         sub     $((3+ARG_CNT)*8+sizestackframeinfo),sp
325
326         mov     t0,0*8(sp)                  /* save register                      */
327
328         mov     (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address  */
329         mov     -1(itmp3),%bl               /* get function code                  */
330         cmp     $0xd2,%bl                   /* called with `call *REG_ITMP2'?     */
331         jne     L_not_static_special
332
333         sub     $11,itmp3                   /* calculate address of immediate     */
334         jmp     L_call_jit_compile
335                 
336 L_not_static_special:
337         cmp     $0xd0,%bl                   /* called with `call *REG_ITMP1'      */
338         jne     L_not_virtual_interface
339                 
340         sub     $7,itmp3                    /* calculate address of offset        */
341         mov     (itmp3),itmp3l              /* get offset (32-bit)                */
342         add     itmp2,itmp3                 /* add base address to get method addr*/
343         jmp     L_call_jit_compile
344
345 L_not_virtual_interface:                /* a call from asm_calljavamethod     */
346         xor     itmp3,itmp3
347                 
348 L_call_jit_compile:
349         mov     0*8(sp),t0                  /* restore register                   */
350         mov     itmp3,0*8(sp)               /* save address for method pointer    */
351         mov     itmp1,1*8(sp)               /* save method pointer                */
352
353         SAVE_ARGUMENT_REGISTERS(3)
354
355         mov     sp,a0                       /* create stackframe info             */
356         add     $((3+ARG_CNT)*8),a0         /* pass sfi                           */
357         xor     a1,a1                       /* if pv is NULL, use findmethod      */
358         mov     sp,a2                       /* pass java sp                       */
359         add     $((1+3+ARG_CNT)*8+sizestackframeinfo),a2
360                                             /* pass ra to java function           */
361         mov     ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3
362         mov     a3,a4                       /* xpc is equal to ra                 */
363         call    stacktrace_create_extern_stackframeinfo@PLT
364
365         mov     1*8(sp),a0                  /* pass method pointer                */
366         call    jit_compile@PLT
367         mov     v0,1*8(sp)                  /* save return value                  */
368
369         mov     sp,a0                       /* remove stackframe info             */
370         add     $((3+ARG_CNT)*8),a0         /* pass sfi                           */
371         call    stacktrace_remove_stackframeinfo@PLT
372
373         mov     0*8(sp),itmp3               /* restore address for method pointer */
374         mov     1*8(sp),v0                  /* restore return value               */
375
376         RESTORE_ARGUMENT_REGISTERS(3)
377
378         add     $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame      */
379
380         test    v0,v0                       /* check for exception                */
381         je      L_asm_call_jit_compiler_exception
382
383         test    itmp3,itmp3                 /* is address == 0 (asm_calljavamethod*/
384         je      L_call_method
385
386         mov     v0,(itmp3)                  /* and now save the new pointer       */
387
388 L_call_method:
389         jmp     *v0                         /* ...and now call the new method     */
390
391 L_asm_call_jit_compiler_exception:
392 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
393         call    builtin_asm_get_exceptionptrptr@PLT
394         mov     v0,itmp2                    /* v0 == xptr                         */
395 #else
396         lea     _no_threads_exceptionptr(%rip),itmp2
397 #endif
398         mov     (itmp2),xptr                /* get the exception pointer          */
399         movl    $0,(itmp2)                  /* clear exception pointer            */
400
401         pop     xpc                         /* delete return address              */
402         sub     $5,xpc                      /* faulting address is ra - 5         */
403         jmp     L_asm_handle_exception
404
405
406 /* asm_handle_exception ********************************************************
407 *                                                                              *
408 *   This function handles an exception. It does not use the usual calling      *
409 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
410 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
411 *   the local exception table for a handler. If no one is found, it unwinds    *
412 *   stacks and continues searching the callers.                                *
413 *                                                                              *
414 *******************************************************************************/
415
416 asm_handle_nat_exception:
417         add     $8,sp                       /* clear return address of native stub*/
418                 
419 asm_handle_exception:
420 L_asm_handle_exception:                 /* required for PIC code              */
421         sub     $((ARG_CNT+TMP_CNT)*8),sp   /* create maybe-leaf stackframe       */
422
423         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
424         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
425
426         mov     $((ARG_CNT+TMP_CNT)*8),a3   /* prepare a3 for handle_exception    */
427         mov     $1,t0                       /* set maybe-leaf flag                */
428
429 L_asm_handle_exception_stack_loop:
430         sub     $(6*8),sp
431         mov     xptr,0*8(sp)                /* save exception pointer             */
432         mov     xpc,1*8(sp)                 /* save exception pc                  */
433         add     sp,a3                       /* calculate Java sp into a3...       */
434         add     $(6*8),a3
435         mov     a3,3*8(sp)                  /* ...and save it                     */
436         mov     t0,4*8(sp)                  /* save maybe-leaf flag               */
437
438         mov     xpc,a0                      /* exception pc                       */
439         call    codegen_findmethod@PLT
440         mov     v0,2*8(sp)                  /* save data segment pointer          */
441         
442         mov     0*8(sp),a0                  /* pass exception pointer             */
443         mov     1*8(sp),a1                  /* pass exception pc                  */
444         mov     v0,a2                       /* pass data segment pointer          */
445         mov     3*8(sp),a3                  /* pass Java stack pointer            */
446         call    exceptions_handle_exception@PLT
447
448         test    v0,v0
449         jz      L_asm_handle_exception_not_catched
450
451         mov     v0,xpc                      /* move handlerpc into xpc            */
452         mov     0*8(sp),xptr                /* restore exception pointer          */
453         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
454         add     $(6*8),sp                   /* free stack frame                   */
455
456         test    t0,t0                       /* test for maybe-leaf flag           */
457         jz      L_asm_handle_exception_no_leaf
458
459         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
460         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
461
462         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
463
464 L_asm_handle_exception_no_leaf:
465         jmp     *xpc                        /* jump to the handler                */
466
467 L_asm_handle_exception_not_catched:
468         mov     0*8(sp),xptr                /* restore exception pointer          */
469         mov     2*8(sp),itmp3               /* restore data segment pointer       */
470         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
471         add     $(6*8),sp
472
473         test    t0,t0
474         jz      L_asm_handle_exception_no_leaf_stack
475
476         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
477         xor     t0,t0                       /* clear the isleaf flags             */
478
479 L_asm_handle_exception_no_leaf_stack:
480         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
481         add     sp,itmp2                    /* pointer to save area               */
482         
483         mov     IntSave(itmp3),a0l          /* a0l = saved int register count     */
484         test    a0l,a0l
485         je      noint
486         
487         cmp     $1,a0l
488         je      int1
489         cmp     $2,a0l
490         je      int2
491         cmp     $3,a0l
492         je      int3
493         cmp     $4,a0l
494         je      int4
495         
496         mov     -5*8(itmp2),s0
497 int4:   
498         mov     -4*8(itmp2),s1
499 int3:   
500         mov     -3*8(itmp2),s2
501 int2:   
502         mov     -2*8(itmp2),s3
503 int1:   
504         mov     -1*8(itmp2),s4
505
506         shl     $3,a0l                      /* multiply by 8 bytes                */
507         sub     a0,itmp2
508                 
509 noint:
510 #if 0
511         mov     FltSave(itmp3),a0l          /* a0l = saved flt register count     */
512         test    a0l,a0l
513         je      noflt
514         
515         cmpl    $1,a0l
516         je      flt1
517         cmpl    $2,a0l
518         je      flt2
519         cmpl    $3,a0l
520         je      flt3
521         cmpl    $4,a0l
522         je      flt4
523
524         movq    -5*8(itmp2),%xmm11
525 flt4:   
526         movq    -4*8(itmp2),%xmm12
527 flt3:   
528         movq    -3*8(itmp2),%xmm13
529 flt2:   
530         movq    -2*8(itmp2),%xmm14
531 flt1:   
532         movq    -1*8(itmp2),%xmm15
533                 
534 noflt:
535 #endif
536         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
537         add     itmp2,sp                    /* unwind stack                       */
538
539                                             /* exception pointer is still set     */
540         pop     xpc                         /* the new xpc is return address      */
541         sub     $3,xpc                      /* subtract 3 bytes for call          */
542
543         xor     a3,a3                       /* prepare a3 for handle_exception    */
544         
545         jmp             L_asm_handle_exception_stack_loop
546
547
548 /* asm_wrapper_patcher *********************************************************
549
550    XXX
551
552    Stack layout:
553      40   return address
554      32   pointer to virtual java_objectheader
555      24   machine code (which is patched back later)
556      16   unresolved class/method/field reference
557       8   data segment displacement from load instructions
558       0   pointer to patcher function
559      -8   bp
560
561 *******************************************************************************/
562
563 asm_wrapper_patcher:
564         push    bp                          /* save base pointer                  */
565         mov     sp,bp                       /* move actual sp to bp               */
566         sub     $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
567         and     $0xfffffffffffffff0,sp      /* align sp to 16-byte (this is for   */
568                                             /* leaf functions)                    */
569
570         SAVE_ARGUMENT_REGISTERS(3)
571         SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
572
573         mov     itmp1,0*8(sp)               /* save itmp1 and itmp2               */
574         mov     itmp2,1*8(sp)               /* can be used by some instructions   */
575
576         mov     sp,a0                       /* create stackframe info             */
577         add     $((3+ARG_CNT+TMP_CNT)*8),a0
578         xor     a1,a1                       /* if pv is NULL, use findmethod      */
579         mov     bp,a2                       /* pass java sp                       */
580         add     $((6+1)*8),a2
581         mov     ((5+1)*8)(bp),a3            /* pass ra to java function           */
582         mov     a3,a4                       /* xpc is equal to ra                 */
583         call    stacktrace_create_extern_stackframeinfo@PLT
584
585         mov     bp,a0                       /* pass stack pointer                 */
586         add     $((1+1)*8),a0               /* skip function pointer              */
587         mov     1*8(bp),itmp3               /* get function pointer               */
588         call    *itmp3                      /* call the patcher function          */
589         mov     v0,2*8(sp)                  /* save return value                  */
590
591         mov     sp,a0                       /* remove stackframe info             */
592         add     $((3+ARG_CNT+TMP_CNT)*8),a0
593         call    stacktrace_remove_stackframeinfo@PLT
594
595         RESTORE_ARGUMENT_REGISTERS(3)
596         RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
597
598         mov     0*8(sp),itmp1               /* restore itmp1 and itmp2            */
599         mov     1*8(sp),itmp2               /* can be used by some instructions   */
600         mov     2*8(sp),itmp3               /* restore return value               */
601
602         mov     bp,sp                       /* restore original sp                */
603         pop     bp                          /* restore bp                         */
604         add     $(5*8),sp                   /* remove patcher stackframe, keep ra */
605
606         test    itmp3,itmp3                 /* exception thrown?                  */
607         jz      L_asm_wrapper_patcher_exception
608         ret                                 /* call new patched code              */
609
610 L_asm_wrapper_patcher_exception:
611 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
612         call    builtin_asm_get_exceptionptrptr@PLT
613         mov     v0,itmp2                    /* v0 == xptr                         */
614 #else
615         mov     _no_threads_exceptionptr,itmp2
616 #endif
617         mov     (itmp2),xptr                /* get the exception pointer          */
618         movl    $0,(itmp2)                  /* clear exception pointer            */
619
620         pop     xpc                         /* get and remove return address      */
621         jmp     L_asm_handle_exception
622
623
624 /* asm_replacement_out *********************************************************
625
626    This code is jumped to from the replacement-out stubs that are executed
627    when a thread reaches an activated replacement point.
628
629    The purpose of asm_replacement_out is to read out the parts of the
630    execution state that cannot be accessed from C code, store this state,
631    and then call the C function replace_me.
632
633    Stack layout:
634       8                 start of stack inside method to replace
635       0   rplpoint *    info on the replacement point that was reached
636
637 *******************************************************************************/
638
639 /* some room to accomodate changes of the stack frame size during replacement */
640         /* XXX we should find a cleaner solution here */
641 #define REPLACEMENT_ROOM  512
642
643 asm_replacement_out:
644     /* create stack frame */
645         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
646
647         /* save registers in execution state */
648         mov     %rax,(RAX*8+offes_intregs)(sp)
649         mov     %rbx,(RBX*8+offes_intregs)(sp)
650         mov     %rcx,(RCX*8+offes_intregs)(sp)
651         mov     %rdx,(RDX*8+offes_intregs)(sp)
652         mov     %rsi,(RSI*8+offes_intregs)(sp)
653         mov     %rdi,(RDI*8+offes_intregs)(sp)
654         mov     %rbp,(RBP*8+offes_intregs)(sp)
655         movq    $0  ,(RSP*8+offes_intregs)(sp) /* not used */
656         mov     %r8 ,(R8 *8+offes_intregs)(sp)
657         mov     %r9 ,(R9 *8+offes_intregs)(sp)
658         mov     %r10,(R10*8+offes_intregs)(sp)
659         mov     %r11,(R11*8+offes_intregs)(sp)
660         mov     %r12,(R12*8+offes_intregs)(sp)
661         mov     %r13,(R13*8+offes_intregs)(sp)
662         mov     %r14,(R14*8+offes_intregs)(sp)
663         mov     %r15,(R15*8+offes_intregs)(sp)
664
665         movq    %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
666         movq    %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
667         movq    %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
668         movq    %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
669         movq    %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
670         movq    %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
671         movq    %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
672         movq    %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
673         movq    %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
674         movq    %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
675         movq    %xmm10,(XMM10*8+offes_fltregs)(sp)
676         movq    %xmm11,(XMM11*8+offes_fltregs)(sp)
677         movq    %xmm12,(XMM12*8+offes_fltregs)(sp)
678         movq    %xmm13,(XMM13*8+offes_fltregs)(sp)
679         movq    %xmm14,(XMM14*8+offes_fltregs)(sp)
680         movq    %xmm15,(XMM15*8+offes_fltregs)(sp)
681
682         /* calculate sp of method */
683         mov     sp,itmp1
684         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
685         mov     itmp1,(offes_sp)(sp)
686
687         /* pv must be looked up via AVL tree */
688         movq    $0,(offes_pv)(sp)
689
690         /* call replace_me */
691         mov     -8(itmp1),a0                /* rplpoint *                         */
692     mov     sp,a1                       /* arg1: execution state              */
693     call    replace_me@PLT              /* call C function replace_me         */
694     call    abort@PLT                   /* NEVER REACHED                      */
695
696 /* asm_replacement_in **********************************************************
697
698    This code writes the given execution state and jumps to the replacement
699    code.
700
701    This function never returns!
702
703    C prototype:
704       void asm_replacement_in(executionstate *es);
705
706 *******************************************************************************/
707
708 asm_replacement_in:
709         mov     a0,%rbp                     /* executionstate *es                 */
710
711         /* set new sp */
712         mov     (offes_sp)(%rbp),%rsp
713         
714         /* store address of new code */
715         push    (offes_pc)(%rbp)
716         
717         /* copy registers from execution state */
718         movq    (XMM0 *8+offes_fltregs)(%rbp),%xmm0
719         movq    (XMM1 *8+offes_fltregs)(%rbp),%xmm1
720         movq    (XMM2 *8+offes_fltregs)(%rbp),%xmm2
721         movq    (XMM3 *8+offes_fltregs)(%rbp),%xmm3
722         movq    (XMM4 *8+offes_fltregs)(%rbp),%xmm4
723         movq    (XMM5 *8+offes_fltregs)(%rbp),%xmm5
724         movq    (XMM6 *8+offes_fltregs)(%rbp),%xmm6
725         movq    (XMM7 *8+offes_fltregs)(%rbp),%xmm7
726         movq    (XMM8 *8+offes_fltregs)(%rbp),%xmm8
727         movq    (XMM9 *8+offes_fltregs)(%rbp),%xmm9
728         movq    (XMM10*8+offes_fltregs)(%rbp),%xmm10
729         movq    (XMM11*8+offes_fltregs)(%rbp),%xmm11
730         movq    (XMM12*8+offes_fltregs)(%rbp),%xmm12
731         movq    (XMM13*8+offes_fltregs)(%rbp),%xmm13
732         movq    (XMM14*8+offes_fltregs)(%rbp),%xmm14
733         movq    (XMM15*8+offes_fltregs)(%rbp),%xmm15
734
735         mov     (RAX*8+offes_intregs)(%rbp),%rax
736         mov     (RBX*8+offes_intregs)(%rbp),%rbx
737         mov     (RCX*8+offes_intregs)(%rbp),%rcx
738         mov     (RDX*8+offes_intregs)(%rbp),%rdx
739         mov     (RSI*8+offes_intregs)(%rbp),%rsi
740         mov     (RDI*8+offes_intregs)(%rbp),%rdi
741         mov     (R8 *8+offes_intregs)(%rbp),%r8
742         mov     (R9 *8+offes_intregs)(%rbp),%r9
743         mov     (R10*8+offes_intregs)(%rbp),%r10
744         mov     (R11*8+offes_intregs)(%rbp),%r11
745         mov     (R12*8+offes_intregs)(%rbp),%r12
746         mov     (R13*8+offes_intregs)(%rbp),%r13
747         mov     (R14*8+offes_intregs)(%rbp),%r14
748         mov     (R15*8+offes_intregs)(%rbp),%r15
749
750         mov     (RBP*8+offes_intregs)(%rbp),%rbp
751
752         /* jump to new code */
753         ret
754
755 /* asm_builtin_x2x *************************************************************
756 *                                                                              *
757 *   Wrapper functions for float to int corner cases                            *
758 *                                                                              *
759 *******************************************************************************/
760
761 asm_builtin_f2i:
762         sub     $(ARG_CNT*8),sp
763         
764         SAVE_ARGUMENT_REGISTERS(0)
765         
766         movq    ftmp1,fa0
767         call    builtin_f2i@PLT
768         
769         RESTORE_ARGUMENT_REGISTERS(0)
770         
771         add     $(ARG_CNT*8),sp
772         ret
773
774
775 asm_builtin_f2l:
776         sub     $(ARG_CNT*8),sp
777         
778         SAVE_ARGUMENT_REGISTERS(0)
779         
780         movq    ftmp1,fa0
781         call    builtin_f2l@PLT
782         
783         RESTORE_ARGUMENT_REGISTERS(0)
784         
785         add     $(ARG_CNT*8),sp
786         ret
787
788
789 asm_builtin_d2i:
790         sub     $(ARG_CNT*8),sp
791         
792         SAVE_ARGUMENT_REGISTERS(0)
793         
794         movq    ftmp1,fa0
795         call    builtin_d2i@PLT
796         
797         RESTORE_ARGUMENT_REGISTERS(0)
798         
799         add     $(ARG_CNT*8),sp
800         ret
801
802
803 asm_builtin_d2l:
804         sub     $(ARG_CNT*8),sp
805         
806         SAVE_ARGUMENT_REGISTERS(0)
807         
808         movq    ftmp1,fa0
809         call    builtin_d2l@PLT
810         
811         RESTORE_ARGUMENT_REGISTERS(0)
812         
813         add     $(ARG_CNT*8),sp
814         ret
815
816
817 /******************* function asm_initialize_thread_stack **********************
818 *                                                                              *
819 * initialized a thread stack                                                   *
820 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
821 *                                                                              *
822 *******************************************************************************/
823
824 asm_initialize_thread_stack:
825         sub     $(7*8),%rsi
826
827         xor     %r10,%r10
828         mov     %r10,0*8(%rsi)
829         mov     %r10,1*8(%rsi)
830         mov     %r10,2*8(%rsi)
831         mov     %r10,3*8(%rsi)
832         mov     %r10,4*8(%rsi)
833         mov     %r10,5*8(%rsi)
834
835         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
836         mov     %rsi,%rax               /* return restorepoint in %rax        */
837         ret
838
839
840 /******************* function asm_perform_threadswitch *************************
841 *                                                                              *
842 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
843 *                                                                              *
844 *   performs a threadswitch                                                    *
845 *                                                                              *
846 *******************************************************************************/
847
848 asm_perform_threadswitch:
849         sub     $(7*8),%rsp             /* allocate stack frame               */
850
851         mov     %rbx,0*8(%rsp)
852         mov     %rbp,1*8(%rsp)
853         mov     %r12,2*8(%rsp)
854         mov     %r13,3*8(%rsp)
855         mov     %r14,4*8(%rsp)
856         mov     %r15,5*8(%rsp)
857
858         mov     7*8(%rsp),%rax                  /* save current return address        */
859         mov     %rax,6*8(%rsp)
860
861         mov     %rsp,(%rdi)                     /* first argument **from              */
862         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
863
864         mov     (%rsi),%rsp                     /* load new stack pointer             */
865
866         mov     0*8(%rsp),%rbx
867         mov     1*8(%rsp),%rbp
868         mov     2*8(%rsp),%r12
869         mov     3*8(%rsp),%r13
870         mov     4*8(%rsp),%r14
871         mov     5*8(%rsp),%r15
872
873         mov     6*8(%rsp),%rax          /* restore return address             */
874         add     $(7*8),%rsp             /* free stack frame                   */
875         mov     %rax,(%rsp)
876         ret
877                 
878
879 /********************* function asm_switchstackandcall *************************
880 *                                                                              *
881 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
882 *                                      void *p);                                       *
883 *                                                                              *
884 *   Switches to a new stack, calls a function and switches back.               *
885 *       a0 (%rdi)     new stack pointer                                        *
886 *       a1 (%rsi)     function pointer                                         *
887 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
888 *       a3 (%rcx)     pointer to user data, is passed to the function          *
889 *                                                                              *
890 *******************************************************************************/
891
892 asm_switchstackandcall:
893         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
894         sub     $16,%rdi                                /* allocate new stack                 */
895
896         mov     8(%rsp),%rax                    /* save return address on new stack   */
897         mov     %rax,(%rdi)
898         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
899         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
900
901         mov     %rdi,%rsp                               /* switch to new stack                */
902
903         mov     %rcx,%rdi                       /* pass pointer                       */
904         call    *%rsi                                   /* and call function                  */
905
906         mov     (%rsp),%r10                             /* load return address                */
907         mov     8(%rsp),%rsp                    /* switch to old stack                */
908         add     $(1*8),%rsp             /* free stack space                   */
909         mov     %r10,(%rsp)             /* write return adress                */
910         ret
911
912
913 asm_getclassvalues_atomic:
914 _crit_restart:
915 _crit_begin:
916         movl    offbaseval(a0),itmp1l
917         movl    offdiffval(a0),itmp2l
918         movl    offbaseval(a1),itmp3l
919 _crit_end:
920         movl    itmp1l,offcast_super_baseval(a2)
921         movl    itmp2l,offcast_super_diffval(a2)
922         movl    itmp3l,offcast_sub_baseval(a2)
923         ret
924
925         .data
926                 
927 asm_criticalsections:
928 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
929         .quad   _crit_begin
930         .quad   _crit_end
931         .quad   _crit_restart
932 #endif
933         .quad 0
934
935
936 /* Disable exec-stacks, required for Gentoo ***********************************/
937
938 #if defined(__GCC__) && defined(__ELF__)
939         .section .note.GNU-stack,"",@progbits
940 #endif
941
942
943 /*
944  * These are local overrides for various environment variables in Emacs.
945  * Please do not remove this and leave it at the end of the file, where
946  * Emacs will automagically detect them.
947  * ---------------------------------------------------------------------
948  * Local variables:
949  * mode: asm
950  * indent-tabs-mode: t
951  * c-basic-offset: 4
952  * tab-width: 4
953  * End:
954  * vim:noexpandtab:sw=4:ts=4:
955  */