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