- changes for asm_check_clinit: don't use a stack location to pass the
[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 2238 2005-04-06 12:13:57Z 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 /* define it like the risc way */
43
44 #define v0       %rax
45
46 #define a0       %rdi
47 #define a1       %rsi
48 #define a2       %rdx
49 #define a3       %rcx
50 #define a4       %r8
51 #define a5       %r9
52
53 #define fa0      %xmm0
54 #define fa1      %xmm1
55 #define fa2      %xmm2
56 #define fa3      %xmm3
57 #define fa4      %xmm4
58 #define fa5      %xmm5
59 #define fa6      %xmm6
60 #define fa7      %xmm7
61
62 #define itmp1    %rax
63 #define itmp2    %r10
64 #define itmp3    %r11
65
66 #define itmp1l   %eax
67 #define itmp2l   %r10d
68 #define itmp3l   %r11d
69
70 #define itmp1b   %al
71 #define itmp2b   %r10b
72 #define itmp3b   %r11b
73
74 #define xptr     itmp1
75 #define xpc      itmp2
76
77
78         .text
79
80
81 /********************* exported functions and variables ***********************/
82
83         .globl asm_calljavafunction
84         .globl asm_calljavafunction_int
85
86         .globl asm_calljavafunction2
87         .globl asm_calljavafunction2int
88         .globl asm_calljavafunction2long
89         .globl asm_calljavafunction2float
90         .globl asm_calljavafunction2double
91
92         .globl asm_call_jit_compiler
93         .globl asm_handle_exception
94         .globl asm_handle_nat_exception
95
96         .globl asm_check_clinit
97
98         .globl asm_builtin_new
99         .globl asm_invokespecial
100
101         .globl asm_builtin_checkarraycast
102         .globl asm_builtin_aastore
103
104 #if defined(USE_THREADS)
105         .globl asm_builtin_monitorenter
106         .globl asm_builtin_monitorexit
107 #endif
108
109         .globl asm_builtin_f2i
110         .globl asm_builtin_f2l
111         .globl asm_builtin_d2i
112         .globl asm_builtin_d2l
113
114         .globl asm_perform_threadswitch
115         .globl asm_initialize_thread_stack
116         .globl asm_switchstackandcall
117         .globl asm_criticalsections
118         .globl asm_getclassvalues_atomic
119                 
120
121 /********************* function asm_calljavafunction ***************************
122 *                                                                              *
123 *   This function calls a Java-method (which possibly needs compilation)       *
124 *   with up to 4 address parameters.                                           *
125 *                                                                              *
126 *   This functions calls the JIT-compiler which eventually translates the      *
127 *   method into machine code.                                                  *
128 *                                                                              *
129 *   C-prototype:                                                               *
130 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
131 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
132 *                                                                              *
133 *******************************************************************************/
134
135 call_name:
136         .align  8
137
138         .quad   0                         /* catch type all                       */
139         .quad   calljava_xhandler         /* handler pc                           */
140         .quad   calljava_xhandler         /* end pc                               */
141         .quad   asm_calljavafunction      /* start pc                             */
142         .long   1                         /* extable size                         */
143         .long   0                         /* fltsave                              */
144         .long   0                         /* intsave                              */
145         .long   0                         /* isleaf                               */
146         .long   0                         /* IsSync                               */
147         .long   8                         /* frame size                           */
148         .quad   0                         /* method pointer (pointer to name)     */
149
150 asm_calljavafunction:
151 asm_calljavafunction_int:
152         sub     $(3*8),%rsp               /* keep stack 16-byte aligned           */
153         mov     %rbp,0*8(%rsp)
154         mov     %rbx,1*8(%rsp)            /* %rbx is not a callee saved in cacao  */
155         mov     %rdi,%rax                 /* move function pointer to %rax        */
156                                                                           /* compilerstub uses this               */
157
158         mov     %rsi,%rdi                 /* pass remaining parameters            */
159         mov     %rdx,%rsi
160         mov     %rcx,%rdx
161         mov     %r8,%rcx
162         
163         lea     asm_call_jit_compiler,%r11
164         call    *%r11                     /* call JIT compiler                    */
165
166         mov     0*8(%rsp),%rbp
167         mov             1*8(%rsp),%rbx
168         add     $(3*8),%rsp               /* free stack space                     */
169         ret
170
171 calljava_xhandler:
172         mov     %rax,%rdi                 /* pass exception pointer               */
173         call    builtin_throw_exception
174         mov     0*8(%rsp),%rbp
175         mov             1*8(%rsp),%rbx
176         add     $(3*8),%rsp
177         xor     %rax,%rax                 /* return NULL                          */
178         ret
179
180
181 /********************* function asm_calljavafunction ***************************
182 *                                                                              *
183 *   This function calls a Java-method (which possibly needs compilation)       *
184 *   with up to 4 address parameters.                                           *
185 *                                                                              *
186 *   This functions calls the JIT-compiler which eventually translates the      *
187 *   method into machine code.                                                  *
188 *                                                                              *
189 *   C-prototype:                                                               *
190 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
191 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
192 *                                                                              *
193 *******************************************************************************/
194
195 call_name2:
196         .align  8
197
198         .quad   0                         /* catch type all                       */
199         .quad   calljava_xhandler2        /* handler pc                           */
200         .quad   calljava_xhandler2        /* end pc                               */
201         .quad   asm_calljavafunction2     /* start pc                             */
202         .long   1                         /* extable size                         */
203         .long   0                         /* fltsave                              */
204         .long   0                         /* intsave                              */
205         .long   0                         /* isleaf                               */
206         .long   0                         /* IsSync                               */
207         .long   24                        /* frame size                           */
208         .quad   0                         /* method pointer (pointer to name)     */
209
210 asm_calljavafunction2:
211 asm_calljavafunction2int:
212 asm_calljavafunction2long:
213 asm_calljavafunction2float:
214 asm_calljavafunction2double:
215         sub     $(7*8),%rsp               /* keep stack 16-byte aligned           */
216         mov     %rbx,0*8(%rsp)            /* %rbx is not a callee saved in cacao  */
217         mov     %rbp,1*8(%rsp)
218         mov     %r12,2*8(%rsp)
219         mov     %r13,3*8(%rsp)
220         mov     %r14,4*8(%rsp)
221         mov     %r15,5*8(%rsp)
222
223         mov     %rdi,%rax                 /* move method pointer for compiler     */
224         xor     %rbp,%rbp                 /* set argument stack frame to zero     */
225
226         test    %rsi,%rsi                 /* maybe we have no args...             */
227         jle     L_copy_done
228
229         mov     %rsi,itmp3                /* arg count                            */
230         mov     %rcx,itmp2                /* pointer to arg block                 */
231
232         mov     itmp2,%r14                /* save argument block pointer          */
233         mov     itmp3,%r15                /* save argument count                  */
234
235         sub     $sizejniblock,itmp2       /* initialize pointer (smaller code)    */
236         add     $1,itmp3                  /* initialize argument count            */
237         xor     %r12,%r12                 /* initialize integer argument counter  */
238         xor     %r13,%r13                 /* initialize float argument counter    */
239
240 L_register_copy:
241         add     $sizejniblock,itmp2       /* goto next argument block             */
242         dec     itmp3                     /* argument count - 1                   */
243         jz      L_register_copy_done
244         andb    $0x02,offjniitemtype(itmp2) /* is this a float/double type?       */
245         jnz     L_register_handle_float   /* yes, handle it                       */
246
247         cmp     $INT_ARG_CNT,%r12         /* are we out of integer argument       */
248         je      L_register_copy           /* register? yes, next loop             */
249
250         lea     jumptable_integer,%rbp
251         mov     0(%rbp,%r12,8),%rbx
252         inc     %r12                      /* integer argument counter + 1         */
253         jmp     *%rbx
254
255 L_register_handle_float:
256         cmp     $FLT_ARG_CNT,%r13         /* are we out of float argument         */
257         je      L_register_copy           /* register? yes, next loop             */
258
259         lea     jumptable_float,%rbp
260         mov     0(%rbp,%r13,8),%rbx
261         inc     %r13                      /* float argument counter + 1           */
262         jmp     *%rbx
263         
264 L_register_copy_done:
265         mov     %r15,%rbp                 /* calculate remaining arguments        */
266         sub     %r12,%rbp                 /* - integer arguments in registers     */
267         sub     %r13,%rbp                 /* - float arguments in registers       */
268         jle     L_copy_done               /* are all assigned to registers?       */
269
270         shl     $3,%rbp                   /* calculate stack size                 */
271         sub     %rbp,%rsp                 /* stack frame for arguments            */
272         mov     %rsp,%rbx                 /* use %rbx as temp sp                  */
273
274         sub     $sizejniblock,%r14        /* initialize pointer (smaller code)    */
275         add     $1,%r15                   /* initialize argument count            */
276                 
277 L_stack_copy_loop:
278         add     $sizejniblock,%r14        /* goto next argument block             */
279         dec     %r15                      /* are there any arguments left?        */
280         jz      L_copy_done               /* no test needed after dec             */
281
282         andb    $0x02,offjniitemtype(%r14) /* is this a float/double type?        */
283         jnz     L_stack_handle_float
284         dec     %r12                      /* arguments assigned to registers      */
285         jge     L_stack_copy_loop
286         jmp     L_stack_copy
287
288 L_stack_handle_float:
289         dec     %r13                      /* arguments assigned to registers      */
290         jge     L_stack_copy_loop
291
292 L_stack_copy:
293     mov     offjniitem(%r14),itmp3    /* copy s8 argument onto stack          */
294     mov     itmp3,0(%rbx)
295     add     $8,%rbx                   /* increase sp to next argument         */
296         jmp     L_stack_copy_loop
297
298 L_copy_done:
299         lea     asm_call_jit_compiler,%r11/* %rax still contains method pointer   */
300         call    *%r11                     /* call JIT compiler                    */
301
302         add     %rbp,%rsp                 /* remove argument stack frame if any   */
303
304         mov     5*8(%rsp),%r15            /* restore callee saved registers       */
305         mov     4*8(%rsp),%r14
306         mov     3*8(%rsp),%r13
307         mov     2*8(%rsp),%r12
308         mov     1*8(%rsp),%rbp
309         mov     0*8(%rsp),%rbx
310         add     $(7*8),%rsp               /* free stack space                     */
311         ret
312                 
313 calljava_xhandler2:
314         mov     %rax,%rdi                 /* pass exception pointer               */
315         call    builtin_throw_exception
316
317         mov     5*8(%rsp),%r15            /* restore callee saved registers       */
318         mov     4*8(%rsp),%r14
319         mov     3*8(%rsp),%r13
320         mov     2*8(%rsp),%r12
321         mov     1*8(%rsp),%rbp
322         mov     0*8(%rsp),%rbx
323         add     $(7*8),%rsp               /* free stack space                     */
324         xor     %rax,%rax                 /* return NULL                          */
325         ret
326
327
328 jumptable_integer:
329         .quad   handle_a0
330         .quad   handle_a1
331         .quad   handle_a2
332         .quad   handle_a3
333         .quad   handle_a4
334         .quad   handle_a5
335
336 handle_a0:
337         mov     offjniitem(itmp2),a0
338         jmp     L_register_copy
339 handle_a1:
340         mov     offjniitem(itmp2),a1
341         jmp     L_register_copy
342 handle_a2:
343         mov     offjniitem(itmp2),a2
344         jmp     L_register_copy
345 handle_a3:
346         mov     offjniitem(itmp2),a3
347         jmp     L_register_copy
348 handle_a4:
349         mov     offjniitem(itmp2),a4
350         jmp     L_register_copy
351 handle_a5:
352         mov     offjniitem(itmp2),a5
353         jmp     L_register_copy
354
355
356 jumptable_float:
357         .quad   handle_fa0
358         .quad   handle_fa1
359         .quad   handle_fa2
360         .quad   handle_fa3
361         .quad   handle_fa4
362         .quad   handle_fa5
363         .quad   handle_fa6
364         .quad   handle_fa7
365
366 handle_fa0:
367         movq    offjniitem(itmp2),fa0
368         jmp     L_register_copy
369 handle_fa1:
370         movq    offjniitem(itmp2),fa1
371         jmp     L_register_copy
372 handle_fa2:
373         movq    offjniitem(itmp2),fa2
374         jmp     L_register_copy
375 handle_fa3:
376         movq    offjniitem(itmp2),fa3
377         jmp     L_register_copy
378 handle_fa4:
379         movq    offjniitem(itmp2),fa4
380         jmp     L_register_copy
381 handle_fa5:
382         movq    offjniitem(itmp2),fa5
383         jmp     L_register_copy
384 handle_fa6:
385         movq    offjniitem(itmp2),fa6
386         jmp     L_register_copy
387 handle_fa7:
388         movq    offjniitem(itmp2),fa7
389         jmp     L_register_copy
390
391
392 /****************** function asm_call_jit_compiler *****************************
393 *                                                                              *
394 *   invokes the compiler for untranslated JavaVM methods.                      *
395 *                                                                              *
396 *   Register R0 contains a pointer to the method info structure (prepared      *
397 *   by createcompilerstub). Using the return address in R26 and the            *
398 *   offset in the LDA instruction or using the value in methodptr R28 the      *
399 *   patching address for storing the method address can be computed:           *
400 *                                                                              *
401 *   method address was either loaded using                                     *
402 *                                                                              *
403 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
404 *   i386_call_reg(REG_ITMP2)                                                   *
405 *                                                                              *
406 *   or                                                                         *
407 *                                                                              *
408 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
409 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
410 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
411 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
412 *   i386_call_reg(REG_ITMP1)                                                   *
413 *                                                                              *
414 *   in the static case the method pointer can be computed using the            *
415 *   return address and the lda function following the jmp instruction          *
416 *                                                                              *
417 *******************************************************************************/
418
419 asm_call_jit_compiler:
420         sub     $8,%rsp                 /* keep stack 16-byte aligned             */
421
422         mov     %rbx,(%rsp)             /* save register                          */
423         
424         mov     8(%rsp),%r11    /* get return address                         */
425         mov     -1(%r11),%bl    /* get function code                          */
426         cmp     $0xd2,%bl               /* called with `call *REG_ITMP2' (%r10)?      */
427         jne     L_not_static_special
428
429         sub     $11,%r11        /* calculate address of immediate             */
430         jmp             L_call_jit_compile
431                 
432 L_not_static_special:
433                 cmp     $0xd0,%bl               /* called with `call *REG_ITMP1' (%rax)       */
434                 jne     L_not_virtual_interface
435                 
436                 sub     $7,%r11         /* calculate address of offset                */
437                 mov     (%r11),%r11d    /* get offset (32-bit)                        */
438                 add     %r10,%r11       /* add base address to get method address     */
439                 jmp     L_call_jit_compile
440
441 L_not_virtual_interface:        /* a call from asm_calljavamethod             */
442                 xor     %r11,%r11
443                 
444 L_call_jit_compile:
445         mov     (%rsp),%rbx     /* restore register                           */
446         
447         sub     $(24*8),%rsp    /* 8 + 6*8 + 8*8 + 8*8                        */
448         
449                 mov     %r11,0*8(%rsp)  /* save address for method pointer            */
450
451         mov     a0,1*8(%rsp)    /* save arguments                             */
452         mov     a1,2*8(%rsp)
453         mov     a2,3*8(%rsp)
454         mov     a3,4*8(%rsp)
455         mov     a4,5*8(%rsp)
456         mov     a5,6*8(%rsp)
457
458         movq    fa0,7*8(%rsp)
459         movq    fa1,8*8(%rsp)
460         movq    fa2,9*8(%rsp)
461         movq    fa3,10*8(%rsp)
462         movq    fa4,11*8(%rsp)
463         movq    fa5,12*8(%rsp)
464         movq    fa6,13*8(%rsp)
465         movq    fa7,14*8(%rsp)
466
467         movq    %xmm8,15*8(%rsp)/* we use them as callee saved registers      */
468         movq    %xmm9,16*8(%rsp)
469         movq    %xmm10,17*8(%rsp)
470         movq    %xmm11,18*8(%rsp)
471         movq    %xmm12,19*8(%rsp)
472         movq    %xmm13,20*8(%rsp)
473         movq    %xmm14,21*8(%rsp)
474         movq    %xmm15,22*8(%rsp)
475
476         mov     %rax,%rdi       /* pass method pointer                        */
477                 call    jit_compile
478
479         mov     0*8(%rsp),%r11
480         
481         mov     1*8(%rsp),a0
482         mov     2*8(%rsp),a1
483         mov     3*8(%rsp),a2
484         mov     4*8(%rsp),a3
485         mov     5*8(%rsp),a4
486         mov     6*8(%rsp),a5
487
488         movq    7*8(%rsp),fa0
489         movq    8*8(%rsp),fa1
490         movq    9*8(%rsp),fa2
491         movq    10*8(%rsp),fa3
492         movq    11*8(%rsp),fa4
493         movq    12*8(%rsp),fa5
494         movq    13*8(%rsp),fa6
495         movq    14*8(%rsp),fa7
496
497         movq    15*8(%rsp),%xmm8
498         movq    16*8(%rsp),%xmm9
499         movq    17*8(%rsp),%xmm10
500         movq    18*8(%rsp),%xmm11
501         movq    19*8(%rsp),%xmm12
502         movq    20*8(%rsp),%xmm13
503         movq    21*8(%rsp),%xmm14
504         movq    22*8(%rsp),%xmm15
505
506         add     $(24*8),%rsp
507         add     $8,%rsp                 /* keep stack 16-byte aligned             */
508
509         test    %rax,%rax               /* check for exception                    */
510         je      L_asm_call_jit_compiler_exception
511
512         test    %r11,%r11               /* is address == 0 (asm_calljavamethod)   */
513         je      L_call_method
514
515         mov     %rax,(%r11)             /* and now save the new pointer           */
516
517 L_call_method:
518         jmp     *%rax                   /* ...and now call the new method         */
519
520 L_asm_call_jit_compiler_exception:
521 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
522         call    builtin_asm_get_exceptionptrptr
523         mov     %rax,itmp2
524 #else
525         lea     _exceptionptr,itmp2
526 #endif
527         mov     (itmp2),xptr                /* get the exception pointer          */
528         movl    $0,(itmp2)                  /* clear the exception pointer        */
529
530         pop     xpc                         /* delete return address              */
531         sub     $5,xpc                      /* faulting address is ra - 5         */
532
533         jmp     asm_handle_exception
534
535
536 /********************* function asm_handle_exception ***************************
537 *                                                                              *
538 *   This function handles an exception. It does not use the usual calling      *
539 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
540 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
541 *   the local exception table for a handler. If no one is found, it unwinds    *
542 *   stacks and continues searching the callers.                                *
543 *                                                                              *
544 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
545 *                                                                              *
546 *******************************************************************************/
547
548 asm_handle_nat_exception:
549         add     $8,%rsp                     /* clear return address of native stub*/
550                 
551 asm_handle_exception:
552         sub     $(4*8),%rsp
553         mov     xptr,0*8(%rsp)              /* save exception pointer             */
554         mov     xpc,1*8(%rsp)               /* save exception pc                  */
555         
556         mov     xpc,%rdi                    /* exception pc                       */
557         call    codegen_findmethod
558         mov     %rax,itmp3
559         mov     %rax,2*8(%rsp)              /* save data segment pointer          */
560         
561         mov     0*8(%rsp),%rax              /* restore exception pointer          */
562         mov     1*8(%rsp),%r10              /* restore exception pc               */
563         
564 ex_stack_loop:
565         mov     %rax,%rdi                   /* exception pointer                  */
566         mov     MethodPointer(itmp3),%rsi   /* method pointer                     */
567         mov     xpc,%rdx                    /* exception pc                       */
568         mov     $0,%rcx
569         mov     $1,%r8                      /* set noindent flag                  */
570         call    builtin_trace_exception
571
572         mov     2*8(%rsp),itmp3             /* %r11 = data segment pointer        */
573         mov     ExTableSize(itmp3),%rcx     /* %rcx = exception table size        */
574         test    %rcx,%rcx                                       /* if empty table skip                */
575         je      empty_table
576
577         lea     ExTableStart(itmp3),%rdi    /* %rdi = start of exception table    */
578         mov     0*8(%rsp),xptr              /* get xptr                           */
579                 
580 ex_table_loop:
581         mov     1*8(%rsp),xpc               /* get xpc                            */
582                 
583         mov     ExStartPC(%rdi),%rdx        /* %rdx = exception start pc          */
584         cmp     xpc,%rdx                    /* %rdx = (startpc <= xpc)            */
585         jg      ex_table_cont               /* if (false) continue                */
586         mov     ExEndPC(%rdi),%rdx          /* %rdx = exception end pc            */
587         cmp     %rdx,xpc                    /* %rdx = (xpc < endpc)               */
588         jge     ex_table_cont               /* if (false) continue                */
589         mov     ExCatchType(%rdi),%rdx      /* %rdx = exception catch type        */
590         test    %rdx,%rdx                   /* NULL catches everything            */
591         je      ex_handle_it
592
593         cmpl    $0,offclassloaded(%rdx)     /* check if class is loaded           */
594         jne     L_class_loaded
595
596         sub     $(4*8),%rsp
597         mov     %rax,0*8(%rsp)
598         mov     %rcx,1*8(%rsp)
599         mov     %rdx,2*8(%rsp)
600         mov     %rdi,3*8(%rsp)
601
602         mov     %rdx,%rdi
603         call    load_class_bootstrap
604
605         mov     0*8(%rsp),%rax
606         mov     1*8(%rsp),%rcx
607         mov     2*8(%rsp),%rdx
608         mov     3*8(%rsp),%rdi
609         add     $(4*8),%rsp
610
611 L_class_loaded:
612         cmpl    $0,offclasslinked(%rdx)     /* check if class is linked           */
613         jne     L_class_linked
614
615         sub     $(4*8),%rsp
616         mov     %rax,0*8(%rsp)
617         mov     %rcx,1*8(%rsp)
618         mov     %rdx,2*8(%rsp)
619         mov     %rdi,3*8(%rsp)
620
621         mov     %rdx,%rdi
622         call    link_class
623
624         mov     0*8(%rsp),%rax
625         mov     1*8(%rsp),%rcx
626         mov     2*8(%rsp),%rdx
627         mov     3*8(%rsp),%rdi
628         add     $(4*8),%rsp
629
630 L_class_linked:
631 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
632         push    %rdx
633
634 _crit_restart1:
635         mov     0(%rsp),%rdx
636 #endif
637
638 _crit_begin1:
639         mov     offobjvftbl(%rax),%rsi      /* %rsi = vftblptr(xptr)              */
640         mov     offclassvftbl(%rdx),%rdx    /* %rdx = vftblptr(catchtype) class (not obj) */
641         mov     offbaseval(%rsi),%esi       /* %esi = baseval(xptr)               */
642         mov     offbaseval(%rdx),%r10d      /* %r10d = baseval(catchtype)         */
643         mov     offdiffval(%rdx),%edx       /* %edx = diffval(catchtype)          */
644 _crit_end1:
645         sub     %r10d,%esi                  /* %esi = baseval(xptr) - baseval(catchtype) */
646
647 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
648         add     $8,%rsp
649 #endif
650
651         cmp     %edx,%esi                   /* xptr is instanceof catchtype       */
652         ja      ex_table_cont
653                 
654 ex_handle_it:
655                 mov     ExHandlerPC(%rdi),xpc       /* xpc = exception handler pc     */
656
657         mov     0*8(%rsp),%rax              /* restore exception pointer      */
658         add     $(4*8),%rsp                 /* free stack frame               */
659
660         jmp             *xpc                        /* jump to the handler            */
661
662 ex_table_cont:
663         lea             ExEntrySize(%rdi),%rdi      /* next exception table entry     */
664         dec     %rcx                        /* decrement entry counter        */
665         test    %rcx,%rcx                   /* if (t0 > 0) next entry         */
666         jg              ex_table_loop
667                 
668 empty_table:
669         mov     0*8(%rsp),%rax              /* restore exception pointer      */
670         mov     1*8(%rsp),%r10              /* restore exception pc           */
671         mov     2*8(%rsp),%r11                          /* restore data segment pointer   */
672         add     $(4*8),%rsp
673         
674                 mov     %rax,%rcx                                       /* save exception pointer         */
675                                 
676 ex_already_cleared:             
677                 movl    IsSync(%r11),%eax                       /* %rax = SyncOffset              */
678                 test    %rax,%rax                                       /* if zero no monitorexit         */
679                 je              no_monitor_exit
680
681 #if defined(USE_THREADS)                
682                 add     %rsp,%rax
683                 mov     -8(%rax),%rdi
684
685         sub     $(4*8),%rsp
686         mov     %rcx,0*8(%rsp)
687         mov     %r10,1*8(%rsp)
688         mov     %r11,2*8(%rsp)
689         
690                 call    builtin_monitorexit
691
692         mov     0*8(%rsp),%rcx
693         mov     1*8(%rsp),%r10
694         mov     2*8(%rsp),%r11
695         add     $(4*8),%rsp
696 #endif
697
698 no_monitor_exit:
699                 mov             FrameSize(%r11),%eax        /* %eax = frame size              */
700                 add             %rax,%rsp                   /* unwind stack                   */
701                 mov             %rsp,%rax                   /* %rax = pointer to save area    */
702
703                 mov             IntSave(%r11),%edx          /* %edx = saved int register count*/
704         test    %edx,%edx
705         je              noint
706         
707                 cmp     $1,%edx
708                 je              int1
709                 cmp             $2,%edx
710                 je              int2
711                 cmp             $3,%edx
712                 je              int3
713                 cmp             $4,%edx
714                 je              int4
715                 cmp             $5,%edx
716                 je              int5
717         
718         mov     -48(%rax),%rbx
719 int5:   
720         mov     -40(%rax),%rbp
721 int4:   
722         mov     -32(%rax),%r12
723 int3:   
724         mov     -24(%rax),%r13
725 int2:   
726                 mov     -16(%rax),%r14
727 int1:   
728                 mov     -8(%rax),%r15
729
730                 shl             $3,%edx                     /* multiply by 8 bytes            */
731                 sub     %rdx,%rax
732                 
733 noint:
734                 mov     FltSave(%r11),%edx          /* %edx = saved flt register count*/
735                 test    %edx,%edx
736                 je      noflt
737
738         cmpl    $1,%edx
739         je      flt1
740         cmpl    $2,%edx
741         je      flt2
742         cmpl    $3,%edx
743         je      flt3
744         cmpl    $4,%edx
745         je      flt4
746         cmpl    $5,%edx
747         je      flt5
748         cmpl    $6,%edx
749         je      flt7
750         cmpl    $7,%edx
751         je      flt7
752
753         movq    -64(%rax),%xmm8
754 flt7:   
755         movq    -56(%rax),%xmm9
756 flt6:   
757         movq    -48(%rax),%xmm10
758 flt5:   
759         movq    -40(%rax),%xmm11
760 flt4:   
761         movq    -32(%rax),%xmm12
762 flt3:   
763         movq    -24(%rax),%xmm13
764 flt2:   
765         movq    -16(%rax),%xmm14
766 flt1:   
767         movq    -8(%rax),%xmm15
768                 
769 noflt:                                  
770                 pop     %r10                                            /* the new xpc is return address  */
771                 sub     $3,%r10                     /* subtract 3 bytes for call      */
772
773         sub     $(2*8),%rsp
774         mov     %rcx,0*8(%rsp)
775         mov     %r10,1*8(%rsp)
776
777         mov     %r10,%rdi
778         call    codegen_findmethod          /* get the new data segment ptr   */
779         mov     %rax,%r11
780         
781         mov     0*8(%rsp),%rcx
782         mov     1*8(%rsp),%r10
783         add     $(2*8),%rsp
784
785         mov     %rcx,%rax                                       /* restore saved exception pointer*/
786
787         sub     $(4*8),%rsp
788                                         
789         mov     %rax,0*8(%rsp)              /* save exception pointer         */
790         mov     %r10,1*8(%rsp)              /* save exception pc              */
791                 mov     %r11,2*8(%rsp)                          /* save data segment pointer      */
792                 
793                 jmp             ex_stack_loop
794
795
796 /* asm_check_clinit ************************************************************
797
798    DOCUMENT ME!!!
799
800    Arguments:
801
802         itmp1   class   ; pointer to class
803         itmp2   mcode   ; machine code to patch back in
804
805    Stack layout:
806
807         0  ra      ; return address of patched call in java machine code
808
809 *******************************************************************************/
810
811 asm_check_clinit:
812         mov     offclassinit(itmp1),itmp3l  /* get initialized flag (int)         */
813         test    itmp3,itmp3
814         jnz     L_is_initialized
815
816         sub     $(17*8),%rsp                /* keep stack 16-byte aligned         */
817
818         mov     a0,0*8(%rsp)                /* save argument registers            */
819         mov     a1,1*8(%rsp)
820         mov     a2,2*8(%rsp)
821         mov     a3,3*8(%rsp)
822         mov     a4,4*8(%rsp)
823         mov     a5,5*8(%rsp)
824
825         movq    fa0,6*8(%rsp)               /* maybe cacao does not use all 8     */
826         movq    fa1,7*8(%rsp)               /* argument register, but who knows   */
827         movq    fa2,8*8(%rsp)
828         movq    fa3,9*8(%rsp)
829         movq    fa4,10*8(%rsp)
830         movq    fa5,11*8(%rsp)
831         movq    fa6,12*8(%rsp)
832         movq    fa7,13*8(%rsp)
833
834         mov     itmp2,14*8(%rsp)            /* save machine code                  */
835
836         mov     itmp1,a0                    /* pass classinfo pointer             */
837         call    initialize_class            /* call class initialize function     */
838         
839         mov     0*8(%rsp),a0                /* restore argument registers         */
840         mov     1*8(%rsp),a1
841         mov     2*8(%rsp),a2
842         mov     3*8(%rsp),a3
843         mov     4*8(%rsp),a4
844         mov     5*8(%rsp),a5
845
846         movq    6*8(%rsp),fa0
847         movq    7*8(%rsp),fa1
848         movq    8*8(%rsp),fa2
849         movq    9*8(%rsp),fa3
850         movq    10*8(%rsp),fa4
851         movq    11*8(%rsp),fa5
852         movq    12*8(%rsp),fa6
853         movq    13*8(%rsp),fa7
854
855         mov     14*8(%rsp),itmp2            /* restore machine code               */
856
857         add     $(17*8),%rsp                /* remove stack frame                 */
858
859         test    v0,v0                       /* we had an exception                */
860         je      L_initializererror
861
862 L_is_initialized:
863         pop     itmp1                       /* get return address                 */
864         sub     $5,itmp1                    /* remove size of `call rel32'        */
865         mov     itmp2,(itmp1)               /* patch back in 8 bytes              */
866         jmp     *itmp1                      /* jump to patched code an execute it */
867
868 L_initializererror:
869 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
870         call    builtin_asm_get_exceptionptrptr
871         mov     %rax,itmp2
872 #else
873         lea     _exceptionptr,itmp2
874 #endif
875         mov     (itmp2),xptr                /* get the exception pointer          */
876         movl    $0,(itmp2)                  /* clear the exception pointer        */
877
878         pop     xpc                         /* delete return address              */
879         sub     $5,xpc                      /* faulting address is ra - 5         */
880         jmp     asm_handle_exception
881                 
882
883 /* asm_builtin_new *************************************************************
884
885    XXX
886
887    Arguments:
888      a0   contains the class reference
889
890 *******************************************************************************/
891
892 asm_builtin_new:
893         sub     $(8*1),%rsp                 /* stack frame (16-byte aligned)      */
894         mov     8*1(%rsp),a1                /* get return address                 */
895         call    asm_builtin_new_helper      /* call the helper function           */
896         add     $(8*1),%rsp                 /* remove stack frame                 */
897         test    v0,v0                       /* exception thrown?                  */
898         jz      L_asm_builtin_new_exception
899
900         pop     itmp2                       /* get return address                 */
901         sub     $(3+10+10),itmp2            /* 3 (callq) + 10 (movi) + 10 (movi)  */
902         mov     v0,2(itmp2)                 /* patch in new classinfo*: 2 (mov)   */
903
904         lea     builtin_new,itmp1           /* get address from builtin_new       */
905         mov     itmp1,12(itmp2)             /* patch back in function address     */
906         jmp     *itmp2                      /* call new patched code              */
907
908 L_asm_builtin_new_exception:
909 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
910         call    builtin_asm_get_exceptionptrptr
911         mov     %rax,itmp2
912 #else
913         lea     _exceptionptr,itmp2
914 #endif
915         mov     (itmp2),xptr                /* get the exception pointer          */
916         movl    $0,(itmp2)                  /* clear the exception pointer        */
917
918         pop     xpc                         /* delete return address              */
919         sub     $5,xpc                      /* faulting address is ra - 5         */
920         jmp     asm_handle_exception
921
922
923 /* asm_builtin_new *************************************************************
924
925    XXX
926
927    Arguments:
928      itmp1   contains the method reference
929      itmp2   machine code (which is patched back later)
930
931 *******************************************************************************/
932
933 asm_invokespecial:
934         sub     $(7*8),%rsp                 /* stack frame (16-byte aligned)      */
935         mov     a0,0*8(%rsp)                /* save argument registers            */
936         mov     a1,1*8(%rsp)
937         mov     a2,2*8(%rsp)
938         mov     a3,3*8(%rsp)
939         mov     a4,4*8(%rsp)
940         mov     a5,5*8(%rsp)
941
942         mov     itmp2,6*8(%rsp)             /* save machine code                  */
943
944         mov     itmp1,a0                    /* pass unresolved_method pointer     */
945         call    asm_invokespecial_helper    /* call the helper function           */
946
947         mov     0*8(%rsp),a0                /* restore argument registers         */
948         mov     1*8(%rsp),a1
949         mov     2*8(%rsp),a2
950         mov     3*8(%rsp),a3
951         mov     4*8(%rsp),a4
952         mov     5*8(%rsp),a5
953
954         mov     6*8(%rsp),itmp3             /* restore machine code               */
955
956         add     $(7*8),%rsp                 /* remove stack frame                 */
957         test    v0,v0                       /* exception thrown?                  */
958         jz      L_asm_builtin_new_exception
959
960         pop     itmp2                       /* get return address                 */
961         sub     $5,itmp2                    /* remove size of `call rel32'        */
962         mov     itmp3,(itmp2)               /* patch back original code (8 bytes) */
963
964         mov     v0,5(itmp2)                 /* patch stubroutine: 3 + 2 (mov)     */
965         jmp     *itmp2                      /* call new patched code              */
966
967
968 /********************* function asm_builtin_monitorenter ***********************
969 *                                                                              *
970 *   Does null check and calls monitorenter or throws an exception              *
971 *                                                                              *
972 *******************************************************************************/
973
974 #if defined(USE_THREADS)
975 asm_builtin_monitorenter:
976         test    %rdi,%rdi
977         je      nb_monitorenter             /* if (null) throw exception          */
978         jmp     builtin_monitorenter        /* else call builtin_monitorenter     */
979
980 nb_monitorenter:
981         call    new_nullpointerexception
982         pop     %r10                        /* delete return address              */
983         sub     $3,%r10                     /* faulting address is ra - 3         */
984         jmp     asm_handle_exception
985 #endif
986                 
987
988 /********************* function asm_builtin_monitorexit ************************
989 *                                                                              *
990 *   Does null check and calls monitorexit or throws an exception               *
991 *                                                                              *
992 *******************************************************************************/
993
994 #if defined(USE_THREADS)
995 asm_builtin_monitorexit:
996         test    %rdi,%rdi
997         je      nb_monitorexit              /* if (null) throw exception          */
998         jmp     builtin_monitorexit         /* else call builtin_monitorenter     */
999
1000 nb_monitorexit:
1001         call    new_nullpointerexception
1002         pop     %r10                        /* delete return address              */
1003         sub     $3,%r10                     /* faulting address is ra - 3         */
1004         jmp     asm_handle_exception
1005 #endif
1006
1007
1008 /********************* function asm_builtin_x2x ********************************
1009 *                                                                              *
1010 *   Wrapper functions for float to int corner cases                            *
1011 *                                                                              *
1012 *******************************************************************************/
1013
1014 asm_builtin_f2i:
1015         sub     $(14*8),%rsp
1016         
1017         mov     %rdi,0*8(%rsp)
1018         mov     %rsi,1*8(%rsp)
1019         mov     %rdx,2*8(%rsp)
1020         mov     %rcx,3*8(%rsp)
1021         mov     %r8,4*8(%rsp)
1022         mov     %r9,5*8(%rsp)
1023         
1024         movq    %xmm0,6*8(%rsp)
1025         movq    %xmm1,7*8(%rsp)
1026         movq    %xmm2,8*8(%rsp)
1027         movq    %xmm3,9*8(%rsp)
1028         movq    %xmm4,10*8(%rsp)
1029         movq    %xmm5,11*8(%rsp)
1030         movq    %xmm6,12*8(%rsp)
1031         movq    %xmm7,13*8(%rsp)
1032         
1033         movq    %xmm8,%xmm0
1034         call    builtin_f2i
1035         
1036         mov     0*8(%rsp),%rdi
1037         mov     1*8(%rsp),%rsi
1038         mov     2*8(%rsp),%rdx
1039         mov     3*8(%rsp),%rcx
1040         mov     4*8(%rsp),%r8
1041         mov     5*8(%rsp),%r9
1042         
1043         movq    6*8(%rsp),%xmm0
1044         movq    7*8(%rsp),%xmm1
1045         movq    8*8(%rsp),%xmm2
1046         movq    9*8(%rsp),%xmm3
1047         movq    10*8(%rsp),%xmm4
1048         movq    11*8(%rsp),%xmm5
1049         movq    12*8(%rsp),%xmm6
1050         movq    13*8(%rsp),%xmm7
1051         
1052         add     $(14*8),%rsp
1053         ret
1054
1055
1056 asm_builtin_f2l:
1057         sub     $(14*8),%rsp
1058         
1059         mov     %rdi,0*8(%rsp)
1060         mov     %rsi,1*8(%rsp)
1061         mov     %rdx,2*8(%rsp)
1062         mov     %rcx,3*8(%rsp)
1063         mov     %r8,4*8(%rsp)
1064         mov     %r9,5*8(%rsp)
1065         
1066         movq    %xmm0,6*8(%rsp)
1067         movq    %xmm1,7*8(%rsp)
1068         movq    %xmm2,8*8(%rsp)
1069         movq    %xmm3,9*8(%rsp)
1070         movq    %xmm4,10*8(%rsp)
1071         movq    %xmm5,11*8(%rsp)
1072         movq    %xmm6,12*8(%rsp)
1073         movq    %xmm7,13*8(%rsp)
1074         
1075         movq    %xmm8,%xmm0
1076         call    builtin_f2l
1077         
1078         mov     0*8(%rsp),%rdi
1079         mov     1*8(%rsp),%rsi
1080         mov     2*8(%rsp),%rdx
1081         mov     3*8(%rsp),%rcx
1082         mov     4*8(%rsp),%r8
1083         mov     5*8(%rsp),%r9
1084         
1085         movq    6*8(%rsp),%xmm0
1086         movq    7*8(%rsp),%xmm1
1087         movq    8*8(%rsp),%xmm2
1088         movq    9*8(%rsp),%xmm3
1089         movq    10*8(%rsp),%xmm4
1090         movq    11*8(%rsp),%xmm5
1091         movq    12*8(%rsp),%xmm6
1092         movq    13*8(%rsp),%xmm7
1093         
1094         add     $(14*8),%rsp
1095         ret
1096
1097
1098 asm_builtin_d2i:
1099         sub     $(14*8),%rsp
1100         
1101         mov     %rdi,0*8(%rsp)
1102         mov     %rsi,1*8(%rsp)
1103         mov     %rdx,2*8(%rsp)
1104         mov     %rcx,3*8(%rsp)
1105         mov     %r8,4*8(%rsp)
1106         mov     %r9,5*8(%rsp)
1107         
1108         movq    %xmm0,6*8(%rsp)
1109         movq    %xmm1,7*8(%rsp)
1110         movq    %xmm2,8*8(%rsp)
1111         movq    %xmm3,9*8(%rsp)
1112         movq    %xmm4,10*8(%rsp)
1113         movq    %xmm5,11*8(%rsp)
1114         movq    %xmm6,12*8(%rsp)
1115         movq    %xmm7,13*8(%rsp)
1116         
1117         movq    %xmm8,%xmm0
1118         call    builtin_d2i
1119         
1120         mov     0*8(%rsp),%rdi
1121         mov     1*8(%rsp),%rsi
1122         mov     2*8(%rsp),%rdx
1123         mov     3*8(%rsp),%rcx
1124         mov     4*8(%rsp),%r8
1125         mov     5*8(%rsp),%r9
1126         
1127         movq    6*8(%rsp),%xmm0
1128         movq    7*8(%rsp),%xmm1
1129         movq    8*8(%rsp),%xmm2
1130         movq    9*8(%rsp),%xmm3
1131         movq    10*8(%rsp),%xmm4
1132         movq    11*8(%rsp),%xmm5
1133         movq    12*8(%rsp),%xmm6
1134         movq    13*8(%rsp),%xmm7
1135         
1136         add     $(14*8),%rsp
1137         ret
1138
1139
1140 asm_builtin_d2l:
1141         sub     $(14*8),%rsp
1142         
1143         mov     %rdi,0*8(%rsp)
1144         mov     %rsi,1*8(%rsp)
1145         mov     %rdx,2*8(%rsp)
1146         mov     %rcx,3*8(%rsp)
1147         mov     %r8,4*8(%rsp)
1148         mov     %r9,5*8(%rsp)
1149         
1150         movq    %xmm0,6*8(%rsp)
1151         movq    %xmm1,7*8(%rsp)
1152         movq    %xmm2,8*8(%rsp)
1153         movq    %xmm3,9*8(%rsp)
1154         movq    %xmm4,10*8(%rsp)
1155         movq    %xmm5,11*8(%rsp)
1156         movq    %xmm6,12*8(%rsp)
1157         movq    %xmm7,13*8(%rsp)
1158         
1159         movq    %xmm8,%xmm0
1160         call    builtin_d2l
1161         
1162         mov     0*8(%rsp),%rdi
1163         mov     1*8(%rsp),%rsi
1164         mov     2*8(%rsp),%rdx
1165         mov     3*8(%rsp),%rcx
1166         mov     4*8(%rsp),%r8
1167         mov     5*8(%rsp),%r9
1168         
1169         movq    6*8(%rsp),%xmm0
1170         movq    7*8(%rsp),%xmm1
1171         movq    8*8(%rsp),%xmm2
1172         movq    9*8(%rsp),%xmm3
1173         movq    10*8(%rsp),%xmm4
1174         movq    11*8(%rsp),%xmm5
1175         movq    12*8(%rsp),%xmm6
1176         movq    13*8(%rsp),%xmm7
1177         
1178         add     $(14*8),%rsp
1179         ret
1180
1181
1182 /* asm_builtin_checkarraycast **************************************************
1183
1184    Does the cast check and eventually throws an exception.
1185
1186 *******************************************************************************/
1187
1188 asm_builtin_checkarraycast:
1189         sub     $24,%rsp                    /* keep stack 16-byte aligned         */
1190         mov     %rdi,(%rsp)                 /* save object pointer                */
1191         call    builtin_checkarraycast      /* builtin_checkarraycast             */
1192         test    %rax,%rax                   /* if (false) throw exception         */
1193         je      nb_carray_throw
1194         mov     (%rsp),%rax                 /* return object pointer              */
1195         add     $24,%rsp                    /* free stack space                   */
1196         ret
1197
1198 nb_carray_throw:
1199         call    new_classcastexception
1200         add     $24,%rsp
1201         pop     %r10                        /* delete return address              */
1202         sub     $3,%r10                     /* faulting address is ra - 3         */
1203         jmp     asm_handle_exception
1204
1205                 
1206 /* asm_builtin_aastore *********************************************************
1207
1208    Checks if the object can be stored in the given array and stores the
1209    address if it's possible. This function can also throw some exceptions.
1210
1211 *******************************************************************************/
1212
1213 asm_builtin_aastore:
1214         sub     $(3*8),%rsp             /* allocate stack space                   */
1215         test    %rdi,%rdi               /* if null pointer throw exception        */
1216         je      nb_aastore_null
1217
1218         movl    offarraysize(%rdi),%eax /* load size                              */
1219         cmpl    %eax,%esi               /* do bound check                         */
1220         jae     nb_aastore_bound        /* if out of bounds throw exception       */
1221
1222         shl     $3,%rsi                 /* index * 8                              */
1223         mov     %rdi,%r10
1224         add     %rsi,%r10               /* add index * 8 to arrayref              */
1225
1226         mov     %r10,(%rsp)             /* save store position                    */
1227         mov     %rdx,8(%rsp)            /* save object                            */
1228
1229         mov     %rdx,%rsi               /* object is second argument              */
1230         call    builtin_canstore        /* builtin_canstore(arrayref,object)      */
1231         test    %rax,%rax               /* if (false) throw exception             */
1232         je      nb_aastore_throw
1233
1234         mov     (%rsp),%r10             /* restore store position                 */
1235         mov     8(%rsp),%rdx            /* restore object                         */
1236         mov     %rdx,offobjarrdata(%r10)/* store objectptr in array               */
1237         add     $(3*8),%rsp             /* free stack space                       */
1238         ret
1239
1240 nb_aastore_null:
1241         call    new_nullpointerexception
1242         add     $24,%rsp
1243         pop     %r10                    /* delete return address                  */
1244         sub     $3,%r10                 /* faulting address is return adress - 3  */
1245         jmp     asm_handle_exception
1246
1247 nb_aastore_bound:
1248         mov     %rsi,%rdi               /* move index into a0                     */
1249         call    new_arrayindexoutofboundsexception
1250         add     $24,%rsp
1251         pop     %r10                    /* delete return address                  */
1252         sub     $3,%r10                 /* faulting address is return adress - 3  */
1253         jmp     asm_handle_exception
1254                 
1255 nb_aastore_throw:
1256         call    new_arraystoreexception
1257         add     $24,%rsp
1258         pop     %r10                    /* delete return address                  */
1259         sub     $3,%r10                 /* faulting address is return adress - 3  */
1260         jmp     asm_handle_exception
1261
1262                 
1263 /******************* function asm_initialize_thread_stack **********************
1264 *                                                                              *
1265 * initialized a thread stack                                                   *
1266 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
1267 *                                                                              *
1268 *******************************************************************************/
1269
1270 asm_initialize_thread_stack:
1271         sub     $(7*8),%rsi
1272
1273         xor     %r10,%r10
1274         mov     %r10,0*8(%rsi)
1275         mov     %r10,1*8(%rsi)
1276         mov     %r10,2*8(%rsi)
1277         mov     %r10,3*8(%rsi)
1278         mov     %r10,4*8(%rsi)
1279         mov     %r10,5*8(%rsi)
1280
1281         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
1282         mov     %rsi,%rax               /* return restorepoint in %rax        */
1283         ret
1284
1285
1286 /******************* function asm_perform_threadswitch *************************
1287 *                                                                              *
1288 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
1289 *                                                                              *
1290 *   performs a threadswitch                                                    *
1291 *                                                                              *
1292 *******************************************************************************/
1293
1294 asm_perform_threadswitch:
1295         sub     $(7*8),%rsp             /* allocate stack frame               */
1296
1297         mov     %rbx,0*8(%rsp)
1298         mov     %rbp,1*8(%rsp)
1299         mov     %r12,2*8(%rsp)
1300         mov     %r13,3*8(%rsp)
1301         mov     %r14,4*8(%rsp)
1302         mov     %r15,5*8(%rsp)
1303
1304         mov     7*8(%rsp),%rax                  /* save current return address        */
1305         mov     %rax,6*8(%rsp)
1306
1307         mov     %rsp,(%rdi)                     /* first argument **from              */
1308         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
1309
1310         mov     (%rsi),%rsp                     /* load new stack pointer             */
1311
1312         mov     0*8(%rsp),%rbx
1313         mov     1*8(%rsp),%rbp
1314         mov     2*8(%rsp),%r12
1315         mov     3*8(%rsp),%r13
1316         mov     4*8(%rsp),%r14
1317         mov     5*8(%rsp),%r15
1318
1319         mov     6*8(%rsp),%rax          /* restore return address             */
1320         add     $(7*8),%rsp             /* free stack frame                   */
1321         mov     %rax,(%rsp)
1322         ret
1323                 
1324
1325 /********************* function asm_switchstackandcall *************************
1326 *                                                                              *
1327 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
1328 *                                      void *p);                                       *
1329 *                                                                              *
1330 *   Switches to a new stack, calls a function and switches back.               *
1331 *       a0 (%rdi)     new stack pointer                                        *
1332 *       a1 (%rsi)     function pointer                                         *
1333 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
1334 *       a3 (%rcx)     pointer to user data, is passed to the function          *
1335 *                                                                              *
1336 *******************************************************************************/
1337
1338 asm_switchstackandcall:
1339         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
1340         sub     $16,%rdi                                /* allocate new stack                 */
1341
1342         mov     8(%rsp),%rax                    /* save return address on new stack   */
1343         mov     %rax,(%rdi)
1344         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
1345         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
1346
1347         mov     %rdi,%rsp                               /* switch to new stack                */
1348
1349         mov     %rcx,%rdi                       /* pass pointer                       */
1350         call    *%rsi                                   /* and call function                  */
1351
1352         mov     (%rsp),%r10                             /* load return address                */
1353         mov     8(%rsp),%rsp                    /* switch to old stack                */
1354         add     $(1*8),%rsp             /* free stack space                   */
1355         mov     %r10,(%rsp)             /* write return adress                */
1356         ret
1357
1358
1359 asm_getclassvalues_atomic:
1360 _crit_restart2:
1361 _crit_begin2:
1362         movl    offbaseval(a0),itmp1l
1363         movl    offdiffval(a0),itmp2l
1364         movl    offbaseval(a1),itmp3l
1365 _crit_end2:
1366         movl    itmp1l,offcast_super_baseval(a2)
1367         movl    itmp2l,offcast_super_diffval(a2)
1368         movl    itmp3l,offcast_sub_baseval(a2)
1369         ret
1370
1371         .data
1372                 
1373 asm_criticalsections:
1374 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1375         .quad   _crit_begin1
1376         .quad   _crit_end1
1377         .quad   _crit_restart1
1378         .quad   _crit_begin2
1379         .quad   _crit_end2
1380         .quad   _crit_restart2
1381 #endif
1382         .quad 0
1383
1384                                 
1385 /*
1386  * These are local overrides for various environment variables in Emacs.
1387  * Please do not remove this and leave it at the end of the file, where
1388  * Emacs will automagically detect them.
1389  * ---------------------------------------------------------------------
1390  * Local variables:
1391  * mode: asm
1392  * indent-tabs-mode: t
1393  * c-basic-offset: 4
1394  * tab-width: 4
1395  * End:
1396  */