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