* src/vm/jit/i386/asmpart.S (L_asm_patcher_wrapper_exception): Removed
[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 5256 2006-08-21 15:25:59Z 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+1+4+4)*4),sp           /* remove stack frame, keep RA        */
499         mov     itmp3,xptr                  /* get exception                      */
500         pop     xpc                         /* get and remove return address      */
501         jmp     L_asm_handle_exception
502
503
504 /* asm_replacement_out *********************************************************
505
506    This code is jumped to from the replacement-out stubs that are executed
507    when a thread reaches an activated replacement point.
508
509    The purpose of asm_replacement_out is to read out the parts of the
510    execution state that cannot be accessed from C code, store this state,
511    and then call the C function replace_me.
512
513    Stack layout:
514       4                 start of stack inside method to replace
515       0   rplpoint *    info on the replacement point that was reached
516
517 *******************************************************************************/
518
519 /* some room to accomodate changes of the stack frame size during replacement */
520         /* XXX we should find a cleaner solution here */
521 #define REPLACEMENT_ROOM  512
522
523 asm_replacement_out:
524     /* create stack frame */
525         sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
526
527         /* save registers in execution state */
528         mov     %eax,(EAX*8+offes_intregs)(sp)
529         mov     %ebx,(EBX*8+offes_intregs)(sp)
530         mov     %ecx,(ECX*8+offes_intregs)(sp)
531         mov     %edx,(EDX*8+offes_intregs)(sp)
532         mov     %esi,(ESI*8+offes_intregs)(sp)
533         mov     %edi,(EDI*8+offes_intregs)(sp)
534         mov     %ebp,(EBP*8+offes_intregs)(sp)
535         movl    $0  ,(ESP*8+offes_intregs)(sp) /* not used */
536
537 #ifndef NDEBUG
538         /* clear high 32bit */
539         movl    $0,(4+0*8+offes_intregs)(sp)
540         movl    $0,(4+1*8+offes_intregs)(sp)
541         movl    $0,(4+2*8+offes_intregs)(sp)
542         movl    $0,(4+3*8+offes_intregs)(sp)
543         movl    $0,(4+4*8+offes_intregs)(sp)
544         movl    $0,(4+5*8+offes_intregs)(sp)
545         movl    $0,(4+6*8+offes_intregs)(sp)
546         movl    $0,(4+7*8+offes_intregs)(sp)
547 #endif
548
549         /* calculate sp of method */
550         mov     sp,itmp1
551         add     $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
552         mov     itmp1,(offes_sp)(sp)
553
554         /* pv must be looked up via AVL tree */
555         movl    $0,(offes_pv)(sp)
556
557         /* call replace_me */
558         mov     -4(itmp1),itmp1             /* rplpoint *                         */
559     push    sp                          /* arg1: execution state              */
560     push    itmp1                       /* arg0: replacement point            */
561     call    replace_me                  /* call C function replace_me         */
562
563
564 /* asm_replacement_in **********************************************************
565
566    This code writes the given execution state and jumps to the replacement
567    code.
568
569    This function never returns!
570
571    C prototype:
572       void asm_replacement_in(executionstate *es);
573
574 *******************************************************************************/
575
576 asm_replacement_in:
577         mov     4(sp),%ebp                  /* executionstate *es                 */
578
579         /* set new sp */
580         mov     (offes_sp)(%ebp),%esp
581         
582         /* store address of new code */
583         push    (offes_pc)(%ebp)
584         
585         /* copy registers from execution state */
586         mov     (EAX*8+offes_intregs)(%ebp),%eax
587         mov     (EBX*8+offes_intregs)(%ebp),%ebx
588         mov     (ECX*8+offes_intregs)(%ebp),%ecx
589         mov     (EDX*8+offes_intregs)(%ebp),%edx
590         mov     (ESI*8+offes_intregs)(%ebp),%esi
591         mov     (EDI*8+offes_intregs)(%ebp),%edi
592
593         mov     (EBP*8+offes_intregs)(%ebp),%ebp
594
595         /* jump to new code */
596         ret
597
598
599 /************************ function asm_builtin_x2x *****************************
600 *                                                                              *
601 *   Wrapper functions for corner cases                                         *
602 *                                                                              *
603 *******************************************************************************/
604
605 asm_builtin_f2i:
606         sub     $(3*4),%esp
607         fsts    (%esp)
608         call    builtin_f2i
609         add     $(3*4),%esp
610         ret
611
612 asm_builtin_d2i:
613         sub     $(3*4),%esp
614         fstl    (%esp)
615         call    builtin_d2i
616         add     $(3*4),%esp
617         ret
618
619 asm_builtin_f2l:
620         sub     $(3*4),%esp
621         fsts    (%esp)
622         call    builtin_f2l
623         add     $(3*4),%esp
624         ret
625
626 asm_builtin_d2l:
627         sub     $(3*4),%esp
628         fstl    (%esp)
629         call    builtin_d2l
630         add     $(3*4),%esp
631         ret
632
633
634 asm_getclassvalues_atomic:
635 _crit_restart2:
636         mov     4(%esp),%ecx        /* super */
637         mov     8(%esp),%edx        /* sub */
638 _crit_begin2:
639         mov     offbaseval(%ecx),%eax
640         mov     offdiffval(%ecx),%ecx
641         mov     offbaseval(%edx),%edx
642 _crit_end2:
643         push    %ebx
644         mov     16(%esp),%ebx      /* out */
645         mov     %eax,offcast_super_baseval(%ebx)
646         mov     %ecx,offcast_super_diffval(%ebx)
647         mov     %edx,offcast_sub_baseval(%ebx)
648         pop     %ebx
649         ret
650
651         .data
652
653 asm_criticalsections:
654 #if defined(ENABLE_THREADS)
655 #if 0
656         .long   _crit_begin1
657         .long   _crit_end1
658         .long   _crit_restart1
659 #endif
660         .long   _crit_begin2
661         .long   _crit_end2
662         .long   _crit_restart2
663 #endif
664         .long 0
665
666
667 /* Disable exec-stacks, required for Gentoo ***********************************/
668
669 #if defined(__GCC__) && defined(__ELF__)
670         .section .note.GNU-stack,"",@progbits
671 #endif
672
673
674 /* asm_get_cycle_count *********************************************************
675
676    Get the current time-stamp counter from the CPU.
677
678 *******************************************************************************/
679
680 asm_get_cycle_count:
681         rdtsc
682         ret
683
684
685 /*
686  * These are local overrides for various environment variables in Emacs.
687  * Please do not remove this and leave it at the end of the file, where
688  * Emacs will automagically detect them.
689  * ---------------------------------------------------------------------
690  * Local variables:
691  * mode: asm
692  * indent-tabs-mode: t
693  * c-basic-offset: 4
694  * tab-width: 4
695  * End:
696  * vim:noexpandtab:sw=4:ts=4:
697  */