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 7475 2007-03-07 12:37:34Z 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
53 .globl asm_call_jit_compiler
55 .globl asm_handle_exception
56 .globl asm_handle_nat_exception
58 .globl asm_abstractmethoderror
60 .globl asm_patcher_wrapper
62 #if defined(ENABLE_REPLACEMENT)
63 .globl asm_replacement_out
64 .globl asm_replacement_in
67 .globl asm_builtin_f2i
68 .globl asm_builtin_f2l
69 .globl asm_builtin_d2i
70 .globl asm_builtin_d2l
72 .globl asm_compare_and_swap
73 .globl asm_memory_barrier
75 .globl asm_criticalsections
76 .globl asm_getclassvalues_atomic
79 /********************* function asm_calljavafunction ***************************
81 * This function calls a Java-method (which possibly needs compilation) *
82 * with up to 4 address parameters. *
84 * This functions calls the JIT-compiler which eventually translates the *
85 * method into machine code. *
88 * javaobject_header *asm_calljavamethod (methodinfo *m, *
89 * void *arg1, void *arg2, void *arg3, void *arg4); *
91 *******************************************************************************/
95 .quad 0 /* catch type all */
96 .quad 0 /* handler pc */
98 .quad 0 /* start pc */
99 .long 1 /* extable size */
100 .long 0 /* ALIGNMENT PADDING */
101 .quad 0 /* line number table start */
102 .quad 0 /* line number table size */
103 .long 0 /* ALIGNMENT PADDING */
104 .long 0 /* fltsave */
105 .long 0 /* intsave */
108 .long 0 /* frame size */
109 .quad 0 /* codeinfo pointer */
112 asm_vm_call_method_int:
113 asm_vm_call_method_long:
114 asm_vm_call_method_float:
115 asm_vm_call_method_double:
116 sub $(7*8),sp /* keep stack 16-byte aligned */
117 mov %rbx,0*8(sp) /* %rbx is not a callee saved in cacao*/
124 mov a0,itmp1 /* move method pointer for compiler */
125 xor %rbp,%rbp /* set argument stack frame to zero */
127 test a1,a1 /* maybe we have no args... */
130 mov a1,itmp3 /* arg count */
131 mov a2,itmp2 /* pointer to arg block */
133 mov itmp2,%r14 /* save argument block pointer */
134 mov itmp3,%r15 /* save argument count */
136 sub $sizevmarg,itmp2 /* initialize pointer (smaller code) */
137 add $1,itmp3 /* initialize argument count */
138 xor %r12,%r12 /* initialize integer argument counter*/
139 xor %r13,%r13 /* initialize float argument counter */
142 add $sizevmarg,itmp2 /* goto next argument block */
143 dec itmp3 /* argument count - 1 */
144 jz L_register_copy_done
145 andb $0x02,offvmargtype(itmp2) /* is this a float/double type? */
146 jnz L_register_handle_float /* yes, handle it */
148 cmp $INT_ARG_CNT,%r12 /* are we out of integer argument */
149 je L_register_copy /* register? yes, next loop */
151 lea jumptable_integer(%rip),%rbp
152 mov 0(%rbp,%r12,8),%rbx
153 inc %r12 /* integer argument counter + 1 */
156 L_register_handle_float:
157 cmp $FLT_ARG_CNT,%r13 /* are we out of float argument */
158 je L_register_copy /* register? yes, next loop */
160 lea jumptable_float(%rip),%rbp
161 mov 0(%rbp,%r13,8),%rbx
162 inc %r13 /* float argument counter + 1 */
165 L_register_copy_done:
166 mov %r15,%rbp /* calculate remaining arguments */
167 sub %r12,%rbp /* - integer arguments in registers */
168 sub %r13,%rbp /* - float arguments in registers */
169 jle L_copy_done /* are all assigned to registers? */
171 and $0xfffffffffffffffe,%rbp /* keep stack 16-byte aligned */
172 shl $3,%rbp /* calculate stack size */
173 sub %rbp,sp /* stack frame for arguments */
174 mov sp,%rbx /* use %rbx as temp sp */
176 sub $sizevmarg,%r14 /* initialize pointer (smaller code) */
177 add $1,%r15 /* initialize argument count */
180 add $sizevmarg,%r14 /* goto next argument block */
181 dec %r15 /* are there any arguments left? */
182 jz L_copy_done /* no test needed after dec */
184 andb $0x02,offvmargtype(%r14) /* is this a float/double type? */
185 jnz L_stack_handle_float
186 dec %r12 /* arguments assigned to registers */
187 jge L_stack_copy_loop
190 L_stack_handle_float:
191 dec %r13 /* arguments assigned to registers */
192 jge L_stack_copy_loop
195 mov offvmargdata(%r14),itmp3 /* copy s8 argument onto stack */
197 add $8,%rbx /* increase sp to next argument */
198 jmp L_stack_copy_loop
201 /* itmp1 still contains method pointer*/
202 lea L_asm_call_jit_compiler(%rip),mptr
203 mov sp,itmp3 /* calculate the old stack pointer */
206 lea (6*8-256)(itmp3),mptr /* We subtract 256 to force the next */
207 /* move instruction to have a 32-bit */
210 mov (0*8+256)(mptr),itmp3 /* method call as in Java */
211 call *itmp3 /* call JIT compiler */
213 add bp,sp /* remove argument stack frame if any */
215 L_asm_vm_call_method_return:
216 mov 0*8(sp),%rbx /* restore callee saved registers */
222 add $(7*8),sp /* free stack space */
225 asm_vm_call_method_exception_handler:
226 mov xptr,a0 /* pass exception pointer */
227 call builtin_throw_exception@PLT
228 jmp L_asm_vm_call_method_return
240 mov offvmargdata(itmp2),a0
243 mov offvmargdata(itmp2),a1
246 mov offvmargdata(itmp2),a2
249 mov offvmargdata(itmp2),a3
252 mov offvmargdata(itmp2),a4
255 mov offvmargdata(itmp2),a5
270 movq offvmargdata(itmp2),fa0
273 movq offvmargdata(itmp2),fa1
276 movq offvmargdata(itmp2),fa2
279 movq offvmargdata(itmp2),fa3
282 movq offvmargdata(itmp2),fa4
285 movq offvmargdata(itmp2),fa5
288 movq offvmargdata(itmp2),fa6
291 movq offvmargdata(itmp2),fa7
295 /****************** function asm_call_jit_compiler *****************************
297 * invokes the compiler for untranslated JavaVM methods. *
299 * Register R0 contains a pointer to the method info structure (prepared *
300 * by createcompilerstub). Using the return address in R26 and the *
301 * offset in the LDA instruction or using the value in methodptr R28 the *
302 * patching address for storing the method address can be computed: *
304 * method address was either loaded using *
306 * i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
307 * i386_call_reg(REG_ITMP2) *
311 * i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
312 * i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
313 * i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
314 * sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
315 * i386_call_reg(REG_ITMP1) *
317 * in the static case the method pointer can be computed using the *
318 * return address and the lda function following the jmp instruction *
320 *******************************************************************************/
322 asm_call_jit_compiler:
323 L_asm_call_jit_compiler: /* required for PIC code */
324 sub $(ARG_CNT+1)*8,sp /* +1: keep stack 16-byte aligned */
326 SAVE_ARGUMENT_REGISTERS(0)
328 mov itmp1,a0 /* pass methodinfo pointer */
329 mov mptr,a1 /* pass method pointer */
330 mov sp,a2 /* pass java sp */
331 add $(1+ARG_CNT+1)*8,a2
332 mov (ARG_CNT+1)*8(sp),a3 /* pass ra to java function */
333 call jit_asm_compile@PLT
335 RESTORE_ARGUMENT_REGISTERS(0)
337 add $(ARG_CNT+1)*8,sp /* remove stack frame */
339 test v0,v0 /* check for exception */
340 je L_asm_call_jit_compiler_exception
342 jmp *v0 /* ...and now call the new method */
344 L_asm_call_jit_compiler_exception:
345 call exceptions_get_and_clear_exception@PLT
346 pop xpc /* delete return address */
347 sub $3,xpc /* faulting address is ra - 3 */
348 jmp L_asm_handle_exception
351 /* asm_handle_exception ********************************************************
353 * This function handles an exception. It does not use the usual calling *
354 * conventions. The exception pointer is passed in REG_ITMP1 and the *
355 * pc from the exception raising position is passed in REG_ITMP2. It searches *
356 * the local exception table for a handler. If no one is found, it unwinds *
357 * stacks and continues searching the callers. *
359 *******************************************************************************/
361 asm_handle_nat_exception:
362 add $8,sp /* clear return address of native stub*/
364 asm_handle_exception:
365 L_asm_handle_exception: /* required for PIC code */
366 sub $((ARG_CNT+TMP_CNT)*8),sp /* create maybe-leaf stackframe */
368 SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
369 SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
371 mov $((ARG_CNT+TMP_CNT)*8),a3 /* prepare a3 for handle_exception */
372 mov $1,t0 /* set maybe-leaf flag */
374 L_asm_handle_exception_stack_loop:
376 mov xptr,0*8(sp) /* save exception pointer */
377 mov xpc,1*8(sp) /* save exception pc */
378 add sp,a3 /* calculate Java sp into a3... */
380 mov a3,3*8(sp) /* ...and save it */
381 mov t0,4*8(sp) /* save maybe-leaf flag */
383 mov xpc,a0 /* exception pc */
384 call codegen_get_pv_from_pc@PLT
385 mov v0,2*8(sp) /* save data segment pointer */
387 mov 0*8(sp),a0 /* pass exception pointer */
388 mov 1*8(sp),a1 /* pass exception pc */
389 mov v0,a2 /* pass data segment pointer */
390 mov 3*8(sp),a3 /* pass Java stack pointer */
391 call exceptions_handle_exception@PLT
394 jz L_asm_handle_exception_not_catched
396 mov v0,xpc /* move handlerpc into xpc */
397 mov 0*8(sp),xptr /* restore exception pointer */
398 mov 4*8(sp),t0 /* get maybe-leaf flag */
399 add $(6*8),sp /* free stack frame */
401 test t0,t0 /* test for maybe-leaf flag */
402 jz L_asm_handle_exception_no_leaf
404 RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
405 RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
407 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
409 L_asm_handle_exception_no_leaf:
410 jmp *xpc /* jump to the handler */
412 L_asm_handle_exception_not_catched:
413 mov 0*8(sp),xptr /* restore exception pointer */
414 mov 2*8(sp),itmp3 /* restore data segment pointer */
415 mov 4*8(sp),t0 /* get maybe-leaf flag */
419 jz L_asm_handle_exception_no_leaf_stack
421 add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */
422 xor t0,t0 /* clear the isleaf flags */
424 L_asm_handle_exception_no_leaf_stack:
425 mov FrameSize(itmp3),itmp2l /* get frame size */
426 add sp,itmp2 /* pointer to save area */
428 mov IntSave(itmp3),a0l /* a0l = saved int register count */
451 shl $3,a0l /* multiply by 8 bytes */
456 mov FltSave(itmp3),a0l /* a0l = saved flt register count */
469 movq -5*8(itmp2),%xmm11
471 movq -4*8(itmp2),%xmm12
473 movq -3*8(itmp2),%xmm13
475 movq -2*8(itmp2),%xmm14
477 movq -1*8(itmp2),%xmm15
481 mov FrameSize(itmp3),itmp2l /* get frame size */
482 add itmp2,sp /* unwind stack */
484 /* exception pointer is still set */
485 pop xpc /* the new xpc is return address */
486 sub $3,xpc /* subtract 3 bytes for call */
488 xor a3,a3 /* prepare a3 for handle_exception */
490 jmp L_asm_handle_exception_stack_loop
493 /* asm_abstractmethoderror *****************************************************
495 Creates and throws an AbstractMethodError.
497 *******************************************************************************/
499 asm_abstractmethoderror:
500 mov sp,a0 /* pass java sp */
502 mov 0*8(sp),a1 /* pass exception address */
504 call exceptions_asm_new_abstractmethoderror@PLT
505 /* exception pointer is return value */
506 pop xpc /* get exception address */
507 sub $3,xpc /* exception address is ra - 3 */
508 jmp L_asm_handle_exception
511 /* asm_patcher_wrapper *********************************************************
517 32 pointer to virtual java_objectheader
518 24 machine code (which is patched back later)
519 16 unresolved class/method/field reference
520 8 data segment displacement from load instructions
521 0 pointer to patcher function
524 *******************************************************************************/
527 push bp /* save base pointer */
528 mov sp,bp /* move actual sp to bp */
529 sub $(3+ARG_CNT+TMP_CNT)*8,sp
530 and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
531 /* leaf functions) */
533 SAVE_ARGUMENT_REGISTERS(3)
534 SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
536 mov itmp1,0*8(sp) /* save itmp1 and itmp2 */
537 mov itmp2,1*8(sp) /* can be used by some instructions */
539 mov bp,a0 /* pass SP of patcher stub */
541 mov $0,a1 /* pass PV (if NULL, use findmethod) */
542 mov $0,a2 /* pass RA (it's on the stack) */
543 call patcher_wrapper@PLT
544 mov v0,2*8(sp) /* save return value */
546 RESTORE_ARGUMENT_REGISTERS(3)
547 RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
549 mov 0*8(sp),itmp1 /* restore itmp1 and itmp2 */
550 mov 1*8(sp),itmp2 /* can be used by some instructions */
551 mov 2*8(sp),itmp3 /* restore return value */
553 mov bp,sp /* restore original sp */
554 pop bp /* restore bp */
555 add $(5*8),sp /* remove patcher stackframe, keep RA */
557 test itmp3,itmp3 /* exception thrown? */
558 jne L_asm_patcher_wrapper_exception
559 ret /* call new patched code */
561 L_asm_patcher_wrapper_exception:
562 mov itmp3,xptr /* get exception */
563 pop xpc /* get and remove return address */
564 jmp L_asm_handle_exception
566 #if defined(ENABLE_REPLACEMENT)
568 /* asm_replacement_out *********************************************************
570 This code is jumped to from the replacement-out stubs that are executed
571 when a thread reaches an activated replacement point.
573 The purpose of asm_replacement_out is to read out the parts of the
574 execution state that cannot be accessed from C code, store this state,
575 and then call the C function replace_me.
578 8 start of stack inside method to replace
579 0 rplpoint * info on the replacement point that was reached
581 *******************************************************************************/
583 /* some room to accomodate changes of the stack frame size during replacement */
584 /* XXX we should find a cleaner solution here */
585 #define REPLACEMENT_ROOM 512
588 /* create stack frame */
589 sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
591 /* save registers in execution state */
592 mov %rax,(RAX*8+offes_intregs)(sp)
593 mov %rbx,(RBX*8+offes_intregs)(sp)
594 mov %rcx,(RCX*8+offes_intregs)(sp)
595 mov %rdx,(RDX*8+offes_intregs)(sp)
596 mov %rsi,(RSI*8+offes_intregs)(sp)
597 mov %rdi,(RDI*8+offes_intregs)(sp)
598 mov %rbp,(RBP*8+offes_intregs)(sp)
599 movq $0 ,(RSP*8+offes_intregs)(sp) /* not used */
600 mov %r8 ,(R8 *8+offes_intregs)(sp)
601 mov %r9 ,(R9 *8+offes_intregs)(sp)
602 mov %r10,(R10*8+offes_intregs)(sp)
603 mov %r11,(R11*8+offes_intregs)(sp)
604 mov %r12,(R12*8+offes_intregs)(sp)
605 mov %r13,(R13*8+offes_intregs)(sp)
606 mov %r14,(R14*8+offes_intregs)(sp)
607 mov %r15,(R15*8+offes_intregs)(sp)
609 movq %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
610 movq %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
611 movq %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
612 movq %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
613 movq %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
614 movq %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
615 movq %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
616 movq %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
617 movq %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
618 movq %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
619 movq %xmm10,(XMM10*8+offes_fltregs)(sp)
620 movq %xmm11,(XMM11*8+offes_fltregs)(sp)
621 movq %xmm12,(XMM12*8+offes_fltregs)(sp)
622 movq %xmm13,(XMM13*8+offes_fltregs)(sp)
623 movq %xmm14,(XMM14*8+offes_fltregs)(sp)
624 movq %xmm15,(XMM15*8+offes_fltregs)(sp)
626 /* calculate sp of method */
628 add $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
629 mov itmp1,(offes_sp)(sp)
631 /* pv must be looked up via AVL tree */
632 movq $0,(offes_pv)(sp)
634 /* call replace_me */
635 mov -8(itmp1),a0 /* rplpoint * */
636 mov sp,a1 /* arg1: execution state */
637 call replace_me@PLT /* call C function replace_me */
638 call abort@PLT /* NEVER REACHED */
640 /* asm_replacement_in **********************************************************
642 This code writes the given execution state and jumps to the replacement
645 This function never returns!
648 void asm_replacement_in(executionstate *es, replace_safestack_t *st);
650 *******************************************************************************/
654 mov a1,s1 /* replace_safestack_t *st */
655 mov a0,%rbp /* executionstate *es == safe stack */
657 /* switch to the safe stack */
660 /* call replace_build_execution_state(st) */
662 call replace_build_execution_state@PLT
665 mov (offes_sp)(%rbp),sp
667 /* push address of new code */
668 pushq (offes_pc)(%rbp)
670 /* allocate an executionstate_t on the stack */
671 sub $(sizeexecutionstate),sp
673 /* call replace_free_safestack(st,& of allocated executionstate_t) */
676 call replace_free_safestack@PLT
678 /* copy registers from execution state */
679 movq (XMM0 *8+offes_fltregs)(sp),%xmm0
680 movq (XMM1 *8+offes_fltregs)(sp),%xmm1
681 movq (XMM2 *8+offes_fltregs)(sp),%xmm2
682 movq (XMM3 *8+offes_fltregs)(sp),%xmm3
683 movq (XMM4 *8+offes_fltregs)(sp),%xmm4
684 movq (XMM5 *8+offes_fltregs)(sp),%xmm5
685 movq (XMM6 *8+offes_fltregs)(sp),%xmm6
686 movq (XMM7 *8+offes_fltregs)(sp),%xmm7
687 movq (XMM8 *8+offes_fltregs)(sp),%xmm8
688 movq (XMM9 *8+offes_fltregs)(sp),%xmm9
689 movq (XMM10*8+offes_fltregs)(sp),%xmm10
690 movq (XMM11*8+offes_fltregs)(sp),%xmm11
691 movq (XMM12*8+offes_fltregs)(sp),%xmm12
692 movq (XMM13*8+offes_fltregs)(sp),%xmm13
693 movq (XMM14*8+offes_fltregs)(sp),%xmm14
694 movq (XMM15*8+offes_fltregs)(sp),%xmm15
696 mov (RAX*8+offes_intregs)(sp),%rax
697 mov (RBX*8+offes_intregs)(sp),%rbx
698 mov (RCX*8+offes_intregs)(sp),%rcx
699 mov (RDX*8+offes_intregs)(sp),%rdx
700 mov (RSI*8+offes_intregs)(sp),%rsi
701 mov (RDI*8+offes_intregs)(sp),%rdi
702 mov (RBP*8+offes_intregs)(sp),%rbp
703 mov (R8 *8+offes_intregs)(sp),%r8
704 mov (R9 *8+offes_intregs)(sp),%r9
705 mov (R10*8+offes_intregs)(sp),%r10
706 mov (R11*8+offes_intregs)(sp),%r11
707 mov (R12*8+offes_intregs)(sp),%r12
708 mov (R13*8+offes_intregs)(sp),%r13
709 mov (R14*8+offes_intregs)(sp),%r14
710 mov (R15*8+offes_intregs)(sp),%r15
712 /* pop the execution state off the stack */
713 add $(sizeexecutionstate),sp
715 /* jump to new code */
718 #endif /* defined(ENABLE_REPLACEMENT) */
721 /* asm_builtin_x2x *************************************************************
723 * Wrapper functions for float to int corner cases *
725 *******************************************************************************/
730 SAVE_ARGUMENT_REGISTERS(0)
735 RESTORE_ARGUMENT_REGISTERS(0)
744 SAVE_ARGUMENT_REGISTERS(0)
749 RESTORE_ARGUMENT_REGISTERS(0)
758 SAVE_ARGUMENT_REGISTERS(0)
763 RESTORE_ARGUMENT_REGISTERS(0)
772 SAVE_ARGUMENT_REGISTERS(0)
777 RESTORE_ARGUMENT_REGISTERS(0)
783 /* asm_compare_and_swap ********************************************************
785 Does an atomic compare and swap. Required for the lock
788 *******************************************************************************/
790 asm_compare_and_swap:
791 mov a1,v0 /* v0 is %rax */
796 /* asm_memory_barrier **********************************************************
798 A memory barrier for the Java Memory Model.
800 *******************************************************************************/
807 asm_getclassvalues_atomic:
810 movl offbaseval(a0),itmp1l
811 movl offdiffval(a0),itmp2l
812 movl offbaseval(a1),itmp3l
814 movl itmp1l,offcast_super_baseval(a2)
815 movl itmp2l,offcast_super_diffval(a2)
816 movl itmp3l,offcast_sub_baseval(a2)
821 asm_criticalsections:
822 #if defined(ENABLE_THREADS)
830 /* Disable exec-stacks, required for Gentoo ***********************************/
832 #if defined(__GCC__) && defined(__ELF__)
833 .section .note.GNU-stack,"",@progbits
838 * These are local overrides for various environment variables in Emacs.
839 * Please do not remove this and leave it at the end of the file, where
840 * Emacs will automagically detect them.
841 * ---------------------------------------------------------------------
844 * indent-tabs-mode: t
848 * vim:noexpandtab:sw=4:ts=4: