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