* src/vm/vm.c (vm_call_method_intern): Removed.
[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:
32
33    $Id: asmpart.S 4559 2006-03-05 23:24:50Z 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_builtin_f2i
68         .globl asm_builtin_f2l
69         .globl asm_builtin_d2i
70         .globl asm_builtin_d2l
71
72         .globl asm_perform_threadswitch
73         .globl asm_initialize_thread_stack
74         .globl asm_switchstackandcall
75         .globl asm_criticalsections
76         .globl asm_getclassvalues_atomic
77
78
79 /********************* function asm_calljavafunction ***************************
80 *                                                                              *
81 *   This function calls a Java-method (which possibly needs compilation)       *
82 *   with up to 4 address parameters.                                           *
83 *                                                                              *
84 *   This functions calls the JIT-compiler which eventually translates the      *
85 *   method into machine code.                                                  *
86 *                                                                              *
87 *   C-prototype:                                                               *
88 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
89 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
90 *                                                                              *
91 *******************************************************************************/
92
93         .align  8
94
95         .quad   0                           /* catch type all                     */
96         .quad   calljava_xhandler2          /* handler pc                         */
97         .quad   calljava_xhandler2          /* end pc                             */
98         .quad   L_asm_vm_call_method        /* start pc                           */
99         .long   1                           /* extable size                       */
100         .long   0                                                                                                                        
101         .quad   0                           /* line number table  start           */
102         .quad   0                           /* line number table  size            */
103         .long   0                                                                                                                        
104         .long   0                           /* fltsave                            */
105         .long   0                           /* intsave                            */
106         .long   0                           /* isleaf                             */
107         .long   0                           /* IsSync                             */
108         .long   24                          /* frame size                         */
109         .quad   0                           /* method pointer (pointer to name)   */
110
111 asm_vm_call_method:
112 asm_vm_call_method_int:
113 asm_vm_call_method_long:
114 asm_vm_call_method_float:
115 asm_vm_call_method_double:
116 L_asm_vm_call_method:                   /* required for PIC code              */
117         sub     $(7*8),sp                   /* keep stack 16-byte aligned         */
118         mov     %rbx,0*8(sp)                /* %rbx is not a callee saved in cacao*/
119         mov     s0,1*8(sp)
120         mov     s1,2*8(sp)
121         mov     s2,3*8(sp)
122         mov     s3,4*8(sp)
123         mov     s4,5*8(sp)
124
125         mov     a0,itmp1                    /* move method pointer for compiler   */
126         xor     %rbp,%rbp                   /* set argument stack frame to zero   */
127
128         test    a1,a1                       /* maybe we have no args...           */
129         jle     L_copy_done
130
131         mov     a1,itmp3                    /* arg count                          */
132         mov     a2,itmp2                    /* pointer to arg block               */
133
134         mov     itmp2,%r14                  /* save argument block pointer        */
135         mov     itmp3,%r15                  /* save argument count                */
136
137         sub     $sizevmarg,itmp2            /* initialize pointer (smaller code)  */
138         add     $1,itmp3                    /* initialize argument count          */
139         xor     %r12,%r12                   /* initialize integer argument counter*/
140         xor     %r13,%r13                   /* initialize float argument counter  */
141
142 L_register_copy:
143         add     $sizevmarg,itmp2            /* goto next argument block           */
144         dec     itmp3                       /* argument count - 1                 */
145         jz      L_register_copy_done
146         andb    $0x02,offvmargtype(itmp2)   /* is this a float/double type?       */
147         jnz     L_register_handle_float     /* yes, handle it                     */
148
149         cmp     $INT_ARG_CNT,%r12           /* are we out of integer argument     */
150         je      L_register_copy             /* register? yes, next loop           */
151
152         lea     jumptable_integer(%rip),%rbp
153         mov     0(%rbp,%r12,8),%rbx
154         inc     %r12                      /* integer argument counter + 1         */
155         jmp     *%rbx
156
157 L_register_handle_float:
158         cmp     $FLT_ARG_CNT,%r13         /* are we out of float argument         */
159         je      L_register_copy           /* register? yes, next loop             */
160
161         lea     jumptable_float(%rip),%rbp
162         mov     0(%rbp,%r13,8),%rbx
163         inc     %r13                      /* float argument counter + 1           */
164         jmp     *%rbx
165         
166 L_register_copy_done:
167         mov     %r15,%rbp                 /* calculate remaining arguments        */
168         sub     %r12,%rbp                 /* - integer arguments in registers     */
169         sub     %r13,%rbp                 /* - float arguments in registers       */
170         jle     L_copy_done               /* are all assigned to registers?       */
171
172         and     $0xfffffffffffffffe,%rbp  /* keep stack 16-byte aligned           */
173         shl     $3,%rbp                   /* calculate stack size                 */
174         sub     %rbp,sp                   /* stack frame for arguments            */
175         mov     sp,%rbx                   /* use %rbx as temp sp                  */
176
177         sub     $sizevmarg,%r14           /* initialize pointer (smaller code)    */
178         add     $1,%r15                   /* initialize argument count            */
179                 
180 L_stack_copy_loop:
181         add     $sizevmarg,%r14           /* goto next argument block             */
182         dec     %r15                      /* are there any arguments left?        */
183         jz      L_copy_done               /* no test needed after dec             */
184
185         andb    $0x02,offvmargtype(%r14)    /* is this a float/double type?       */
186         jnz     L_stack_handle_float
187         dec     %r12                        /* arguments assigned to registers    */
188         jge     L_stack_copy_loop
189         jmp     L_stack_copy
190
191 L_stack_handle_float:
192         dec     %r13                        /* arguments assigned to registers    */
193         jge     L_stack_copy_loop
194
195 L_stack_copy:
196         mov     offvmargdata(%r14),itmp3    /* copy s8 argument onto stack        */
197         mov     itmp3,0(%rbx)
198         add     $8,%rbx                     /* increase sp to next argument       */
199         jmp     L_stack_copy_loop
200
201 L_copy_done:
202                                             /* itmp1 still contains method pointer*/
203         lea     L_asm_call_jit_compiler(%rip),itmp3
204         call    *itmp3                      /* call JIT compiler                  */
205
206         add     bp,sp                       /* remove argument stack frame if any */
207
208 L_asm_vm_call_method_return:
209         mov     0*8(sp),%rbx                /* restore callee saved registers     */
210         mov     1*8(sp),s0
211         mov     2*8(sp),s1
212         mov     3*8(sp),s2
213         mov     4*8(sp),s3
214         mov     5*8(sp),s4
215         add     $(7*8),sp                   /* free stack space                   */
216         ret
217                 
218 calljava_xhandler2:
219         mov     xptr,a0                     /* pass exception pointer             */
220         call    builtin_throw_exception@PLT
221         xor     v0,v0                       /* return NULL                        */
222         jmp     L_asm_vm_call_method_return
223
224
225 jumptable_integer:
226         .quad   handle_a0
227         .quad   handle_a1
228         .quad   handle_a2
229         .quad   handle_a3
230         .quad   handle_a4
231         .quad   handle_a5
232
233 handle_a0:
234         mov     offvmargdata(itmp2),a0
235         jmp     L_register_copy
236 handle_a1:
237         mov     offvmargdata(itmp2),a1
238         jmp     L_register_copy
239 handle_a2:
240         mov     offvmargdata(itmp2),a2
241         jmp     L_register_copy
242 handle_a3:
243         mov     offvmargdata(itmp2),a3
244         jmp     L_register_copy
245 handle_a4:
246         mov     offvmargdata(itmp2),a4
247         jmp     L_register_copy
248 handle_a5:
249         mov     offvmargdata(itmp2),a5
250         jmp     L_register_copy
251
252
253 jumptable_float:
254         .quad   handle_fa0
255         .quad   handle_fa1
256         .quad   handle_fa2
257         .quad   handle_fa3
258         .quad   handle_fa4
259         .quad   handle_fa5
260         .quad   handle_fa6
261         .quad   handle_fa7
262
263 handle_fa0:
264         movq    offvmargdata(itmp2),fa0
265         jmp     L_register_copy
266 handle_fa1:
267         movq    offvmargdata(itmp2),fa1
268         jmp     L_register_copy
269 handle_fa2:
270         movq    offvmargdata(itmp2),fa2
271         jmp     L_register_copy
272 handle_fa3:
273         movq    offvmargdata(itmp2),fa3
274         jmp     L_register_copy
275 handle_fa4:
276         movq    offvmargdata(itmp2),fa4
277         jmp     L_register_copy
278 handle_fa5:
279         movq    offvmargdata(itmp2),fa5
280         jmp     L_register_copy
281 handle_fa6:
282         movq    offvmargdata(itmp2),fa6
283         jmp     L_register_copy
284 handle_fa7:
285         movq    offvmargdata(itmp2),fa7
286         jmp     L_register_copy
287
288
289 /****************** function asm_call_jit_compiler *****************************
290 *                                                                              *
291 *   invokes the compiler for untranslated JavaVM methods.                      *
292 *                                                                              *
293 *   Register R0 contains a pointer to the method info structure (prepared      *
294 *   by createcompilerstub). Using the return address in R26 and the            *
295 *   offset in the LDA instruction or using the value in methodptr R28 the      *
296 *   patching address for storing the method address can be computed:           *
297 *                                                                              *
298 *   method address was either loaded using                                     *
299 *                                                                              *
300 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
301 *   i386_call_reg(REG_ITMP2)                                                   *
302 *                                                                              *
303 *   or                                                                         *
304 *                                                                              *
305 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
306 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
307 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
308 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
309 *   i386_call_reg(REG_ITMP1)                                                   *
310 *                                                                              *
311 *   in the static case the method pointer can be computed using the            *
312 *   return address and the lda function following the jmp instruction          *
313 *                                                                              *
314 *******************************************************************************/
315
316 asm_call_jit_compiler:
317 L_asm_call_jit_compiler:                /* required for PIC code              */
318                                             /* keep stack 16-byte aligned         */
319         sub     $((3+ARG_CNT)*8+sizestackframeinfo),sp
320
321         mov     t0,0*8(sp)                  /* save register                      */
322
323         mov     (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address  */
324         mov     -1(itmp3),%bl               /* get function code                  */
325         cmp     $0xd2,%bl                   /* called with `call *REG_ITMP2'?     */
326         jne     L_not_static_special
327
328         sub     $11,itmp3                   /* calculate address of immediate     */
329         jmp     L_call_jit_compile
330                 
331 L_not_static_special:
332         cmp     $0xd0,%bl                   /* called with `call *REG_ITMP1'      */
333         jne     L_not_virtual_interface
334                 
335         sub     $7,itmp3                    /* calculate address of offset        */
336         mov     (itmp3),itmp3l              /* get offset (32-bit)                */
337         add     itmp2,itmp3                 /* add base address to get method addr*/
338         jmp     L_call_jit_compile
339
340 L_not_virtual_interface:                /* a call from asm_calljavamethod     */
341         xor     itmp3,itmp3
342                 
343 L_call_jit_compile:
344         mov     0*8(sp),t0                  /* restore register                   */
345         mov     itmp3,0*8(sp)               /* save address for method pointer    */
346         mov     itmp1,1*8(sp)               /* save method pointer                */
347
348         SAVE_ARGUMENT_REGISTERS(3)
349
350         mov     sp,a0                       /* create stackframe info             */
351         add     $((3+ARG_CNT)*8),a0         /* pass sfi                           */
352         xor     a1,a1                       /* if pv is NULL, use findmethod      */
353         mov     sp,a2                       /* pass java sp                       */
354         add     $((1+3+ARG_CNT)*8+sizestackframeinfo),a2
355                                             /* pass ra to java function           */
356         mov     ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3
357         mov     a3,a4                       /* xpc is equal to ra                 */
358         call    stacktrace_create_extern_stackframeinfo@PLT
359
360         mov     1*8(sp),a0                  /* pass method pointer                */
361         call    jit_compile@PLT
362         mov     v0,1*8(sp)                  /* save return value                  */
363
364         mov     sp,a0                       /* remove stackframe info             */
365         add     $((3+ARG_CNT)*8),a0         /* pass sfi                           */
366         call    stacktrace_remove_stackframeinfo@PLT
367
368         mov     0*8(sp),itmp3               /* restore address for method pointer */
369         mov     1*8(sp),v0                  /* restore return value               */
370
371         RESTORE_ARGUMENT_REGISTERS(3)
372
373         add     $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame      */
374
375         test    v0,v0                       /* check for exception                */
376         je      L_asm_call_jit_compiler_exception
377
378         test    itmp3,itmp3                 /* is address == 0 (asm_calljavamethod*/
379         je      L_call_method
380
381         mov     v0,(itmp3)                  /* and now save the new pointer       */
382
383 L_call_method:
384         jmp     *v0                         /* ...and now call the new method     */
385
386 L_asm_call_jit_compiler_exception:
387 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
388         call    builtin_asm_get_exceptionptrptr@PLT
389         mov     v0,itmp2                    /* v0 == xptr                         */
390 #else
391         lea     _no_threads_exceptionptr(%rip),itmp2
392 #endif
393         mov     (itmp2),xptr                /* get the exception pointer          */
394         movl    $0,(itmp2)                  /* clear exception pointer            */
395
396         pop     xpc                         /* delete return address              */
397         sub     $5,xpc                      /* faulting address is ra - 5         */
398         jmp     L_asm_handle_exception
399
400
401 /* asm_handle_exception ********************************************************
402 *                                                                              *
403 *   This function handles an exception. It does not use the usual calling      *
404 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
405 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
406 *   the local exception table for a handler. If no one is found, it unwinds    *
407 *   stacks and continues searching the callers.                                *
408 *                                                                              *
409 *******************************************************************************/
410
411 asm_handle_nat_exception:
412         add     $8,sp                       /* clear return address of native stub*/
413                 
414 asm_handle_exception:
415 L_asm_handle_exception:                 /* required for PIC code              */
416         sub     $((ARG_CNT+TMP_CNT)*8),sp   /* create maybe-leaf stackframe       */
417
418         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
419         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
420
421         mov     $((ARG_CNT+TMP_CNT)*8),a3   /* prepare a3 for handle_exception    */
422         mov     $1,t0                       /* set maybe-leaf flag                */
423
424 L_asm_handle_exception_stack_loop:
425         sub     $(6*8),sp
426         mov     xptr,0*8(sp)                /* save exception pointer             */
427         mov     xpc,1*8(sp)                 /* save exception pc                  */
428         add     sp,a3                       /* calculate Java sp into a3...       */
429         add     $(6*8),a3
430         mov     a3,3*8(sp)                  /* ...and save it                     */
431         mov     t0,4*8(sp)                  /* save maybe-leaf flag               */
432
433         mov     xpc,a0                      /* exception pc                       */
434         call    codegen_findmethod@PLT
435         mov     v0,2*8(sp)                  /* save data segment pointer          */
436         
437         mov     0*8(sp),a0                  /* pass exception pointer             */
438         mov     1*8(sp),a1                  /* pass exception pc                  */
439         mov     v0,a2                       /* pass data segment pointer          */
440         mov     3*8(sp),a3                  /* pass Java stack pointer            */
441         call    exceptions_handle_exception@PLT
442
443         test    v0,v0
444         jz      L_asm_handle_exception_not_catched
445
446         mov     v0,xpc                      /* move handlerpc into xpc            */
447         mov     0*8(sp),xptr                /* restore exception pointer          */
448         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
449         add     $(6*8),sp                   /* free stack frame                   */
450
451         test    t0,t0                       /* test for maybe-leaf flag           */
452         jz      L_asm_handle_exception_no_leaf
453
454         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
455         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
456
457         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
458
459 L_asm_handle_exception_no_leaf:
460         jmp     *xpc                        /* jump to the handler                */
461
462 L_asm_handle_exception_not_catched:
463         mov     0*8(sp),xptr                /* restore exception pointer          */
464         mov     2*8(sp),itmp3               /* restore data segment pointer       */
465         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
466         add     $(6*8),sp
467
468         test    t0,t0
469         jz      L_asm_handle_exception_no_leaf_stack
470
471         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
472         xor     t0,t0                       /* clear the isleaf flags             */
473
474 L_asm_handle_exception_no_leaf_stack:
475         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
476         add     sp,itmp2                    /* pointer to save area               */
477         
478         mov     IntSave(itmp3),a0l          /* a0l = saved int register count     */
479         test    a0l,a0l
480         je      noint
481         
482         cmp     $1,a0l
483         je      int1
484         cmp     $2,a0l
485         je      int2
486         cmp     $3,a0l
487         je      int3
488         cmp     $4,a0l
489         je      int4
490         
491         mov     -5*8(itmp2),s0
492 int4:   
493         mov     -4*8(itmp2),s1
494 int3:   
495         mov     -3*8(itmp2),s2
496 int2:   
497         mov     -2*8(itmp2),s3
498 int1:   
499         mov     -1*8(itmp2),s4
500
501         shl     $3,a0l                      /* multiply by 8 bytes                */
502         sub     a0,itmp2
503                 
504 noint:
505 #if 0
506         mov     FltSave(itmp3),a0l          /* a0l = saved flt register count     */
507         test    a0l,a0l
508         je      noflt
509         
510         cmpl    $1,a0l
511         je      flt1
512         cmpl    $2,a0l
513         je      flt2
514         cmpl    $3,a0l
515         je      flt3
516         cmpl    $4,a0l
517         je      flt4
518
519         movq    -5*8(itmp2),%xmm11
520 flt4:   
521         movq    -4*8(itmp2),%xmm12
522 flt3:   
523         movq    -3*8(itmp2),%xmm13
524 flt2:   
525         movq    -2*8(itmp2),%xmm14
526 flt1:   
527         movq    -1*8(itmp2),%xmm15
528                 
529 noflt:
530 #endif
531         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
532         add     itmp2,sp                    /* unwind stack                       */
533
534                                             /* exception pointer is still set     */
535         pop     xpc                         /* the new xpc is return address      */
536         sub     $3,xpc                      /* subtract 3 bytes for call          */
537
538         xor     a3,a3                       /* prepare a3 for handle_exception    */
539         
540         jmp             L_asm_handle_exception_stack_loop
541
542
543 /* asm_wrapper_patcher *********************************************************
544
545    XXX
546
547    Stack layout:
548      40   return address
549      32   pointer to virtual java_objectheader
550      24   machine code (which is patched back later)
551      16   unresolved class/method/field reference
552       8   data segment displacement from load instructions
553       0   pointer to patcher function
554      -8   bp
555
556 *******************************************************************************/
557
558 asm_wrapper_patcher:
559         push    bp                          /* save base pointer                  */
560         mov     sp,bp                       /* move actual sp to bp               */
561         sub     $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
562         and     $0xfffffffffffffff0,sp      /* align sp to 16-byte (this is for   */
563                                             /* leaf functions)                    */
564
565         SAVE_ARGUMENT_REGISTERS(3)
566         SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
567
568         mov     itmp1,0*8(sp)               /* save itmp1 and itmp2               */
569         mov     itmp2,1*8(sp)               /* can be used by some instructions   */
570
571         mov     sp,a0                       /* create stackframe info             */
572         add     $((3+ARG_CNT+TMP_CNT)*8),a0
573         xor     a1,a1                       /* if pv is NULL, use findmethod      */
574         mov     bp,a2                       /* pass java sp                       */
575         add     $((6+1)*8),a2
576         mov     ((5+1)*8)(bp),a3            /* pass ra to java function           */
577         mov     a3,a4                       /* xpc is equal to ra                 */
578         call    stacktrace_create_extern_stackframeinfo@PLT
579
580         mov     bp,a0                       /* pass stack pointer                 */
581         add     $((1+1)*8),a0               /* skip function pointer              */
582         mov     1*8(bp),itmp3               /* get function pointer               */
583         call    *itmp3                      /* call the patcher function          */
584         mov     v0,2*8(sp)                  /* save return value                  */
585
586         mov     sp,a0                       /* remove stackframe info             */
587         add     $((3+ARG_CNT+TMP_CNT)*8),a0
588         call    stacktrace_remove_stackframeinfo@PLT
589
590         RESTORE_ARGUMENT_REGISTERS(3)
591         RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
592
593         mov     0*8(sp),itmp1               /* restore itmp1 and itmp2            */
594         mov     1*8(sp),itmp2               /* can be used by some instructions   */
595         mov     2*8(sp),itmp3               /* restore return value               */
596
597         mov     bp,sp                       /* restore original sp                */
598         pop     bp                          /* restore bp                         */
599         add     $(5*8),sp                   /* remove patcher stackframe, keep ra */
600
601         test    itmp3,itmp3                 /* exception thrown?                  */
602         jz      L_asm_wrapper_patcher_exception
603         ret                                 /* call new patched code              */
604
605 L_asm_wrapper_patcher_exception:
606 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
607         call    builtin_asm_get_exceptionptrptr@PLT
608         mov     v0,itmp2                    /* v0 == xptr                         */
609 #else
610         mov     _no_threads_exceptionptr,itmp2
611 #endif
612         mov     (itmp2),xptr                /* get the exception pointer          */
613         movl    $0,(itmp2)                  /* clear exception pointer            */
614
615         pop     xpc                         /* get and remove return address      */
616         jmp     L_asm_handle_exception
617
618
619 /* asm_builtin_x2x *************************************************************
620 *                                                                              *
621 *   Wrapper functions for float to int corner cases                            *
622 *                                                                              *
623 *******************************************************************************/
624
625 asm_builtin_f2i:
626         sub     $(ARG_CNT*8),sp
627         
628         SAVE_ARGUMENT_REGISTERS(0)
629         
630         movq    ftmp1,fa0
631         call    builtin_f2i@PLT
632         
633         RESTORE_ARGUMENT_REGISTERS(0)
634         
635         add     $(ARG_CNT*8),sp
636         ret
637
638
639 asm_builtin_f2l:
640         sub     $(ARG_CNT*8),sp
641         
642         SAVE_ARGUMENT_REGISTERS(0)
643         
644         movq    ftmp1,fa0
645         call    builtin_f2l@PLT
646         
647         RESTORE_ARGUMENT_REGISTERS(0)
648         
649         add     $(ARG_CNT*8),sp
650         ret
651
652
653 asm_builtin_d2i:
654         sub     $(ARG_CNT*8),sp
655         
656         SAVE_ARGUMENT_REGISTERS(0)
657         
658         movq    ftmp1,fa0
659         call    builtin_d2i@PLT
660         
661         RESTORE_ARGUMENT_REGISTERS(0)
662         
663         add     $(ARG_CNT*8),sp
664         ret
665
666
667 asm_builtin_d2l:
668         sub     $(ARG_CNT*8),sp
669         
670         SAVE_ARGUMENT_REGISTERS(0)
671         
672         movq    ftmp1,fa0
673         call    builtin_d2l@PLT
674         
675         RESTORE_ARGUMENT_REGISTERS(0)
676         
677         add     $(ARG_CNT*8),sp
678         ret
679
680
681 /******************* function asm_initialize_thread_stack **********************
682 *                                                                              *
683 * initialized a thread stack                                                   *
684 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
685 *                                                                              *
686 *******************************************************************************/
687
688 asm_initialize_thread_stack:
689         sub     $(7*8),%rsi
690
691         xor     %r10,%r10
692         mov     %r10,0*8(%rsi)
693         mov     %r10,1*8(%rsi)
694         mov     %r10,2*8(%rsi)
695         mov     %r10,3*8(%rsi)
696         mov     %r10,4*8(%rsi)
697         mov     %r10,5*8(%rsi)
698
699         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
700         mov     %rsi,%rax               /* return restorepoint in %rax        */
701         ret
702
703
704 /******************* function asm_perform_threadswitch *************************
705 *                                                                              *
706 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
707 *                                                                              *
708 *   performs a threadswitch                                                    *
709 *                                                                              *
710 *******************************************************************************/
711
712 asm_perform_threadswitch:
713         sub     $(7*8),%rsp             /* allocate stack frame               */
714
715         mov     %rbx,0*8(%rsp)
716         mov     %rbp,1*8(%rsp)
717         mov     %r12,2*8(%rsp)
718         mov     %r13,3*8(%rsp)
719         mov     %r14,4*8(%rsp)
720         mov     %r15,5*8(%rsp)
721
722         mov     7*8(%rsp),%rax                  /* save current return address        */
723         mov     %rax,6*8(%rsp)
724
725         mov     %rsp,(%rdi)                     /* first argument **from              */
726         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
727
728         mov     (%rsi),%rsp                     /* load new stack pointer             */
729
730         mov     0*8(%rsp),%rbx
731         mov     1*8(%rsp),%rbp
732         mov     2*8(%rsp),%r12
733         mov     3*8(%rsp),%r13
734         mov     4*8(%rsp),%r14
735         mov     5*8(%rsp),%r15
736
737         mov     6*8(%rsp),%rax          /* restore return address             */
738         add     $(7*8),%rsp             /* free stack frame                   */
739         mov     %rax,(%rsp)
740         ret
741                 
742
743 /********************* function asm_switchstackandcall *************************
744 *                                                                              *
745 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
746 *                                      void *p);                                       *
747 *                                                                              *
748 *   Switches to a new stack, calls a function and switches back.               *
749 *       a0 (%rdi)     new stack pointer                                        *
750 *       a1 (%rsi)     function pointer                                         *
751 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
752 *       a3 (%rcx)     pointer to user data, is passed to the function          *
753 *                                                                              *
754 *******************************************************************************/
755
756 asm_switchstackandcall:
757         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
758         sub     $16,%rdi                                /* allocate new stack                 */
759
760         mov     8(%rsp),%rax                    /* save return address on new stack   */
761         mov     %rax,(%rdi)
762         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
763         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
764
765         mov     %rdi,%rsp                               /* switch to new stack                */
766
767         mov     %rcx,%rdi                       /* pass pointer                       */
768         call    *%rsi                                   /* and call function                  */
769
770         mov     (%rsp),%r10                             /* load return address                */
771         mov     8(%rsp),%rsp                    /* switch to old stack                */
772         add     $(1*8),%rsp             /* free stack space                   */
773         mov     %r10,(%rsp)             /* write return adress                */
774         ret
775
776
777 asm_getclassvalues_atomic:
778 _crit_restart:
779 _crit_begin:
780         movl    offbaseval(a0),itmp1l
781         movl    offdiffval(a0),itmp2l
782         movl    offbaseval(a1),itmp3l
783 _crit_end:
784         movl    itmp1l,offcast_super_baseval(a2)
785         movl    itmp2l,offcast_super_diffval(a2)
786         movl    itmp3l,offcast_sub_baseval(a2)
787         ret
788
789         .data
790                 
791 asm_criticalsections:
792 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
793         .quad   _crit_begin
794         .quad   _crit_end
795         .quad   _crit_restart
796 #endif
797         .quad 0
798
799
800 /* Disable exec-stacks, required for Gentoo ***********************************/
801
802 #if defined(__GCC__) && defined(__ELF__)
803         .section .note.GNU-stack,"",@progbits
804 #endif
805
806
807 /*
808  * These are local overrides for various environment variables in Emacs.
809  * Please do not remove this and leave it at the end of the file, where
810  * Emacs will automagically detect them.
811  * ---------------------------------------------------------------------
812  * Local variables:
813  * mode: asm
814  * indent-tabs-mode: t
815  * c-basic-offset: 4
816  * tab-width: 4
817  * End:
818  */