1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
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
8 This file is part of CACAO.
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.
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.
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
25 $Id: asmpart.S 7661 2007-04-03 22:29:59Z twisti $
32 #include "vm/jit/x86_64/arch.h"
33 #include "vm/jit/x86_64/md-abi.h"
34 #include "vm/jit/x86_64/md-asm.h"
35 #include "vm/jit/x86_64/offsets.h"
37 #include "vm/jit/abi-asm.h"
38 #include "vm/jit/methodheader.h"
44 /* export functions ***********************************************************/
46 .globl asm_vm_call_method
47 .globl asm_vm_call_method_int
48 .globl asm_vm_call_method_long
49 .globl asm_vm_call_method_float
50 .globl asm_vm_call_method_double
51 .globl asm_vm_call_method_exception_handler
52 .globl asm_vm_call_method_end
54 .globl asm_call_jit_compiler
56 .globl asm_handle_exception
57 .globl asm_handle_nat_exception
59 .globl asm_abstractmethoderror
61 .globl asm_patcher_wrapper
63 #if defined(ENABLE_REPLACEMENT)
64 .globl asm_replacement_out
65 .globl asm_replacement_in
68 .globl asm_builtin_f2i
69 .globl asm_builtin_f2l
70 .globl asm_builtin_d2i
71 .globl asm_builtin_d2l
73 .globl asm_compare_and_swap
74 .globl asm_memory_barrier
76 .globl asm_criticalsections
77 .globl asm_getclassvalues_atomic
80 /********************* function asm_calljavafunction ***************************
82 * This function calls a Java-method (which possibly needs compilation) *
83 * with up to 4 address parameters. *
85 * This functions calls the JIT-compiler which eventually translates the *
86 * method into machine code. *
89 * javaobject_header *asm_calljavamethod (methodinfo *m, *
90 * void *arg1, void *arg2, void *arg3, void *arg4); *
92 *******************************************************************************/
96 .quad 0 /* catch type all */
97 .quad 0 /* handler pc */
99 .quad 0 /* start pc */
100 .long 1 /* extable size */
101 .long 0 /* ALIGNMENT PADDING */
102 .quad 0 /* line number table start */
103 .quad 0 /* line number table size */
104 .long 0 /* ALIGNMENT PADDING */
105 .long 0 /* fltsave */
106 .long 0 /* intsave */
109 .long 0 /* frame size */
110 .quad 0 /* codeinfo pointer */
113 asm_vm_call_method_int:
114 asm_vm_call_method_long:
115 asm_vm_call_method_float:
116 asm_vm_call_method_double:
117 sub $(7*8),sp /* keep stack 16-byte aligned */
118 mov %rbx,0*8(sp) /* %rbx is not a callee saved in cacao*/
125 mov a0,itmp1 /* move method pointer for compiler */
126 xor %rbp,%rbp /* set argument stack frame to zero */
128 test a1,a1 /* maybe we have no args... */
131 mov a1,itmp3 /* arg count */
132 mov a2,itmp2 /* pointer to arg block */
134 mov itmp2,%r14 /* save argument block pointer */
135 mov itmp3,%r15 /* save argument count */
137 sub $sizevmarg,itmp2 /* initialize pointer (smaller code) */
138 add $1,itmp3 /* initialize argument count */
139 xor %r12,%r12 /* initialize integer argument counter*/
140 xor %r13,%r13 /* initialize float argument counter */
143 add $sizevmarg,itmp2 /* goto next argument block */
144 dec itmp3 /* argument count - 1 */
145 jz L_register_copy_done
146 andb $0x02,offvmargtype(itmp2) /* is this a float/double type? */
147 jnz L_register_handle_float /* yes, handle it */
149 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
150 je L_register_copy /* register? yes, next loop */
152 lea jumptable_integer(%rip),%rbp
153 mov 0(%rbp,%r12,8),%rbx
154 inc %r12 /* integer argument counter + 1 */
157 L_register_handle_float:
158 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
159 je L_register_copy /* register? yes, next loop */
161 lea jumptable_float(%rip),%rbp
162 mov 0(%rbp,%r13,8),%rbx
163 inc %r13 /* float argument counter + 1 */
166 L_register_copy_done:
167 mov %r15,%rbp /* calculate remaining arguments */
168 sub %r12,%rbp /* - integer arguments in registers */
169 sub %r13,%rbp /* - float arguments in registers */
170 jle L_copy_done /* are all assigned to registers? */
172 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
173 shl $3,%rbp /* calculate stack size */
174 sub %rbp,sp /* stack frame for arguments */
175 mov sp,%rbx /* use %rbx as temp sp */
177 sub $sizevmarg,%r14 /* initialize pointer (smaller code) */
178 add $1,%r15 /* initialize argument count */
181 add $sizevmarg,%r14 /* goto next argument block */
182 dec %r15 /* are there any arguments left? */
183 jz L_copy_done /* no test needed after dec */
185 andb $0x02,offvmargtype(%r14) /* is this a float/double type? */
186 jnz L_stack_handle_float
187 dec %r12 /* arguments assigned to registers */
188 jge L_stack_copy_loop
191 L_stack_handle_float:
192 dec %r13 /* arguments assigned to registers */
193 jge L_stack_copy_loop
196 mov offvmargdata(%r14),itmp3 /* copy s8 argument onto stack */
198 add $8,%rbx /* increase sp to next argument */
199 jmp L_stack_copy_loop
202 /* itmp1 still contains method pointer*/
203 lea L_asm_call_jit_compiler(%rip),mptr
204 mov sp,itmp3 /* calculate the old stack pointer */
207 lea (6*8-256)(itmp3),mptr /* We subtract 256 to force the next */
208 /* move instruction to have a 32-bit */
211 mov (0*8+256)(mptr),itmp3 /* method call as in Java */
212 call *itmp3 /* call JIT compiler */
214 add bp,sp /* remove argument stack frame if any */
216 L_asm_vm_call_method_return:
217 mov 0*8(sp),%rbx /* restore callee saved registers */
223 add $(7*8),sp /* free stack space */
226 asm_vm_call_method_exception_handler:
227 mov xptr,a0 /* pass exception pointer */
228 call builtin_throw_exception@PLT
229 jmp L_asm_vm_call_method_return
241 mov offvmargdata(itmp2),a0
244 mov offvmargdata(itmp2),a1
247 mov offvmargdata(itmp2),a2
250 mov offvmargdata(itmp2),a3
253 mov offvmargdata(itmp2),a4
256 mov offvmargdata(itmp2),a5
271 movq offvmargdata(itmp2),fa0
274 movq offvmargdata(itmp2),fa1
277 movq offvmargdata(itmp2),fa2
280 movq offvmargdata(itmp2),fa3
283 movq offvmargdata(itmp2),fa4
286 movq offvmargdata(itmp2),fa5
289 movq offvmargdata(itmp2),fa6
292 movq offvmargdata(itmp2),fa7
295 asm_vm_call_method_end:
298 /****************** function asm_call_jit_compiler *****************************
300 * invokes the compiler for untranslated JavaVM methods. *
302 * Register R0 contains a pointer to the method info structure (prepared *
303 * by createcompilerstub). Using the return address in R26 and the *
304 * offset in the LDA instruction or using the value in methodptr R28 the *
305 * patching address for storing the method address can be computed: *
307 * method address was either loaded using *
309 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
310 * i386_call_reg(REG_ITMP2) *
314 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
315 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
316 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
317 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
318 * i386_call_reg(REG_ITMP1) *
320 * in the static case the method pointer can be computed using the *
321 * return address and the lda function following the jmp instruction *
323 *******************************************************************************/
325 asm_call_jit_compiler:
326 L_asm_call_jit_compiler: /* required for PIC code */
327 sub $(ARG_CNT+1)*8,sp /* +1: keep stack 16-byte aligned */
329 SAVE_ARGUMENT_REGISTERS(0)
331 mov itmp1,a0 /* pass methodinfo pointer */
332 mov mptr,a1 /* pass method pointer */
333 mov sp,a2 /* pass java sp */
334 add $(1+ARG_CNT+1)*8,a2
335 mov (ARG_CNT+1)*8(sp),a3 /* pass ra to java function */
336 call jit_asm_compile@PLT
338 RESTORE_ARGUMENT_REGISTERS(0)
340 add $(ARG_CNT+1)*8,sp /* remove stack frame */
342 test v0,v0 /* check for exception */
343 je L_asm_call_jit_compiler_exception
345 jmp *v0 /* ...and now call the new method */
347 L_asm_call_jit_compiler_exception:
348 call exceptions_get_and_clear_exception@PLT
349 pop xpc /* delete return address */
350 sub $3,xpc /* faulting address is ra - 3 */
351 jmp L_asm_handle_exception
354 /* asm_handle_exception ********************************************************
356 * This function handles an exception. It does not use the usual calling *
357 * conventions. The exception pointer is passed in REG_ITMP1 and the *
358 * pc from the exception raising position is passed in REG_ITMP2. It searches *
359 * the local exception table for a handler. If no one is found, it unwinds *
360 * stacks and continues searching the callers. *
362 *******************************************************************************/
364 asm_handle_nat_exception:
365 add $8,sp /* clear return address of native stub*/
367 asm_handle_exception:
368 L_asm_handle_exception: /* required for PIC code */
369 sub $((ARG_CNT+TMP_CNT)*8),sp /* create maybe-leaf stackframe */
371 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
372 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
374 mov $((ARG_CNT+TMP_CNT)*8),a3 /* prepare a3 for handle_exception */
375 mov $1,t0 /* set maybe-leaf flag */
377 L_asm_handle_exception_stack_loop:
379 mov xptr,0*8(sp) /* save exception pointer */
380 mov xpc,1*8(sp) /* save exception pc */
381 add sp,a3 /* calculate Java sp into a3... */
383 mov a3,3*8(sp) /* ...and save it */
384 mov t0,4*8(sp) /* save maybe-leaf flag */
386 mov xpc,a0 /* exception pc */
387 call codegen_get_pv_from_pc@PLT
388 mov v0,2*8(sp) /* save data segment pointer */
390 mov 0*8(sp),a0 /* pass exception pointer */
391 mov 1*8(sp),a1 /* pass exception pc */
392 mov v0,a2 /* pass data segment pointer */
393 mov 3*8(sp),a3 /* pass Java stack pointer */
394 call exceptions_handle_exception@PLT
397 jz L_asm_handle_exception_not_catched
399 mov v0,xpc /* move handlerpc into xpc */
400 mov 0*8(sp),xptr /* restore exception pointer */
401 mov 4*8(sp),t0 /* get maybe-leaf flag */
402 add $(6*8),sp /* free stack frame */
404 test t0,t0 /* test for maybe-leaf flag */
405 jz L_asm_handle_exception_no_leaf
407 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
408 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
410 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
412 L_asm_handle_exception_no_leaf:
413 jmp *xpc /* jump to the handler */
415 L_asm_handle_exception_not_catched:
416 mov 0*8(sp),xptr /* restore exception pointer */
417 mov 2*8(sp),itmp3 /* restore data segment pointer */
418 mov 4*8(sp),t0 /* get maybe-leaf flag */
422 jz L_asm_handle_exception_no_leaf_stack
424 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
425 xor t0,t0 /* clear the isleaf flags */
427 L_asm_handle_exception_no_leaf_stack:
428 mov FrameSize(itmp3),itmp2l /* get frame size */
429 add sp,itmp2 /* pointer to save area */
431 mov IntSave(itmp3),a0l /* a0l = saved int register count */
454 shl $3,a0l /* multiply by 8 bytes */
459 mov FltSave(itmp3),a0l /* a0l = saved flt register count */
472 movq -5*8(itmp2),%xmm11
474 movq -4*8(itmp2),%xmm12
476 movq -3*8(itmp2),%xmm13
478 movq -2*8(itmp2),%xmm14
480 movq -1*8(itmp2),%xmm15
484 mov FrameSize(itmp3),itmp2l /* get frame size */
485 add itmp2,sp /* unwind stack */
487 /* exception pointer is still set */
488 pop xpc /* the new xpc is return address */
489 sub $3,xpc /* subtract 3 bytes for call */
491 xor a3,a3 /* prepare a3 for handle_exception */
493 jmp L_asm_handle_exception_stack_loop
496 /* asm_abstractmethoderror *****************************************************
498 Creates and throws an AbstractMethodError.
500 *******************************************************************************/
502 asm_abstractmethoderror:
503 mov sp,a0 /* pass java sp */
505 mov 0*8(sp),a1 /* pass exception address */
507 call exceptions_asm_new_abstractmethoderror@PLT
508 /* exception pointer is return value */
509 pop xpc /* get exception address */
510 sub $3,xpc /* exception address is ra - 3 */
511 jmp L_asm_handle_exception
514 /* asm_patcher_wrapper *********************************************************
520 32 pointer to virtual java_objectheader
521 24 machine code (which is patched back later)
522 16 unresolved class/method/field reference
523 8 data segment displacement from load instructions
524 0 pointer to patcher function
527 *******************************************************************************/
530 push bp /* save base pointer */
531 mov sp,bp /* move actual sp to bp */
532 sub $(3+ARG_CNT+TMP_CNT)*8,sp
533 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
534 /* leaf functions) */
536 SAVE_ARGUMENT_REGISTERS(3)
537 SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
539 mov itmp1,0*8(sp) /* save itmp1 and itmp2 */
540 mov itmp2,1*8(sp) /* can be used by some instructions */
542 mov bp,a0 /* pass SP of patcher stub */
544 mov $0,a1 /* pass PV (if NULL, use findmethod) */
545 mov $0,a2 /* pass RA (it's on the stack) */
546 call patcher_wrapper@PLT
547 mov v0,2*8(sp) /* save return value */
549 RESTORE_ARGUMENT_REGISTERS(3)
550 RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
552 mov 0*8(sp),itmp1 /* restore itmp1 and itmp2 */
553 mov 1*8(sp),itmp2 /* can be used by some instructions */
554 mov 2*8(sp),itmp3 /* restore return value */
556 mov bp,sp /* restore original sp */
557 pop bp /* restore bp */
558 add $(5*8),sp /* remove patcher stackframe, keep RA */
560 test itmp3,itmp3 /* exception thrown? */
561 jne L_asm_patcher_wrapper_exception
562 ret /* call new patched code */
564 L_asm_patcher_wrapper_exception:
565 mov itmp3,xptr /* get exception */
566 pop xpc /* get and remove return address */
567 jmp L_asm_handle_exception
569 #if defined(ENABLE_REPLACEMENT)
571 /* asm_replacement_out *********************************************************
573 This code is jumped to from the replacement-out stubs that are executed
574 when a thread reaches an activated replacement point.
576 The purpose of asm_replacement_out is to read out the parts of the
577 execution state that cannot be accessed from C code, store this state,
578 and then call the C function replace_me.
581 8 start of stack inside method to replace
582 0 rplpoint * info on the replacement point that was reached
584 *******************************************************************************/
586 /* some room to accomodate changes of the stack frame size during replacement */
587 /* XXX we should find a cleaner solution here */
588 #define REPLACEMENT_ROOM 512
591 /* create stack frame */
592 sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
594 /* save registers in execution state */
595 mov %rax,(RAX*8+offes_intregs)(sp)
596 mov %rbx,(RBX*8+offes_intregs)(sp)
597 mov %rcx,(RCX*8+offes_intregs)(sp)
598 mov %rdx,(RDX*8+offes_intregs)(sp)
599 mov %rsi,(RSI*8+offes_intregs)(sp)
600 mov %rdi,(RDI*8+offes_intregs)(sp)
601 mov %rbp,(RBP*8+offes_intregs)(sp)
602 movq $0 ,(RSP*8+offes_intregs)(sp) /* not used */
603 mov %r8 ,(R8 *8+offes_intregs)(sp)
604 mov %r9 ,(R9 *8+offes_intregs)(sp)
605 mov %r10,(R10*8+offes_intregs)(sp)
606 mov %r11,(R11*8+offes_intregs)(sp)
607 mov %r12,(R12*8+offes_intregs)(sp)
608 mov %r13,(R13*8+offes_intregs)(sp)
609 mov %r14,(R14*8+offes_intregs)(sp)
610 mov %r15,(R15*8+offes_intregs)(sp)
612 movq %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
613 movq %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
614 movq %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
615 movq %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
616 movq %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
617 movq %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
618 movq %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
619 movq %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
620 movq %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
621 movq %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
622 movq %xmm10,(XMM10*8+offes_fltregs)(sp)
623 movq %xmm11,(XMM11*8+offes_fltregs)(sp)
624 movq %xmm12,(XMM12*8+offes_fltregs)(sp)
625 movq %xmm13,(XMM13*8+offes_fltregs)(sp)
626 movq %xmm14,(XMM14*8+offes_fltregs)(sp)
627 movq %xmm15,(XMM15*8+offes_fltregs)(sp)
629 /* calculate sp of method */
631 add $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
632 mov itmp1,(offes_sp)(sp)
634 /* pv must be looked up via AVL tree */
635 movq $0,(offes_pv)(sp)
637 /* call replace_me */
638 mov -8(itmp1),a0 /* rplpoint * */
639 mov sp,a1 /* arg1: execution state */
640 call replace_me@PLT /* call C function replace_me */
641 call abort@PLT /* NEVER REACHED */
643 /* asm_replacement_in **********************************************************
645 This code writes the given execution state and jumps to the replacement
648 This function never returns!
651 void asm_replacement_in(executionstate *es, replace_safestack_t *st);
653 *******************************************************************************/
657 mov a1,s1 /* replace_safestack_t *st */
658 mov a0,%rbp /* executionstate *es == safe stack */
660 /* switch to the safe stack */
663 /* call replace_build_execution_state(st) */
665 call replace_build_execution_state@PLT
668 mov (offes_sp)(%rbp),sp
670 /* push address of new code */
671 pushq (offes_pc)(%rbp)
673 /* allocate an executionstate_t on the stack */
674 sub $(sizeexecutionstate),sp
676 /* call replace_free_safestack(st,& of allocated executionstate_t) */
679 call replace_free_safestack@PLT
681 /* copy registers from execution state */
682 movq (XMM0 *8+offes_fltregs)(sp),%xmm0
683 movq (XMM1 *8+offes_fltregs)(sp),%xmm1
684 movq (XMM2 *8+offes_fltregs)(sp),%xmm2
685 movq (XMM3 *8+offes_fltregs)(sp),%xmm3
686 movq (XMM4 *8+offes_fltregs)(sp),%xmm4
687 movq (XMM5 *8+offes_fltregs)(sp),%xmm5
688 movq (XMM6 *8+offes_fltregs)(sp),%xmm6
689 movq (XMM7 *8+offes_fltregs)(sp),%xmm7
690 movq (XMM8 *8+offes_fltregs)(sp),%xmm8
691 movq (XMM9 *8+offes_fltregs)(sp),%xmm9
692 movq (XMM10*8+offes_fltregs)(sp),%xmm10
693 movq (XMM11*8+offes_fltregs)(sp),%xmm11
694 movq (XMM12*8+offes_fltregs)(sp),%xmm12
695 movq (XMM13*8+offes_fltregs)(sp),%xmm13
696 movq (XMM14*8+offes_fltregs)(sp),%xmm14
697 movq (XMM15*8+offes_fltregs)(sp),%xmm15
699 mov (RAX*8+offes_intregs)(sp),%rax
700 mov (RBX*8+offes_intregs)(sp),%rbx
701 mov (RCX*8+offes_intregs)(sp),%rcx
702 mov (RDX*8+offes_intregs)(sp),%rdx
703 mov (RSI*8+offes_intregs)(sp),%rsi
704 mov (RDI*8+offes_intregs)(sp),%rdi
705 mov (RBP*8+offes_intregs)(sp),%rbp
706 mov (R8 *8+offes_intregs)(sp),%r8
707 mov (R9 *8+offes_intregs)(sp),%r9
708 mov (R10*8+offes_intregs)(sp),%r10
709 mov (R11*8+offes_intregs)(sp),%r11
710 mov (R12*8+offes_intregs)(sp),%r12
711 mov (R13*8+offes_intregs)(sp),%r13
712 mov (R14*8+offes_intregs)(sp),%r14
713 mov (R15*8+offes_intregs)(sp),%r15
715 /* pop the execution state off the stack */
716 add $(sizeexecutionstate),sp
718 /* jump to new code */
721 #endif /* defined(ENABLE_REPLACEMENT) */
724 /* asm_builtin_x2x *************************************************************
726 * Wrapper functions for float to int corner cases *
728 *******************************************************************************/
733 SAVE_ARGUMENT_REGISTERS(0)
738 RESTORE_ARGUMENT_REGISTERS(0)
747 SAVE_ARGUMENT_REGISTERS(0)
752 RESTORE_ARGUMENT_REGISTERS(0)
761 SAVE_ARGUMENT_REGISTERS(0)
766 RESTORE_ARGUMENT_REGISTERS(0)
775 SAVE_ARGUMENT_REGISTERS(0)
780 RESTORE_ARGUMENT_REGISTERS(0)
786 /* asm_compare_and_swap ********************************************************
788 Does an atomic compare and swap. Required for the lock
791 *******************************************************************************/
793 asm_compare_and_swap:
794 mov a1,v0 /* v0 is %rax */
799 /* asm_memory_barrier **********************************************************
801 A memory barrier for the Java Memory Model.
803 *******************************************************************************/
810 asm_getclassvalues_atomic:
813 movl offbaseval(a0),itmp1l
814 movl offdiffval(a0),itmp2l
815 movl offbaseval(a1),itmp3l
817 movl itmp1l,offcast_super_baseval(a2)
818 movl itmp2l,offcast_super_diffval(a2)
819 movl itmp3l,offcast_sub_baseval(a2)
824 asm_criticalsections:
825 #if defined(ENABLE_THREADS)
833 /* disable exec-stacks ********************************************************/
835 #if defined(__linux__) && defined(__ELF__)
836 .section .note.GNU-stack,"",@progbits
841 * These are local overrides for various environment variables in Emacs.
842 * Please do not remove this and leave it at the end of the file, where
843 * Emacs will automagically detect them.
844 * ---------------------------------------------------------------------
847 * indent-tabs-mode: t
851 * vim:noexpandtab:sw=4:ts=4: