cast_lock removed (using asm_getclassvalues_atomic now)
[cacao.git] / src / vm / jit / i386 / asmpart.S
1 /* jit/i386/asmpart.S - Java-C interface functions for i386
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Institut f. Computersprachen, TU Wien
5    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6    S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
7    J. Wenninger
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29             Reinhard Grafl
30             Christian Thalinger
31
32    $Id: asmpart.S 1072 2004-05-19 17:20:12Z stefan $
33
34 */
35
36
37 #include "config.h"
38 #include "offsets.h"
39
40 /* data segment offsets */
41
42 #define MethodPointer           -4
43 #define FrameSize               -8
44 #define IsSync                  -12
45 #define IsLeaf                  -16
46 #define IntSave                 -20
47 #define FltSave                 -24
48 #define LineNumberTableSize     -28
49 #define LineNumberTableStart    -32
50 #define ExTableSize             -36
51 #define ExTableStart            -36
52
53 #define ExEntrySize     -16
54 #define ExStartPC       -4
55 #define ExEndPC         -8
56 #define ExHandlerPC     -12
57 #define ExCatchType     -16
58
59
60 #define LineEntrySize   -8
61 #define LinePC          0
62 #define LineLine        -4
63                 
64         .text
65
66
67 /********************* exported functions and variables ***********************/
68
69         .globl asm_calljavafunction
70         .globl asm_calljavafunction2
71         .globl asm_calljavafunction2long
72         .globl asm_calljavafunction2double
73
74         .globl asm_call_jit_compiler
75         .globl asm_handle_builtin_exception
76         .globl asm_handle_nat_exception
77         .globl asm_handle_exception
78         .globl asm_check_clinit
79         .globl asm_builtin_checkcast    
80         .globl asm_builtin_checkarraycast
81         .globl asm_builtin_newarray
82         .globl asm_builtin_anewarray
83         .globl asm_builtin_newarray_array
84         .globl asm_builtin_aastore
85         .globl asm_builtin_monitorenter
86         .globl asm_builtin_monitorexit
87         .globl asm_builtin_ldiv
88         .globl asm_builtin_lrem
89     .globl asm_builtin_f2i
90     .globl asm_builtin_f2l
91     .globl asm_builtin_d2i
92     .globl asm_builtin_d2l
93         .globl asm_builtin_arrayinstanceof
94         .globl asm_perform_threadswitch
95         .globl asm_initialize_thread_stack
96         .globl asm_switchstackandcall
97         .globl asm_getcallingmethod
98         .globl Java_java_lang_VMSecurityManager_getClassContext
99         .globl Java_java_lang_VMSecurityManager_currentClassLoader    
100         .globl asm_builtin_new
101         .globl asm_get_stackTrace
102         .globl asm_criticalsections
103         .globl asm_getclassvalues_atomic
104
105 /*************************** imported functions *******************************/
106
107         .globl jit_compile
108         .globl builtin_monitorexit
109         .globl builtin_throw_exception
110         .globl builtin_trace_exception
111         .globl class_java_lang_Object
112         .globl findmethod
113         .globl builtin_asm_createclasscontextarray
114         .globl builtin_asm_getclassloader
115         .globl callgetexceptionptrptr
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         .ascii  "calljavafunction\0\0"
134
135         .align  8
136         .long   0                         /* catch type all                       */
137         .long   calljava_xhandler         /* handler pc                           */
138         .long   calljava_xhandler         /* end pc                               */
139         .long   asm_calljavafunction      /* start pc                             */
140         .long   1                         /* extable size                         */
141         .long   0                         /* line number table  start             */
142         .long   0                         /* line number table  size              */
143         .long   0                         /* fltsave                              */
144         .long   0                         /* intsave                              */
145         .long   0                         /* isleaf                               */
146         .long   0                         /* IsSync                               */
147         .long   32                        /* frame size                           */
148         .long   0                         /* method pointer (pointer to name)     */
149
150 asm_calljavafunction:
151                 push    %ebp                  /* allocate stack space                 */
152                 mov             %esp, %ebp
153
154         push    %ebx                  /* save registers                       */
155         push    %esi
156         push    %edi
157         
158                 sub             $32,%esp              /* pass the remaining parameters        */
159                 xor             %edx,%edx
160
161                 mov             %edx,28(%esp)         /* convert parms to 8 byte              */
162                 mov             24(%ebp),%eax
163                 mov             %eax,24(%esp)
164                 
165                 mov             %edx,20(%esp)
166                 mov             20(%ebp),%eax
167                 mov             %eax,16(%esp)
168
169                 mov             %edx,12(%esp)
170                 mov             16(%ebp),%eax
171                 mov             %eax,8(%esp)
172
173                 mov             %edx,4(%esp)
174                 mov             12(%ebp),%eax
175                 mov             %eax,(%esp)
176
177                 mov             8(%ebp),%eax          /* move function pointer to %eax        */
178
179                 lea             asm_call_jit_compiler,%edx 
180                 call    *%edx                 /* call JIT compiler                    */
181         
182 calljava_return:
183         add     $32,%esp
184         pop     %edi                 /* restore registers                     */
185         pop     %esi
186         pop     %ebx
187                 leave
188                 ret
189
190 calljava_xhandler:
191                 push    %eax                              /* pass exception pointer               */
192                 call    builtin_throw_exception
193                 add     $4,%esp
194
195                 add     $32,%esp
196         pop     %edi                 /* restore registers                     */
197         pop     %esi
198         pop     %ebx
199         leave
200                 ret
201
202
203 /********************* function asm_calljavafunction ***************************
204 *                                                                              *
205 *   This function calls a Java-method (which possibly needs compilation)       *
206 *   with up to 4 address parameters.                                           *
207 *                                                                              *
208 *   This functions calls the JIT-compiler which eventually translates the      *
209 *   method into machine code.                                                  *
210 *                                                                              *
211 *   C-prototype:                                                               *
212 *    javaobject_header *asm_calljavafunction2(methodinfo *m,                   *
213 *         u4 count, u4 size, void *callblock);                                 *
214 *                                                                              *
215 *******************************************************************************/
216
217 call_name2:
218         .ascii  "calljavafunction2\0\0"
219
220         .align  8
221         .long   0                         /* catch type all                       */
222         .long   calljava_xhandler2        /* handler pc                           */
223         .long   calljava_xhandler2        /* end pc                               */
224         .long   asm_calljavafunction2     /* start pc                             */
225         .long   1                         /* extable size                         */
226         .long   0                         /* line number table start              */
227         .long   0                         /* line number table size               */
228         .long   0                         /* fltsave                              */
229         .long   0                         /* intsave                              */
230         .long   0                         /* isleaf                               */
231         .long   0                         /* IsSync                               */
232         .long   32                        /* frame size                           */
233         .long   0                         /* method pointer (pointer to name)     */
234
235 asm_calljavafunction2:
236 asm_calljavafunction2double:
237 asm_calljavafunction2long:
238         push    %ebp
239         mov     %esp,%ebp                 /* save stackptr                        */
240
241         push    %ebx                      /* save registers                       */
242         push    %esi
243         push    %edi
244
245         mov     20(%ebp),%eax             /* pointer to arg block                 */
246         mov     12(%ebp),%ecx             /* arg count                            */
247         test    %ecx,%ecx                 /* maybe we have no args                */
248         jle     calljava_copydone
249
250         mov     %ecx,%edx                 /* calculate stack size                 */
251         shl     $3,%edx
252         mov     %edx,%esi                 /* save in callee saved register        */
253         sub     %esi,%esp                 /* stack frame for arguments            */
254         mov     %esp,%edi
255
256 calljava_copyloop:
257     mov     offjniitem(%eax),%edx
258     mov     %edx,0(%edi)
259     mov     offjniitem+4(%eax),%edx
260     mov     %edx,4(%edi)
261
262         sub     $1,%ecx                   /* are there any args left?             */
263         test    %ecx,%ecx
264         jle     calljava_copydone
265
266         add     $sizejniblock,%eax        /* goto next argument block             */
267     add     $8,%edi                   /* increase sp to next argument         */
268         jmp     calljava_copyloop
269
270 calljava_copydone:
271         mov     8(%ebp),%eax              /* move function pointer to %eax        */
272
273         lea     asm_call_jit_compiler,%edx 
274         call    *%edx                     /* call JIT compiler                    */
275         
276 calljava_return2:
277         add     %esi,%esp                 /* remove arg stack frame               */
278         pop     %edi                      /* restore registers                    */
279         pop     %esi
280         pop     %ebx
281         leave
282         ret
283
284 calljava_xhandler2:
285         push    %eax                      /* pass exception pointer               */
286         call    builtin_throw_exception
287         add     $4,%esp
288     
289         add     %esi,%esp                 /* remove arg stack frame               */
290         pop     %edi                      /* restore registers                    */
291         pop     %esi
292         pop     %ebx
293         leave
294         ret
295
296
297 /****************** function asm_call_jit_compiler *****************************
298 *                                                                              *
299 *   invokes the compiler for untranslated JavaVM methods.                      *
300 *                                                                              *
301 *   Register R0 contains a pointer to the method info structure (prepared      *
302 *   by createcompilerstub). Using the return address in R26 and the            *
303 *   offset in the LDA instruction or using the value in methodptr R28 the      *
304 *   patching address for storing the method address can be computed:           *
305 *                                                                              *
306 *   method address was either loaded using                                     *
307 *                                                                              *
308 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
309 *   i386_call_reg(REG_ITMP2)                                                   *
310 *                                                                              *
311 *   or                                                                         *
312 *                                                                              *
313 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface    *
314 *   i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)                *
315 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \                *
316 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
317 *   i386_call_reg(REG_ITMP1)                                                   *
318 *                                                                              *
319 *   in the static case the method pointer can be computed using the            *
320 *   return address and the lda function following the jmp instruction          *
321 *                                                                              *
322 *******************************************************************************/
323
324 asm_call_jit_compiler:
325         push    %ebx                /* save register                              */
326     push    %ebp
327                         
328         mov     8(%esp),%ebp        /* get return address (2 push)                */
329         mov     -1(%ebp),%bl        /* get function code                          */
330         cmp     $0xd1,%bl           /* called with `call *REG_ITMP2' (%ecx)?      */
331         jne             L_not_static_special
332
333         sub     $6,%ebp             /* calculate address of immediate             */
334         jmp             L_call_jit_compile
335                 
336 L_not_static_special:
337         cmp     $0xd0,%bl           /* called with `call *REG_ITMP1' (%eax)       */
338         jne             L_not_virtual_interface
339         
340         sub     $6,%ebp             /* calculate address of offset                */
341         mov     (%ebp),%ebp         /* get offset                                 */
342         add     %ecx,%ebp           /* add base address to get method address     */
343         jmp             L_call_jit_compile
344
345 L_not_virtual_interface:        /* a call from asm_calljavafunction           */
346         xor     %ebp,%ebp
347                 
348 L_call_jit_compile:
349         push    %ebp                /* save address for method pointer            */
350
351         push    %eax                /* push methodpointer on stack                */
352         call    jit_compile
353         add     $4,%esp
354
355         pop     %ebp                /* restore address for method pointer         */
356         test    %ebp,%ebp           /* is address == 0 (asm_calljavafunction)     */
357         je              L_call_method
358         
359         mov     %eax,(%ebp)         /* and now save the new pointer               */
360
361 L_call_method:
362         pop     %ebp                /* restore registers                          */
363         pop     %ebx
364                 
365         jmp             *%eax               /* ...and now call the new method             */
366
367
368 /********************* function asm_handle_exception ***************************
369 *                                                                              *
370 *   This function handles an exception. It does not use the usual calling      *
371 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
372 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
373 *   the local exception table for a handler. If no one is found, it unwinds    *
374 *   stacks and continues searching the callers.                                *
375 *                                                                              *
376 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
377 *                                                                              *
378 *******************************************************************************/
379
380 asm_handle_nat_exception:
381                 add     $4,%esp                                         /* clear return address of native stub */
382                 
383 asm_handle_exception:
384 #if 0
385                 push %ebp
386                 mov %esp,%ebp
387                 push %eax       /* exception pointer */
388                 push %ecx       /* excepiton pc */
389
390                 call asm_get_stackTrace
391
392                 pop %ecx
393                 pop %eax
394                 pop %ebp
395 #endif
396 asm_handle_exception_loop:
397                 push    %ebp
398                 mov     %esp,%ebp
399         
400                 push    %eax                                            /* save exception pointer         */
401                 push    %ecx                        /* save exception pc              */
402
403                 call    findmethod                  /* get the data segment ptr       */
404                 mov     %eax,%edx
405                         
406                 mov     -4(%ebp),%eax
407                 mov     -8(%ebp),%ecx               /* could be changed in findmethod */
408
409                 push    %edx                                            /* save data segment pointer      */
410                 push    %ebx
411                 push    %esi
412                 push    %edi
413                 
414 ex_stack_loop:
415                 sub     $20,%esp
416                 mov     %eax,(%esp)                                     /* exception pointer              */
417                 mov     MethodPointer(%edx),%eax        /* method pointer                 */
418                 mov     %eax,4(%esp)
419                 mov     %ecx,8(%esp)                            /* exception pc                   */
420                 movl    $0,12(%esp)                 /* line number                    */
421                 movl    $1,16(%esp)                                     /* set no unwind flag             */
422                 call    builtin_trace_exception
423                 add     $20,%esp
424                 mov     -12(%ebp),%esi                          /* %esi = data segment pointer    */
425                 mov     ExTableSize(%esi),%ecx          /* %ecx = exception table size    */
426                 test    %ecx,%ecx                                       /* if empty table skip            */
427                 je      empty_table
428
429                 lea             ExTableStart(%esi),%edi         /* %edi = start of exception table*/
430                 mov     -4(%ebp),%eax               /* get xptr                       */
431                 
432 ex_table_loop:
433                 mov     -8(%ebp),%edx                           /* get xpc                        */
434
435                 mov     ExStartPC(%edi),%ebx            /* %ebx = exception start pc      */
436                 cmp     %edx,%ebx                                       /* %ebx = (startpc <= xpc)        */
437                 jg      ex_table_cont                           /* if (false) continue            */
438                 mov     ExEndPC(%edi),%ebx                      /* %ebx = exception end pc        */
439                 cmp     %ebx,%edx                                       /* %ebx = (xpc < endpc)           */
440                 jge     ex_table_cont                           /* if (false) continue            */
441                 mov     ExCatchType(%edi),%ebx          /* arg1 = exception catch type    */
442                 test    %ebx,%ebx                                       /* NULL catches everything        */
443                 je      ex_handle_it
444
445 #if 1
446         cmpl    $0,offclassloaded(%ebx)     /* check if class is loaded           */
447         jne     L_class_loaded
448
449         push    %eax                        /* save not callee saved regs         */
450         push    %ecx
451
452         push    %ebx                        /* exception class is argument        */
453         call    class_load
454         add     $4,%esp
455
456         pop     %ecx
457         pop     %eax
458
459 L_class_loaded:
460         cmpl    $0,offclasslinked(%ebx)
461         jne     L_class_linked
462
463         push    %eax                        /* save not callee saved regs         */
464         push    %ecx
465
466         push    %ebx                        /* exception class is argument        */
467         call    class_link
468         add     $4,%esp
469
470         pop    %ecx
471         pop    %eax
472
473 L_class_linked:
474 #endif
475 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
476                 push    %ebx
477
478 _crit_restart1:
479                 mov     0(%esp),%ebx
480 #endif
481                 
482 _crit_begin1:
483                 mov     offobjvftbl(%eax),%esi          /* %esi = vftblptr(xptr)          */
484                 mov     offclassvftbl(%ebx),%ebx    /* %ebx = vftblptr(catchtype) class (not obj) */
485                 mov     offbaseval(%esi),%esi           /* %esi = baseval(xptr)           */
486                 mov     offbaseval(%ebx),%edx           /* %edx = baseval(catchtype)      */
487                 mov     offdiffval(%ebx),%ebx           /* %ebx = diffval(catchtype)      */
488 _crit_end1:
489                 sub     %edx,%esi                                       /* %esi = baseval(xptr) - baseval(catchtype) */
490
491 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
492                 add     $4,%esp
493 #endif
494         
495                 cmp     %ebx,%esi                                       /* xptr is instanceof catchtype   */
496                 ja      ex_table_cont
497                 
498 ex_handle_it:
499                 mov     ExHandlerPC(%edi),%edx
500                 
501                 pop     %edi                        /* restore registers              */
502                 pop     %esi
503                 pop     %ebx
504         add     $8,%esp                     /* suck %ecx, %edx                */
505         pop     %eax                        /* restore xptr                   */
506
507                 leave
508                 jmp             *%edx                       /* jump to exception handler      */
509
510 ex_table_cont:
511                 lea     ExEntrySize(%edi),%edi
512                 dec     %ecx
513                 test    %ecx,%ecx
514                 jg      ex_table_loop
515                 
516 empty_table:
517         pop     %edi
518         pop     %esi
519         pop     %ebx
520         pop     %edx                        /* restore data segment pointer   */
521         pop     %ecx
522         pop     %eax
523         pop     %ebp
524
525         push    %eax                        /* save exception pointer         */
526         
527 ex_already_cleared:
528                 mov     IsSync(%edx),%eax                       /* %eax = SyncOffset              */
529                 test    %eax,%eax                                       /* if zero no monitorexit         */
530                 je      no_monitor_exit
531
532         add     %esp,%eax
533         mov     -4(%eax),%eax               /* we have the xptr on the stack  */
534         push    %edx                        /* save regs                      */
535         push    %eax
536                 call    builtin_monitorexit
537                 add     $4,%esp
538         pop     %edx                        /* restore regs                   */
539         
540 no_monitor_exit:
541         mov     %esp,%eax
542         add     FrameSize(%edx),%eax        /* %eax = frame size              */
543         add     $4,%eax                     /* we have the xptr on the stack  */
544         
545                 mov     IntSave(%edx),%ecx          /* %ecx = saved int register count*/
546                 test    %ecx,%ecx
547                 je      noint
548                 cmp     $1,%ecx
549                 je      int1
550                 cmp     $2,%ecx
551                 je      int2
552                 cmp     $3,%ecx
553                 je      int3
554
555 int4:   
556                 mov     -32(%eax),%ebx
557
558 int3:   
559                 mov     -24(%eax),%ebp
560
561 int2:   
562                 mov     -16(%eax),%esi
563
564 int1:   
565                 mov     -8(%eax),%edi
566
567                 shl     $3,%ecx                                         /* multiply by 8 bytes             */
568                 sub     %ecx,%eax
569                 
570 noint:
571                 mov     FltSave(%edx),%ecx                      /* %ecx = saved flt register count */
572                 test    %ecx,%ecx
573                 je      noflt
574                 cmp     $1,%ecx
575                 je      flt1
576                 cmp     $2,%ecx
577                 je      flt2
578                 cmp     $3,%ecx
579                 je      flt3
580                 
581 flt4:   
582                 fldl    -32(%eax)
583                 fstp    %st(1)
584
585 flt3:   
586                 fldl    -24(%eax)
587                 fstp    %st(2)
588                 
589 flt2:   
590                 fldl    -16(%eax)
591                 fstp    %st(3)
592                 
593 flt1:   
594                 fldl    -8(%eax)
595                 fstp    %st(4)
596                 
597 noflt:
598         pop     %eax                        /* restore exception pointer      */
599         
600         mov     FrameSize(%edx),%ecx        /* %ecx = frame size              */
601         add     %ecx,%esp                   /* unwind stack                   */
602         
603                 pop     %ecx                        /* the new xpc is return address  */
604                 sub     $2,%ecx
605                 
606                 jmp             asm_handle_exception_loop
607                 
608
609 /********************* function asm_check_clinit *******************************
610 *                                                                              *
611 *   Does null check and calls monitorenter or throws an exception              *
612 *                                                                              *
613 *******************************************************************************/
614
615 asm_check_clinit:
616         mov     offclassinit(%eax),%ecx     /* get initialized flag               */
617         test    %ecx,%ecx
618         jnz     L_is_initialized
619
620         sub     $16,%esp                    /* build stack frame (4 * 4 bytes)    */
621         mov     %eax,(%esp)
622         call    builtin_asm_get_stackframeinfo
623
624         movl    $0,12(%esp)
625     mov     %eax,8(%esp)
626         mov     (%eax),%ecx
627         mov     %ecx,4(%esp)
628         mov     %esp,%ecx
629         add     $4,%ecx
630         mov     %ecx,(%eax)
631
632         call    class_init                  /* call class_init function           */
633
634         mov     4(%esp),%ebx
635         mov     8(%esp),%ecx
636         mov     %ebx,(%ecx)
637
638         add     $16,%esp
639
640         test    %eax,%eax                   /* we had an exception                */
641         je      L_initializererror
642
643 L_is_initialized:
644         mov     (%esp),%eax                 /* get return address                 */
645         sub     $12,%eax                    /* asm_putstatic call code size       */
646         movb    $0xeb,(%eax)                /* jmp rel8                           */
647         movb    $10,1(%eax)                 /* 8-bit offset                       */
648         ret
649
650 L_initializererror:
651 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
652         call    builtin_asm_get_exceptionptrptr
653         mov     %eax,%ecx
654         mov     (%ecx),%eax                 /* get the exception pointer          */
655         movl    $0,(%ecx)                   /* clear the exception pointer        */
656 #else
657         lea     _exceptionptr,%ecx
658         mov     (%ecx),%eax                 /* get the exception pointer          */
659         movl    $0,(%ecx)                   /* clear the exception pointer        */
660 #endif
661
662         pop     %ecx                        /* delete return address              */
663         sub     $2,%ecx                     /* faulting address is return adress - 2 */
664
665         jmp     asm_handle_exception
666
667
668 /********************* function asm_builtin_monitorenter ***********************
669 *                                                                              *
670 *   Does null check and calls monitorenter or throws an exception              *
671 *                                                                              *
672 *******************************************************************************/
673
674 asm_builtin_monitorenter:
675         cmpl    $0,4(%esp)
676         je      nb_monitorenter             /* if (null) throw exception          */
677         jmp             builtin_monitorenter        /* else call builtin_monitorenter     */
678
679 nb_monitorenter:
680         push    string_java_lang_NullPointerException
681         call    new_exception
682         add     $(1*4),%esp
683         
684         pop     %ecx                        /* delete return address              */
685         sub     $2,%ecx                     /* faulting address is return adress - 2 */
686         jmp     asm_handle_exception
687                 
688
689 /********************* function asm_builtin_monitorexit ************************
690 *                                                                              *
691 *   Does null check and calls monitorexit or throws an exception               *
692 *                                                                              *
693 *******************************************************************************/
694
695 asm_builtin_monitorexit:
696         mov     4(%esp),%eax
697     test    %eax,%eax
698         je      nb_monitorexit              /* if (null) throw exception          */
699     push    %ecx                        /* save registers which could be used */
700     push    %edx
701     push    %eax
702         call    builtin_monitorexit         /* else call builtin_monitorenter     */
703     add     $4,%esp
704     pop     %edx                        /* restore registers which could be used */
705     pop     %ecx
706     ret
707
708 nb_monitorexit:
709         push    string_java_lang_NullPointerException
710         call    new_exception
711         add     $(1*4),%esp
712         
713         pop     %ecx                    /* delete return address              */
714         sub     $2,%ecx                 /* faulting address is return adress - 2 */
715         jmp     asm_handle_exception
716
717
718 /************************ function asm_builtin_ldiv ****************************
719 *                                                                              *
720 *   Does null check and calls ldiv or throws an exception                      *
721 *                                                                              *
722 *******************************************************************************/
723
724 asm_builtin_ldiv:
725         mov     12(%esp),%eax
726         or      16(%esp),%eax
727         test    %eax,%eax                   /* if (null) throw exception          */
728         je      nb_ldiv
729
730         jmp     builtin_ldiv
731
732 nb_ldiv:
733         push    string_java_lang_ArithmeticException_message
734         push    string_java_lang_ArithmeticException
735         call    new_exception_message
736         add     $(2*4),%esp
737         
738         pop     %ecx                        /* delete return address              */
739         sub     $2,%ecx                     /* faulting address is return adress - 2 */
740         jmp     asm_handle_exception
741                                 
742
743 /************************ function asm_builtin_lrem ****************************
744 *                                                                              *
745 *   Does null check and calls lrem or throws an exception                      *
746 *                                                                              *
747 *******************************************************************************/
748
749 asm_builtin_lrem:
750         mov     12(%esp),%eax
751         or      16(%esp),%eax
752         test    %eax,%eax                   /* if (null) throw exception          */
753         je      nb_lrem
754
755         jmp     builtin_lrem
756
757 nb_lrem:
758         push    string_java_lang_ArithmeticException_message
759         push    string_java_lang_ArithmeticException
760         call    new_exception_message
761         add     $(2*4),%esp
762
763         pop     %ecx                        /* delete return address              */
764         sub     $2,%ecx                     /* faulting address is return adress - 2 */
765         jmp     asm_handle_exception
766                 
767
768 /************************ function asm_builtin_x2x *****************************
769 *                                                                              *
770 *   Wrapper functions for corner cases                                         *
771 *                                                                              *
772 *******************************************************************************/
773
774 asm_builtin_f2i:
775         sub     $4,%esp
776         fsts    (%esp)
777         call    builtin_f2i
778         add     $4,%esp
779         ret
780
781 asm_builtin_d2i:
782         sub     $8,%esp
783         fstl    (%esp)
784         call    builtin_d2i
785         add     $8,%esp
786         ret
787
788 asm_builtin_f2l:
789         sub     $4,%esp
790         fsts    (%esp)
791         call    builtin_f2l
792         add     $4,%esp
793         ret
794
795 asm_builtin_d2l:
796         sub     $8,%esp
797         fstl    (%esp)
798         call    builtin_d2l
799         add     $8,%esp
800         ret
801
802
803 /******************* function asm_builtin_checkarraycast ***********************
804 *                                                                              *
805 *   Does the cast check and eventually throws an exception                     *
806 *                                                                              *
807 *******************************************************************************/
808
809 asm_builtin_checkarraycast:
810         sub             $8,%esp                     /* build stack frame (2 * 4 bytes)    */
811
812         mov             12(%esp),%eax               /* 8 (frame) + 4 (return)             */
813         mov             %eax,(%esp)                 /* save object pointer                */
814
815         mov             20(%esp),%eax
816         mov             %eax,4(%esp)
817
818         call    builtin_checkarraycast      /* builtin_checkarraycast             */
819
820         test    %eax,%eax                   /* if (false) throw exception         */
821         je              nb_carray_throw
822
823         mov             12(%esp),%eax               /* return object pointer              */
824         add             $8,%esp
825         ret
826
827 nb_carray_throw:
828         push    string_java_lang_ClassCastException
829         call    new_exception
830         add     $(1*4),%esp
831         
832         add             $8,%esp
833         
834         pop             %ecx                        /* delete return address              */
835         sub             $2,%ecx                     /* faulting address is return adress - 2 */
836         jmp             asm_handle_exception
837
838                 
839 /******************* function asm_builtin_newarray *****************************
840 *                                                                              *
841 *   Does the cast check and eventually throws an exception                     *
842 *                                                                              *
843 *******************************************************************************/
844
845 asm_builtin_newarray:
846         sub             $8,%esp                     /* build stack frame (2 * 4 bytes)    */
847
848         mov             12(%esp),%eax
849         mov             %eax,(%esp)
850
851         mov             20(%esp),%eax
852         mov             %eax,4(%esp)
853
854         call    builtin_newarray
855
856         add             $8,%esp
857         ret
858
859                 
860 /******************* function asm_builtin_aastore ******************************
861 *                                                                              *
862 *   Does the cast check and eventually throws an exception                     *
863 *                                                                              *
864 *******************************************************************************/
865
866 asm_builtin_aastore:
867         sub     $12,%esp                    /* build stack frame (3 * 4 bytes)    */
868
869         mov     16(%esp),%eax               /* 12 (frame) + 4 (return)            */
870         test    %eax,%eax                   /* if null pointer throw exception    */
871         je      nb_aastore_null
872
873         mov     offarraysize(%eax),%edx /* load size                          */
874         mov     24(%esp),%ecx               /* index                              */
875         cmp     %edx,%ecx                   /* do bound check                     */
876         jae     nb_aastore_bound            /* if out of bounds throw exception   */
877
878         shl     $2,%ecx                     /* index * 4                          */
879         add     %eax,%ecx                   /* add index * 4 to arrayref          */
880            
881         mov     %ecx,8(%esp)                /* save store position                */
882            
883         mov     16(%esp),%eax               /* 12 (frame) + 4 (return)            */
884         mov     %eax,(%esp)
885            
886         mov     32(%esp),%eax               /* object is second argument          */
887         mov     %eax,4(%esp)
888         
889         call    builtin_canstore            /* builtin_canstore(arrayref,object)  */
890
891         test    %eax,%eax                   /* if (false) throw exception         */
892         je      nb_aastore_store
893
894         mov     32(%esp),%eax
895         mov     8(%esp),%ecx
896         mov     %eax,offobjarrdata(%ecx)    /* store objectptr in array           */
897         
898         add     $12,%esp
899         ret
900
901 nb_aastore_null:
902         push    string_java_lang_NullPointerException
903         call    new_exception
904         add     $(1*4),%esp
905         
906         add     $12,%esp
907         pop     %ecx                        /* delete return address              */
908         sub     $2,%ecx                     /* faulting address is return adress - 2 */
909         jmp             asm_handle_exception
910
911 nb_aastore_bound:
912         push    %ecx                        /* itmp2 contains array index         */
913         push    string_java_lang_ArrayIndexOutOfBoundsException
914         call    new_exception_int
915         add     $(2*4),%esp
916
917         add     $12,%esp
918         pop     %ecx                        /* delete return address              */
919         sub     $2,%ecx                     /* faulting address is return adress - 2 */
920         jmp     asm_handle_exception
921                 
922 nb_aastore_store:
923         push    string_java_lang_ArrayStoreException
924         call    new_exception
925         add     $(1*4),%esp
926         
927         add     $12,%esp
928         pop     %ecx                        /* delete return address              */
929         sub     $2,%ecx                     /* faulting address is return adress - 2 */
930         jmp     asm_handle_exception
931
932                 
933 /******************* function asm_builtin_arrayinstanceof **********************
934 *                                                                              *
935 *   Does the instanceof check of arrays                                        *
936 *                                                                              *
937 *******************************************************************************/
938
939 asm_builtin_arrayinstanceof:
940         sub             $8,%esp                     /* build stack frame (2 * 4 bytes)    */
941
942         mov     12(%esp),%eax
943         mov     %eax,(%esp)
944
945         mov     20(%esp),%eax
946         mov     %eax,4(%esp)
947
948         call    builtin_arrayinstanceof
949
950         add     $8,%esp
951         ret
952
953                 
954 /******************* function asm_initialize_thread_stack **********************
955 *                                                                              *
956 * initialized a thread stack                                                   *
957 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
958 *                                                                              *
959 *******************************************************************************/
960
961 asm_initialize_thread_stack:
962                 mov             8(%esp),%eax            /* (to)->stackEnd                     */
963                 sub             $36,%eax                /* 4 bytes * 8 regs + 4 bytes func    */
964                                 
965                 xor             %edx,%edx
966                 mov             %edx,0(%eax)
967                 mov             %edx,4(%eax)
968                 mov             %edx,8(%eax)
969                 mov             %edx,12(%eax)
970                 mov             %edx,16(%eax)
971                 mov             %edx,20(%eax)
972                 mov     %edx,24(%eax)
973                 mov     %edx,28(%eax)
974                                 
975                 mov     4(%esp),%edx            /* save (u1*) (func)                  */
976                 mov     %edx,32(%eax)
977
978                 ret                             /* return restorepoint in %eax        */
979
980
981 /******************* function asm_perform_threadswitch *************************
982 *                                                                              *
983 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
984 *                                                                              *
985 *   performs a threadswitch                                                    *
986 *                                                                              *
987 *******************************************************************************/
988
989 asm_perform_threadswitch:
990         sub     $36,%esp
991            
992         mov     %eax,0(%esp)
993         mov     %ecx,4(%esp)
994         mov     %edx,8(%esp)
995         mov     %ebx,12(%esp)
996         mov     %esp,16(%esp)
997         mov     %ebp,20(%esp)
998         mov     %esi,24(%esp)
999         mov     %edi,28(%esp)
1000            
1001         mov     36(%esp),%eax         /* save current return address              */
1002         mov     %eax,32(%esp)
1003            
1004         mov     40(%esp),%eax         /* first argument **from                    */
1005         mov     %esp,0(%eax)
1006            
1007         mov     48(%esp),%eax         /* third argument **stackTop                */
1008         mov     %esp,0(%eax)
1009            
1010         mov     44(%esp),%eax         /* second argument **to                     */
1011         mov     0(%eax),%esp          /* load new stack pointer                   */
1012            
1013         mov     0(%esp),%eax
1014         mov     4(%esp),%ecx
1015         mov     8(%esp),%edx
1016         mov     12(%esp),%ebx
1017                                       /* skip stack pointer                       */
1018         mov     20(%esp),%ebp
1019         mov     24(%esp),%esi
1020         mov     28(%esp),%edi
1021            
1022         add     $32,%esp              /* leave return address on stack            */
1023         ret
1024                 
1025
1026 /********************* function asm_switchstackandcall *************************
1027 *                                                                              *
1028 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
1029 *                                      void *p);                                       *
1030 *                                                                              *
1031 *   Switches to a new stack, calls a function and switches back.               *
1032 *       a0      new stack pointer                                              *
1033 *       a1      function pointer                                               *
1034 *               a2              pointer to variable where stack top should be stored           *
1035 *       a3      pointer to user data, is passed to the function                *
1036 *                                                                              *
1037 *******************************************************************************/
1038
1039 asm_switchstackandcall:
1040         mov     4(%esp),%edx          /* first argument *stack                    */
1041         sub     $8,%edx               /* allocate new stack                       */
1042
1043         mov     (%esp),%eax           /* save return address on new stack         */
1044         mov     %eax,(%edx)
1045
1046         mov     %esp,4(%edx)          /* save old stack pointer on new stack      */
1047
1048         mov     12(%esp),%eax         /* third argument **stacktopsave            */
1049         mov     %esp,(%eax)           /* save old stack pointer to variable       */
1050
1051         mov     8(%esp),%eax          /* load function pointer                    */
1052         mov     16(%esp),%ecx         /* fourth argument *p                       */
1053         
1054         mov     %edx,%esp             /* switch to new stack                      */
1055
1056         sub     $4,%esp
1057         mov     %ecx,0(%esp)          /* pass pointer                             */
1058         call    *%eax                 /* and call function                        */
1059         add     $4,%esp
1060
1061         mov     (%esp),%edx           /* load return address                      */
1062         mov     4(%esp),%esp          /* switch to old stack                      */
1063         mov     %edx,(%esp)
1064         ret
1065
1066                 
1067 Java_java_lang_VMSecurityManager_currentClassLoader:
1068         lea  builtin_asm_getclassloader,%eax 
1069         push %eax       /*store collector function pointer*/
1070         jmp getClassContext_begin
1071 Java_java_lang_VMSecurityManager_getClassContext:
1072         lea  builtin_asm_createclasscontextarray,%eax 
1073         push %eax /*store collector function pointer*/
1074 getClassContext_begin:  /*start the real work*/
1075
1076         mov %esp,%eax
1077         sub $4,%eax
1078         sub $68,%esp /*64 memory location without overwriting return adress and collector function adress*/
1079         mov %esp,%ebx   /*end of allocated memory block for classpointers is the adress of the working data block +4 */
1080         push $0 /*%esp+32 was native*/
1081         push %eax /*%esp+24 blkbegin*/
1082         push %eax /*%esp+20 currentpos*/
1083         push %ebx /*%esp+16 blkend*/
1084
1085         call builtin_asm_get_threadrootmethod
1086         push %eax /*%esp+12*/
1087         movl 104(%esp),%eax /*(stack contains: threadRootMethod,blkend,blkpos,blkbegin,was native, data(64kB),collector,ret,env,class,frame stack info of stub, we want the frame stack info  of thestub*/
1088         movl %esp,%edx
1089         addl $116, %edx
1090         push %edx /*esp+8*/ /*position of return address of native stub*/
1091         call builtin_asm_get_stackframeinfo
1092         movl (%eax),%eax /*comment ??*/
1093         push 0(%eax) /*esp+4*/ /*address of frame info block*/
1094         movl 124(%esp),%edx
1095
1096 /*DEBUG*/
1097 /*      mov %esp,%eax
1098         addl $116,%eax
1099         push %eax
1100         call i386_native_stub_debug
1101         pop %eax*/
1102
1103         push %edx /*esp+0*/ /*return adress out of native stub*/
1104         call findmethod /*find calling java method, this one is still to be skipped (==SecurityManager.getClassContext (or .currentClassLoader)*/
1105
1106 /*DEBUGGING*/
1107 /*      push %eax
1108         movl MethodPointer(%eax),%eax
1109         push %eax
1110         call temporaryGetClassContextHelper
1111         pop %eax
1112         call traverseStackInfo
1113         pop %eax
1114 */
1115
1116         movl 20(%esp),%edx
1117         movl MethodPointer(%eax),%ebx
1118         movl offclassmethodinfo(%ebx),%ecx
1119         movl %ecx,(%edx)
1120         subl $4,%edx
1121         movl %edx,20(%esp)
1122
1123         mov 8(%esp),%ebx /*pos of return adress */
1124         add FrameSize(%eax),%ebx
1125         add $4,%ebx     /*adress of new return adress (out of Securitymanager.*/
1126         mov %ebx,8(%esp) 
1127         mov %eax,(%esp)
1128
1129         /* by now we have skipped this method call*/
1130
1131 getClassContext_next:   
1132         movl 8(%esp),%eax
1133         movl (%eax),%eax
1134         movl %eax,(%esp) /*return adress*/
1135
1136         call findmethod
1137
1138         cmp $1,32(%esp)
1139         mov 8(%esp),%ebx
1140         add FrameSize(%eax),%ebx
1141         add $4,%ebx
1142         mov %ebx,8(%esp) /*store adress of next return adress*/
1143 getClassContext_nextRetStored:
1144
1145         mov MethodPointer(%eax),%ecx    /*get struct methodinfo*/
1146
1147         cmp $0,%ecx
1148         je getClassContext_nativeCall
1149         /*save class pointer*/
1150         movl $0,32(%esp)
1151 getClassContext_saveClassPointer:
1152         movl 20(%esp),%ebx      /*get temporary memory adress in stack*/
1153         movl offclassmethodinfo(%ecx),%edx /* get class pointer of method*/
1154         movl %edx,(%ebx) /*save */
1155         sub $4,%ebx     /*calculate next position */
1156         movl %ebx,20(%esp) /* check if the new adress would overwrite our working data */
1157         cmp %ebx,16(%esp)
1158         je getClassContext_incStack
1159 getClassContext_checkLeave:
1160         
1161         cmp 12(%esp),%ecx       /*check if we reached the toplevel method of our thread*/
1162         je  getClassContext_leave /*yes ->leave*/
1163
1164 /*DEBUGING*/
1165 /*      mov %ecx,(%esp)
1166         call temporaryGetClassContextHelper
1167 */
1168         
1169         
1170         jmp getClassContext_next /*continue*/
1171
1172
1173 getClassContext_nativeCall:
1174         movl $1,32(%esp)
1175         movl 4(%esp),%eax       /*get top most element on stackframe help information stack*/
1176         movl 0(%eax),%ecx 
1177         movl %ecx,4(%esp)
1178         addl $8,%eax
1179         movl (%eax),%ecx
1180         addl $4,%eax
1181         movl %eax,8(%esp)
1182         
1183         cmp $0,%ecx
1184         je getClassContext_checkLeave
1185         jmp getClassContext_saveClassPointer
1186
1187 getClassContext_incStack:
1188         /*make another 64 in our temporary storage free and store the workingdata */
1189         movl %esp,%edx
1190         subl $40,%esp /*should be 32*/
1191         push 32(%edx)
1192         push 28(%edx)
1193         push 24(%edx)
1194         push 20(%edx)
1195         push 16(%edx)
1196         push 12(%edx)
1197         push 8(%edx)
1198         push 4(%edx)
1199         push 0(%edx)
1200         subl $64,16(%esp)
1201
1202         jmp getClassContext_checkLeave /* continue */
1203
1204 getClassContext_leave:
1205 /*DEBUGING*/
1206 /*      mov %ecx,(%esp)
1207         call temporaryGetClassContextHelper*/
1208
1209         /*call collector function with begin/end of temporary classarray*/
1210         push 24(%esp)
1211         push 24(%esp)
1212         
1213         movl 32(%esp),%eax
1214         add $4,%eax
1215         movl (%eax),%ebx
1216         call *%ebx
1217
1218         /* free stack memory of this function*/
1219         mov 32(%esp),%esp
1220         add $8,%esp
1221         ret
1222
1223
1224 asm_builtin_new:
1225 /*optimize a littlebit */
1226                 mov %esp,%eax
1227 /*DEBUG*/
1228 /*              push %eax
1229                 call i386_native_stub_debug
1230                 pop %eax */
1231                 
1232                 movl 4(%esp),%eax
1233                 mov     offclassinit(%eax),%ecx     /* get initialized flag           */
1234                 test    %ecx,%ecx
1235                 jnz             L_builtin_new_noinit
1236
1237                 sub             $16,%esp                                 /* build stack frame (4 * 4 bytes) */
1238
1239                 mov             20(%esp),%eax
1240                 mov             %eax,(%esp)
1241
1242                 call    builtin_asm_get_stackframeinfo
1243                 movl    $0,12(%esp)
1244                 mov     %eax,8(%esp)
1245                 mov     (%eax),%ebx
1246                 mov     %ebx,4(%esp)
1247                 mov     %esp,%ecx
1248                 add     $4,%ecx
1249                 mov     %ecx,(%eax)
1250
1251                 call    builtin_new
1252
1253                 mov     4(%esp),%ebx
1254                 mov     8(%esp),%ecx
1255                 mov     %ebx,(%ecx)
1256
1257                 add             $16,%esp
1258
1259                 jmp L_builtin_new_patch
1260
1261
1262 L_builtin_new_noinit:
1263                 mov 4(%esp),%eax
1264                 push %eax
1265                 call builtin_new
1266                 add $4,%esp
1267                 /*jmp L_builtin_new_patch*/
1268
1269 L_builtin_new_patch:
1270 /*add patching code here */
1271                 lea builtin_new,%edx
1272                 mov (%esp),%ecx
1273                 mov %edx,-6(%ecx)       /*patch calling instruction, t directly call builtin_new the next time*/
1274                 ret
1275
1276
1277
1278
1279
1280 asm_get_stackTrace:
1281         push %ebp /*(%ebp-4)*/
1282         mov %esp,%ebp
1283         add $4,%ebp
1284         push %edi /*(%ebp-8)*/
1285         push %esi /*(%ebp-12)*/
1286         push %ebx /*(%ebp-16)*/
1287         call builtin_asm_get_stackframeinfo
1288         movl (%eax),%eax
1289         pushl 0(%eax) /*(%ebp-20)*/
1290         lea 12(%eax),%edi
1291         call builtin_asm_get_threadrootmethod
1292         pushl %eax /*(%ebp-24)*/
1293
1294         pushl (%edi)
1295 asm_get_stackTraceLoop:
1296         call findmethod
1297         mov %eax,%esi
1298         add $4,%esp
1299         pushl $1 /*no indent*/
1300
1301         mov (%edi),%edx
1302         sub $4,%edx
1303
1304 get_stackTrace_line:
1305         movl LineNumberTableSize(%esi),%ecx
1306         test    %ecx,%ecx /* skip if empty line table */
1307         je      get_stackTrace_noLineInfo
1308
1309         movl LineNumberTableStart(%esi),%ebx
1310         
1311 get_stackTrace_lineLoop:
1312         cmp %edx,LinePC(%ebx)
1313         jg get_stackTrace_nextLineInfo
1314
1315         pushl LineLine(%ebx)
1316         jmp get_stackTrace_cont
1317
1318 get_stackTrace_nextLineInfo:    
1319         lea LineEntrySize(%ebx),%ebx
1320         dec %ecx
1321         test %ecx,%ecx
1322
1323         jne get_stackTrace_lineLoop
1324
1325 get_stackTrace_noLineInfo:
1326         pushl $0
1327
1328
1329 get_stackTrace_cont:
1330         pushl (%edi) /*4*/
1331         pushl MethodPointer(%esi)
1332         pushl $0 /*8(%ebp)*/ /*exception ptr*/
1333         call builtin_trace_exception
1334         add $12,%esp
1335
1336         movl MethodPointer(%esi),%eax
1337         movl %eax,4(%esp)
1338         test %eax,%eax
1339         je get_stackTrace_nat
1340
1341         cmp %eax,-24(%ebp)
1342         je get_stackTrace_leave
1343
1344         mov FrameSize(%esi),%eax
1345         add $4,%edi
1346         add %eax,%edi
1347         pushl (%edi)
1348         jmp asm_get_stackTraceLoop
1349
1350 get_stackTrace_nat:
1351         add $8,%esp
1352         movl -20(%ebp),%eax
1353         cmp $0,%eax
1354         je get_stackTrace_leave
1355         movl  0(%eax),%ebx
1356         movl  %ebx,-20(%ebp)
1357         pushl 8(%eax)
1358         pushl $0
1359         lea 12(%eax),%edi
1360         pushl (%edi)
1361         jmp asm_get_stackTraceLoop
1362
1363 get_stackTrace_leave:
1364         mov %esp,%eax
1365         lea -24(%ebp),%ebx
1366         push %ebx
1367         push %eax
1368         push 4(%ebp)
1369         call builtin_stacktrace_copy
1370
1371         lea -16(%ebp),%esp
1372         pop %ebx
1373         pop %esi
1374         pop %edi
1375         pop %ebp
1376         ret
1377
1378 asm_getclassvalues_atomic:
1379 _crit_restart2:
1380         mov 4(%esp),%ecx        /* super */
1381         mov 8(%esp),%edx        /* sub */
1382 _crit_begin2:
1383         mov offbaseval(%ecx),%eax
1384         mov offdiffval(%ecx),%ecx
1385         mov offbaseval(%edx),%edx
1386 _crit_end2:
1387         push %ebx
1388         mov 16(%esp),%ebx      /* out */
1389         mov %eax,offcast_super_baseval(%ebx)
1390         mov %ecx,offcast_super_diffval(%ebx)
1391         mov %edx,offcast_sub_baseval(%ebx)
1392         pop %ebx
1393         ret
1394
1395         .data
1396
1397 asm_criticalsections:
1398 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1399         .long _crit_begin1
1400         .long _crit_end1
1401         .long _crit_restart1
1402         .long _crit_begin2
1403         .long _crit_end2
1404         .long _crit_restart2
1405 #endif
1406         .long 0
1407
1408 /*
1409  * These are local overrides for various environment variables in Emacs.
1410  * Please do not remove this and leave it at the end of the file, where
1411  * Emacs will automagically detect them.
1412  * ---------------------------------------------------------------------
1413  * Local variables:
1414  * mode: asm
1415  * indent-tabs-mode: t
1416  * c-basic-offset: 4
1417  * tab-width: 4
1418  * End:
1419  */