c5f4904714ddbb3033bdedde5fe977a313badb32
[cacao.git] / src / vm / jit / i386 / asmpart.S
1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    Changes: Joseph Wenninger
32             Edwin Steiner
33
34    $Id: asmpart.S 5255 2006-08-21 15:17:48Z twisti $
35
36 */
37
38
39 #include "config.h"
40
41 #include "md-asm.h"
42
43 #include "vm/jit/i386/arch.h"
44 #include "vm/jit/i386/md-abi.h"
45 #include "vm/jit/i386/offsets.h"
46
47 #include "vm/jit/abi-asm.h"
48 #include "vm/jit/methodheader.h"
49
50
51         .text
52
53
54 /* export functions ***********************************************************/
55
56         .globl asm_md_init
57
58         .globl asm_vm_call_method
59         .globl asm_vm_call_method_int
60         .globl asm_vm_call_method_long
61         .globl asm_vm_call_method_float
62         .globl asm_vm_call_method_double
63         .globl asm_vm_call_method_exception_handler
64
65         .globl asm_call_jit_compiler
66         .globl asm_handle_nat_exception
67         .globl asm_handle_exception
68
69         .globl asm_abstractmethoderror
70
71         .globl asm_patcher_wrapper
72
73         .globl asm_replacement_out
74         .globl asm_replacement_in
75
76         .globl asm_builtin_f2i
77         .globl asm_builtin_f2l
78         .globl asm_builtin_d2i
79         .globl asm_builtin_d2l
80
81         .globl asm_criticalsections
82         .globl asm_getclassvalues_atomic
83
84         .globl asm_get_cycle_count
85
86
87 /* asm_md_init *****************************************************************
88
89    Initialize machine dependent stuff.
90
91    See: http://www.srware.com/linux_numerics.txt
92
93    This puts the X86 FPU in 64-bit precision mode.  The default under
94    Linux is to use 80-bit mode, which produces subtle differences from
95    FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
96    64-bit mode, 299 in 80-bit mode.
97
98    Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
99
100 *******************************************************************************/
101
102 asm_md_init:
103         sub     $4,sp                       /* allocate space for the FPU state   */
104         fnstcw  (sp)                        /* get the FPU state                  */
105         mov     (sp),%eax
106         and     $0xfcff,%ax                 /* remove the extended mode flag      */
107         or      $0x0200,%ax                 /* put the double mode flag           */
108         mov     %eax,(sp)                   /* store new FPU state                */
109         fldcw   (sp)                        /* setup new FPU state                */
110         add     $4,sp
111         ret
112
113
114 /********************* function asm_calljavafunction ***************************
115 *                                                                              *
116 *   This function calls a Java-method (which possibly needs compilation)       *
117 *   with up to 4 address parameters.                                           *
118 *                                                                              *
119 *   This functions calls the JIT-compiler which eventually translates the      *
120 *   method into machine code.                                                  *
121 *                                                                              *
122 *   C-prototype:                                                               *
123 *    javaobject_header *asm_vm_call_method(methodinfo *m,                      *
124 *         u4 count, u4 size, void *callblock);                                 *
125 *                                                                              *
126 *******************************************************************************/
127
128         .align  8
129
130         .long   0                           /* catch type all                     */
131         .long   0                           /* handler pc                         */
132         .long   0                           /* end pc                             */
133         .long   0                           /* start pc                           */
134         .long   1                           /* extable size                       */
135         .long   0                           /* line number table start            */
136         .long   0                           /* line number table size             */
137         .long   0                           /* fltsave                            */
138         .long   0                           /* intsave                            */
139         .long   0                           /* isleaf                             */
140         .long   0                           /* IsSync                             */
141         .long   0                           /* frame size                         */
142         .long   0                           /* codeinfo pointer                   */
143
144 asm_vm_call_method:
145 asm_vm_call_method_int:
146 asm_vm_call_method_long:
147 asm_vm_call_method_float:
148 asm_vm_call_method_double:
149         push    bp
150         mov     sp,bp                       /* save stackptr                      */
151         sub     $(4*4),sp                   /* create stackframe                  */
152         and     $0xfffffff0,sp              /* align stack to 16-byte             */
153
154         mov     t0,0*4(sp)                  /* save registers                     */
155         mov     s1,1*4(sp)
156         mov     s2,2*4(sp)
157
158         mov     4*4(bp),itmp1               /* pointer to arg block (4(push)+4(return)+4+4)*/
159         mov     3*4(bp),itmp2               /* arg count            (4(push)+4(return)+4 */
160
161         mov     sp,s1                       /* save the stackpointer              */
162
163         test    itmp2,itmp2                 /* maybe we have no args              */
164         jle     L_asm_vm_call_method_copy_done
165
166         mov     itmp2,itmp3                 /* calculate stack size               */
167         mov     itmp1,%edi                  /* save pointer to arg block          */
168
169 calljava_calcstacksize:
170         mov     offvmargtype(itmp1),t0
171         test    $1,t0                       /* two word type?                     */
172         jz      calljava_onewordtype
173
174         sub     $4,sp                       /* add 1 slot to stackframe size      */
175
176 calljava_onewordtype:
177         sub     $4,sp                       /* add 1 slot to stackframe size      */
178         sub     $1,itmp3
179         test    itmp3,itmp3                 /* any args left?                     */
180         jz      calljava_setstack
181
182         add     $sizevmarg,itmp1            /* goto next argument block           */
183         jmp     calljava_calcstacksize
184                 
185 calljava_setstack:                              
186         mov     %edi,itmp1                  /* restore pointer to arg block       */
187         and     $0xfffffff0,sp              /* align stack to 16-byte             */
188         mov     sp,itmp3                    /* initialize pointer for copying     */
189
190 calljava_copyloop:
191         mov     offvmargdata(itmp1),t0      /* get 4-bytes of argument            */
192         mov     t0,(itmp3)                  /* and store them on the stack        */
193         add     $4,itmp3                    /* increase sp to next argument       */
194
195         mov     offvmargtype(itmp1),t0      /* get the argument type              */
196         test    $1,t0                       /* two word type?                     */
197         jz      calljava_copynext
198
199         mov     offvmargdata+4(itmp1),t0    /* get upper 4-bytes of 2 word type   */
200         mov     t0,(itmp3)                      
201         add     $4,itmp3                    /* increase sp to next argument       */
202
203 calljava_copynext:              
204         sub     $1,itmp2                    /* are there any args left?           */
205         test    itmp2,itmp2
206         jle     L_asm_vm_call_method_copy_done
207
208         add     $sizevmarg,itmp1            /* goto next argument block           */
209         jmp     calljava_copyloop
210
211 L_asm_vm_call_method_copy_done:
212         mov     2*4(bp),itmp1               /* move function pointer to itmp1     */
213
214         lea     L_asm_call_jit_compiler,mptr
215         mov     mptr,3*4(s1)
216         lea     (3*4-256)(s1),mptr          /* We subtract 256 to force the next  */
217                                             /* move instruction to have a 32-bit  */
218                                             /* offset.                            */
219
220         mov     (0*4+256)(mptr),itmp3       /* method call as in Java             */
221         call    *itmp3                      /* call JIT compiler                  */
222
223 L_asm_vm_call_method_return:
224         mov     s1,sp                       /* restore stackpointer               */
225
226         mov     0*4(sp),t0                  /* restore registers                  */
227         mov     1*4(sp),s1
228         mov     2*4(sp),s2
229
230         leave
231         ret
232
233 asm_vm_call_method_exception_handler:
234         push    xptr                        /* pass exception pointer             */
235         call    builtin_throw_exception
236         add     $4,sp
237         jmp     L_asm_vm_call_method_return
238
239
240 /* asm_call_jit_compiler *******************************************************
241
242    Invokes the compiler for untranslated JavaVM methods.
243
244    Register R0 contains a pointer to the method info structure (prepared
245    by createcompilerstub). Using the return address in R26 and the
246    offset in the LDA instruction or using the value in methodptr R28 the
247    patching address for storing the method address can be computed:
248
249    Method address was either loaded using
250
251    i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special
252    i386_call_reg(REG_ITMP2)
253
254    or
255
256    i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface
257    i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
258    i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
259        sizeof(methodptr) * m->vftblindex, REG_ITMP1)
260    i386_call_reg(REG_ITMP1)
261
262    In the static case the method pointer can be computed using the
263    return address and the lda function following the jmp instruction.
264
265 *******************************************************************************/
266
267 asm_call_jit_compiler:
268 L_asm_call_jit_compiler:                /* required for PIC code              */
269         sub     $(4*4),sp                   /* keep stack 16-byte aligned         */
270
271         mov     itmp1,0*4(sp)               /* pass methodinfo pointer            */
272         mov     mptr,1*4(sp)                /* pass method pointer                */
273         mov     sp,itmp2                    /* pass java sp                       */
274         add     $((1+4)*4),itmp2
275         mov     itmp2,2*4(sp)
276         mov     4*4(sp),itmp3               /* pass java ra                       */
277         mov     itmp3,3*4(sp)
278         call    jit_asm_compile
279
280         add     $(4*4),sp                   /* remove stack frame                 */
281
282         test    v0,v0                       /* check for exception                */
283         je      L_asm_call_jit_compiler_exception
284
285         jmp             *v0                         /* ...and now call the new method     */
286
287 L_asm_call_jit_compiler_exception:
288         call    exceptions_get_and_clear_exception
289                                             /* v0 == xptr                         */
290         pop     xpc                         /* get return address                 */
291         sub     $2,xpc                      /* faulting address is ra - 2         */
292         jmp     L_asm_handle_exception
293
294
295 /* asm_handle_exception ********************************************************
296 *                                                                              *
297 *   This function handles an exception. It does not use the usual calling      *
298 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
299 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
300 *   the local exception table for a handler. If no one is found, it unwinds    *
301 *   stacks and continues searching the callers.                                *
302 *                                                                              *
303 *******************************************************************************/
304
305 asm_handle_nat_exception:
306         add     $4,sp                       /* clear return address of native stub*/
307                 
308 asm_handle_exception:
309 L_asm_handle_exception:                 /* required for PIC code              */
310         sub     $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned         */
311
312         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
313         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
314
315         mov     $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
316         mov     $1,t0                       /* set maybe-leaf flag                */
317
318 L_asm_handle_exception_stack_loop:
319         sub     $(12*4),sp                  /* keep stack 16-byte aligned         */
320         mov     xptr,4*4(sp)                /* save exception pointer             */
321         mov     xpc,5*4(sp)                 /* save exception pc                  */
322         add     sp,itmp3                    /* calculate Java sp into a3...       */
323         add     $(12*4),itmp3
324         mov     itmp3,7*4(sp)               /* ...and save it                     */
325         mov     t0,8*4(sp)                  /* save maybe-leaf flag               */
326
327         mov     xpc,0*4(sp)                 /* pass exception pc                  */
328         call    codegen_get_pv_from_pc
329         mov     v0,6*4(sp)                  /* save data segment pointer          */
330
331         mov     4*4(sp),itmp3               /* pass exception pointer             */
332         mov     itmp3,0*4(sp)
333         mov     5*4(sp),itmp3               /* pass exception pc                  */
334         mov     itmp3,1*4(sp)
335         mov     v0,2*4(sp)                  /* pass data segment pointer          */
336         mov     7*4(sp),itmp3               /* pass Java stack pointer            */
337         mov     itmp3,3*4(sp)
338         call    exceptions_handle_exception
339
340         test    v0,v0
341         jz      L_asm_handle_exception_not_catched
342
343         mov     v0,xpc                      /* move handlerpc into xpc            */
344         mov     4*4(sp),xptr                /* restore exception pointer          */
345         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
346         add     $(12*4),sp                  /* free stackframe                    */
347
348         test    t0,t0                       /* test for maybe-leaf flag           */
349         jz      L_asm_handle_exception_no_leaf
350
351         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
352         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
353
354         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
355
356 L_asm_handle_exception_no_leaf:
357         jmp     *xpc                        /* jump to exception handler          */
358
359 L_asm_handle_exception_not_catched:
360         mov     4*4(sp),xptr                /* restore exception pointer          */
361         mov     6*4(sp),itmp3               /* restore data segment pointer       */
362         mov     8*4(sp),t0                  /* get maybe-leaf flag                */
363         add     $(12*4),sp                  /* free stackframe                    */
364
365         test    t0,t0
366         jz      L_asm_handle_exception_no_leaf_stack
367
368         add     $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe       */
369         xor     t0,t0                       /* clear the maybe-leaf flag          */
370
371 L_asm_handle_exception_no_leaf_stack:
372         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
373         add     sp,itmp2                    /* pointer to save area               */
374
375         push    xptr                        /* we are out of registers            */
376
377         mov     IntSave(itmp3),itmp1        /* itmp1 = saved int register count   */
378         test    itmp1,itmp1
379         je      noint
380
381         cmp     $1,itmp1
382         je      int1
383         cmp     $2,itmp1
384         je      int2
385
386         mov     -3*4(itmp2),s0
387 int2:   
388         mov     -2*4(itmp2),s1
389 int1:   
390         mov     -1*4(itmp2),s2
391
392         shl     $2,itmp1                    /* multiply by 4 bytes                */
393         sub     itmp1,itmp2
394                 
395 noint:
396 #if 0
397         mov     FltSave(itmp3),itmp1        /* itmp1 = saved flt register count   */
398         test    itmp1,itmp1
399         je      noflt
400
401         cmp     $1,itmp1
402         je      flt1
403         cmp     $2,itmp1
404         je      flt2
405         cmp     $3,itmp1
406         je      flt3
407                 
408         fldl    -4*8(itmp2)
409         fstp    %st(1)
410 flt3:
411         fldl    -3*8(itmp2)
412         fstp    %st(2)
413 flt2:
414         fldl    -2*8(itmp2)
415         fstp    %st(3)
416 flt1:
417         fldl    -1*8(itmp2)
418         fstp    %st(4)
419                 
420 noflt:
421 #endif
422         pop     xptr                        /* restore exception pointer          */
423         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
424         add     itmp2,sp                    /* unwind stack                       */
425
426         pop     xpc                         /* the new xpc is return address      */
427         sub     $2,xpc                      /* subtract 2-bytes for call          */
428
429         xor     itmp3,itmp3                 /* prepare a3 for handle_exception    */
430
431         jmp     L_asm_handle_exception_stack_loop
432                 
433
434 /* asm_abstractmethoderror *****************************************************
435
436    Creates and throws an AbstractMethodError.
437
438 *******************************************************************************/
439
440 asm_abstractmethoderror:
441         sub     $(3*4),sp                   /* keep stack 16-byte aligned         */
442         mov     sp,itmp1                    /* pass java sp                       */
443         add     $((1+3)*4),itmp1
444         mov     itmp1,0*4(sp)
445         mov     3*4(sp),itmp2               /* pass exception address             */
446         sub     $2,itmp2
447         mov     itmp2,1*4(sp)
448         call    exceptions_asm_new_abstractmethoderror
449                                             /* exception pointer is return value  */
450         add     $(3*4),sp                   /* remove stack frame                 */
451
452         pop     xpc                         /* get exception address              */
453         sub     $2,xpc                      /* exception address is ra - 2        */
454         jmp     L_asm_handle_exception
455
456
457 /* asm_patcher_wrapper *********************************************************
458
459    XXX
460
461    Stack layout:
462      24   return address
463      20   REG_ITMP3
464      16   pointer to virtual java_objectheader
465      12   last byte of machine code (xmcode)
466       8   machine code (which is patched back later)
467       4   unresolved field reference
468       0   patcher function pointer to call
469
470 *******************************************************************************/
471
472 asm_patcher_wrapper:
473         sub     $((1+4+4)*4),sp             /* keep stack 16-byte aligned         */
474
475         mov     itmp1,(0+4)*4(sp)           /* save itmp1 and itmp2               */
476         mov     itmp2,(1+4)*4(sp)
477
478         mov     sp,itmp1                    /* pass SP of patcher stub            */
479         add     $((1+4+4)*4),itmp1
480         mov     itmp1,0*4(sp)
481         movl    $0,1*4(sp)                  /* pass PV (if NULL, use findmethod)  */
482         movl    $0,2*4(sp)                  /* pass RA (it's on the stack)        */
483         call    patcher_wrapper
484         mov     v0,itmp3                    /* save return value                  */
485
486         mov     (0+4)*4(sp),itmp1           /* restore itmp1 and itmp2            */
487         mov     (1+4)*4(sp),itmp2
488
489         test    itmp3,itmp3                 /* exception thrown?                  */
490         jne     L_asm_patcher_wrapper_exception
491
492         mov     (5+1+4+4)*4(sp),itmp3       /* restore itmp3                      */
493         add     $((6+1+4+4)*4),sp           /* remove stack frame, keep RA        */
494
495         ret                                 /* jump to new patched code           */
496
497 L_asm_patcher_wrapper_exception:
498         add     $((6+2+4)*4),sp             /* remove stack frame, keep RA        */
499         add     $((6+1+4+4)*4),sp           /* remove stack frame, keep RA        */
500         mov     itmp3,xptr                  /* get exception                      */
501         pop     xpc                         /* get and remove return address      */
502         jmp     L_asm_handle_exception
503
504
505 /* asm_replacement_out *********************************************************
506
507    This code is jumped to from the replacement-out stubs that are executed
508    when a thread reaches an activated replacement point.
509
510    The purpose of asm_replacement_out is to read out the parts of the
511    execution state that cannot be accessed from C code, store this state,
512    and then call the C function replace_me.
513
514    Stack layout:
515       4                 start of stack inside method to replace
516       0   rplpoint *    info on the replacement point that was reached
517
518 *******************************************************************************/
519
520 /* some room to accomodate changes of the stack frame size during replacement */
521         /* XXX we should find a cleaner solution here */
522 #define REPLACEMENT_ROOM  512
523
524 asm_replacement_out:
525     /* create stack frame */
526         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
527
528         /* save registers in execution state */
529         mov     %eax,(EAX*8+offes_intregs)(sp)
530         mov     %ebx,(EBX*8+offes_intregs)(sp)
531         mov     %ecx,(ECX*8+offes_intregs)(sp)
532         mov     %edx,(EDX*8+offes_intregs)(sp)
533         mov     %esi,(ESI*8+offes_intregs)(sp)
534         mov     %edi,(EDI*8+offes_intregs)(sp)
535         mov     %ebp,(EBP*8+offes_intregs)(sp)
536         movl    $0  ,(ESP*8+offes_intregs)(sp) /* not used */
537
538 #ifndef NDEBUG
539         /* clear high 32bit */
540         movl    $0,(4+0*8+offes_intregs)(sp)
541         movl    $0,(4+1*8+offes_intregs)(sp)
542         movl    $0,(4+2*8+offes_intregs)(sp)
543         movl    $0,(4+3*8+offes_intregs)(sp)
544         movl    $0,(4+4*8+offes_intregs)(sp)
545         movl    $0,(4+5*8+offes_intregs)(sp)
546         movl    $0,(4+6*8+offes_intregs)(sp)
547         movl    $0,(4+7*8+offes_intregs)(sp)
548 #endif
549
550         /* calculate sp of method */
551         mov     sp,itmp1
552         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
553         mov     itmp1,(offes_sp)(sp)
554
555         /* pv must be looked up via AVL tree */
556         movl    $0,(offes_pv)(sp)
557
558         /* call replace_me */
559         mov     -4(itmp1),itmp1             /* rplpoint *                         */
560     push    sp                          /* arg1: execution state              */
561     push    itmp1                       /* arg0: replacement point            */
562     call    replace_me                  /* call C function replace_me         */
563
564
565 /* asm_replacement_in **********************************************************
566
567    This code writes the given execution state and jumps to the replacement
568    code.
569
570    This function never returns!
571
572    C prototype:
573       void asm_replacement_in(executionstate *es);
574
575 *******************************************************************************/
576
577 asm_replacement_in:
578         mov     4(sp),%ebp                  /* executionstate *es                 */
579
580         /* set new sp */
581         mov     (offes_sp)(%ebp),%esp
582         
583         /* store address of new code */
584         push    (offes_pc)(%ebp)
585         
586         /* copy registers from execution state */
587         mov     (EAX*8+offes_intregs)(%ebp),%eax
588         mov     (EBX*8+offes_intregs)(%ebp),%ebx
589         mov     (ECX*8+offes_intregs)(%ebp),%ecx
590         mov     (EDX*8+offes_intregs)(%ebp),%edx
591         mov     (ESI*8+offes_intregs)(%ebp),%esi
592         mov     (EDI*8+offes_intregs)(%ebp),%edi
593
594         mov     (EBP*8+offes_intregs)(%ebp),%ebp
595
596         /* jump to new code */
597         ret
598
599
600 /************************ function asm_builtin_x2x *****************************
601 *                                                                              *
602 *   Wrapper functions for corner cases                                         *
603 *                                                                              *
604 *******************************************************************************/
605
606 asm_builtin_f2i:
607         sub     $(3*4),%esp
608         fsts    (%esp)
609         call    builtin_f2i
610         add     $(3*4),%esp
611         ret
612
613 asm_builtin_d2i:
614         sub     $(3*4),%esp
615         fstl    (%esp)
616         call    builtin_d2i
617         add     $(3*4),%esp
618         ret
619
620 asm_builtin_f2l:
621         sub     $(3*4),%esp
622         fsts    (%esp)
623         call    builtin_f2l
624         add     $(3*4),%esp
625         ret
626
627 asm_builtin_d2l:
628         sub     $(3*4),%esp
629         fstl    (%esp)
630         call    builtin_d2l
631         add     $(3*4),%esp
632         ret
633
634
635 asm_getclassvalues_atomic:
636 _crit_restart2:
637         mov     4(%esp),%ecx        /* super */
638         mov     8(%esp),%edx        /* sub */
639 _crit_begin2:
640         mov     offbaseval(%ecx),%eax
641         mov     offdiffval(%ecx),%ecx
642         mov     offbaseval(%edx),%edx
643 _crit_end2:
644         push    %ebx
645         mov     16(%esp),%ebx      /* out */
646         mov     %eax,offcast_super_baseval(%ebx)
647         mov     %ecx,offcast_super_diffval(%ebx)
648         mov     %edx,offcast_sub_baseval(%ebx)
649         pop     %ebx
650         ret
651
652         .data
653
654 asm_criticalsections:
655 #if defined(ENABLE_THREADS)
656 #if 0
657         .long   _crit_begin1
658         .long   _crit_end1
659         .long   _crit_restart1
660 #endif
661         .long   _crit_begin2
662         .long   _crit_end2
663         .long   _crit_restart2
664 #endif
665         .long 0
666
667
668 /* Disable exec-stacks, required for Gentoo ***********************************/
669
670 #if defined(__GCC__) && defined(__ELF__)
671         .section .note.GNU-stack,"",@progbits
672 #endif
673
674
675 /* asm_get_cycle_count *********************************************************
676
677    Get the current time-stamp counter from the CPU.
678
679 *******************************************************************************/
680
681 asm_get_cycle_count:
682         rdtsc
683         ret
684
685
686 /*
687  * These are local overrides for various environment variables in Emacs.
688  * Please do not remove this and leave it at the end of the file, where
689  * Emacs will automagically detect them.
690  * ---------------------------------------------------------------------
691  * Local variables:
692  * mode: asm
693  * indent-tabs-mode: t
694  * c-basic-offset: 4
695  * tab-width: 4
696  * End:
697  * vim:noexpandtab:sw=4:ts=4:
698  */