diff options
Diffstat (limited to 'gnu/usr.bin/cc/include/i386/i386.h')
-rw-r--r-- | gnu/usr.bin/cc/include/i386/i386.h | 530 |
1 files changed, 370 insertions, 160 deletions
diff --git a/gnu/usr.bin/cc/include/i386/i386.h b/gnu/usr.bin/cc/include/i386/i386.h index 983bfc5..a5623a7 100644 --- a/gnu/usr.bin/cc/include/i386/i386.h +++ b/gnu/usr.bin/cc/include/i386/i386.h @@ -1,4 +1,4 @@ -/* Definitions of target machine for GNU compiler for Intel 80386. +/* Definitions of target machine for GNU compiler for Intel X86 (386, 486, pentium) Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc. This file is part of GNU CC. @@ -62,77 +62,130 @@ extern int target_flags; #define TARGET_CPU_DEFAULT 0 #endif -/* Compile 80387 insns for floating point (not library calls). */ -#define TARGET_80387 (target_flags & 1) -/* Compile code for an i486. */ -#define TARGET_486 (target_flags & 2) +/* Masks for the -m switches */ +#define MASK_80387 000000000001 /* Hardware floating point */ +#define MASK_486 000000000002 /* 80486 specific */ +#define MASK_NOTUSED 000000000004 /* bit not currently used */ +#define MASK_RTD 000000000010 /* Use ret that pops args */ +#define MASK_REGPARM 000000000020 /* Pass args in eax, edx */ +#define MASK_SVR3_SHLIB 000000000040 /* Uninit locals into bss */ +#define MASK_IEEE_FP 000000000100 /* IEEE fp comparisons */ +#define MASK_FLOAT_RETURNS 000000000200 /* Return float in st(0) */ +#define MASK_NO_FANCY_MATH_387 000000000400 /* Disable sin, cos, sqrt */ + + /* Temporary codegen switches */ +#define MASK_DEBUG_ADDR 000001000000 /* Debug GO_IF_LEGITIMATE_ADDRESS */ +#define MASK_NO_WIDE_MULTIPLY 000002000000 /* Disable 32x32->64 multiplies */ +#define MASK_NO_MOVE 000004000000 /* Don't generate mem->mem */ + +/* Use the floating point instructions */ +#define TARGET_80387 (target_flags & MASK_80387) + /* Compile using ret insn that pops args. This will not work unless you use prototypes at least for all functions that can take varying numbers of args. */ -#define TARGET_RTD (target_flags & 8) +#define TARGET_RTD (target_flags & MASK_RTD) + /* Compile passing first two args in regs 0 and 1. This exists only to test compiler features that will be needed for RISC chips. It is not usable and is not intended to be usable on this cpu. */ -#define TARGET_REGPARM (target_flags & 020) +#define TARGET_REGPARM (target_flags & MASK_RTD) /* Put uninitialized locals into bss, not data. Meaningful only on svr3. */ -#define TARGET_SVR3_SHLIB (target_flags & 040) +#define TARGET_SVR3_SHLIB (target_flags & MASK_SVR3_SHLIB) /* Use IEEE floating point comparisons. These handle correctly the cases where the result of a comparison is unordered. Normally SIGFPE is generated in such cases, in which case this isn't needed. */ -#define TARGET_IEEE_FP (target_flags & 0100) +#define TARGET_IEEE_FP (target_flags & MASK_IEEE_FP) /* Functions that return a floating point value may return that value in the 387 FPU or in 386 integer registers. If set, this flag causes the 387 to be used, which is compatible with most calling conventions. */ -#define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & 0200) +#define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & MASK_FLOAT_RETURNS) /* Disable generation of FP sin, cos and sqrt operations for 387. This is because FreeBSD lacks these in the math-emulator-code */ -#define TARGET_NO_FANCY_MATH_387 (target_flags & 0400) - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - -#define TARGET_SWITCHES \ - { { "80387", 1}, \ - { "no-80387", -1}, \ - { "soft-float", -1}, \ - { "no-soft-float", 1}, \ - { "486", 2}, \ - { "no-486", -2}, \ - { "386", -2}, \ - { "rtd", 8}, \ - { "no-rtd", -8}, \ - { "regparm", 020}, \ - { "no-regparm", -020}, \ - { "svr3-shlib", 040}, \ - { "no-svr3-shlib", -040}, \ - { "ieee-fp", 0100}, \ - { "no-ieee-fp", -0100}, \ - { "fp-ret-in-387", 0200}, \ - { "no-fp-ret-in-387", -0200}, \ - { "no-fancy-math-387", 0400}, \ - { "fancy-math-387", -0400}, \ - SUBTARGET_SWITCHES \ - { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} - -/* This is meant to be redefined in the host dependent files */ +#define TARGET_NO_FANCY_MATH_387 (target_flags & MASK_NO_FANCY_MATH_387) + +/* Temporary switches for tuning code generation */ + +/* Disable 32x32->64 bit multiplies that are used for long long multiplies + and division by constants, but sometimes cause reload problems. */ +#define TARGET_NO_WIDE_MULTIPLY (target_flags & MASK_NO_WIDE_MULTIPLY) +#define TARGET_WIDE_MULTIPLY (!TARGET_NO_WIDE_MULTIPLY) + +/* Debug GO_IF_LEGITIMATE_ADDRESS */ +#define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR) + +/* Hack macros for tuning code generation */ +#define TARGET_MOVE ((target_flags & MASK_NO_MOVE) == 0) /* Don't generate memory->memory */ + +/* Specific hardware switches */ +#define TARGET_486 (target_flags & MASK_486) /* 80486DX, 80486SX, 80486DX[24] */ +#define TARGET_386 (!TARGET_486) /* 80386 */ + +#define TARGET_SWITCHES \ +{ { "80387", MASK_80387 }, \ + { "no-80387", -MASK_80387 }, \ + { "hard-float", MASK_80387 }, \ + { "soft-float", -MASK_80387 }, \ + { "no-soft-float", MASK_80387 }, \ + { "386", -MASK_486 }, \ + { "no-386", MASK_486 }, \ + { "486", MASK_486 }, \ + { "no-486", -MASK_486 }, \ + { "rtd", MASK_RTD }, \ + { "no-rtd", -MASK_RTD }, \ + { "regparm", MASK_REGPARM }, \ + { "no-regparm", -MASK_REGPARM }, \ + { "svr3-shlib", MASK_SVR3_SHLIB }, \ + { "no-svr3-shlib", -MASK_SVR3_SHLIB }, \ + { "ieee-fp", MASK_IEEE_FP }, \ + { "no-ieee-fp", -MASK_IEEE_FP }, \ + { "fp-ret-in-387", MASK_FLOAT_RETURNS }, \ + { "no-fp-ret-in-387", -MASK_FLOAT_RETURNS }, \ + { "no-fancy-math-387", MASK_NO_FANCY_MATH_387 }, \ + { "fancy-math-387", -MASK_NO_FANCY_MATH_387 }, \ + { "no-wide-multiply", MASK_NO_WIDE_MULTIPLY }, \ + { "wide-multiply", -MASK_NO_WIDE_MULTIPLY }, \ + { "debug-addr", MASK_DEBUG_ADDR }, \ + { "no-debug-addr", -MASK_DEBUG_ADDR }, \ + { "move", -MASK_NO_MOVE }, \ + { "no-move", MASK_NO_MOVE }, \ + SUBTARGET_SWITCHES \ + { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} + +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an + initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + fixed part of the option name, and the address of a variable. The + variable, type `char *', is set to the variable part of the given + option if the fixed part matches. The actual option name is made + by appending `-m' to the specified name. */ +#define TARGET_OPTIONS \ +{ { "reg-alloc=", &i386_reg_alloc_order }, \ + SUBTARGET_OPTIONS } + +/* Sometimes certain combinations of command options do not make + sense on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + Don't use this macro to turn on various extra optimizations for + `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ + +#define OVERRIDE_OPTIONS override_options () + +/* These are meant to be redefined in the host dependent files */ #define SUBTARGET_SWITCHES +#define SUBTARGET_OPTIONS -#define OVERRIDE_OPTIONS \ -{ \ - SUBTARGET_OVERRIDE_OPTIONS \ -} - -/* This is meant to be redefined in the host dependent files */ -#define SUBTARGET_OVERRIDE_OPTIONS /* target machine storage layout */ @@ -263,11 +316,39 @@ extern int target_flags; listed once, even those in FIXED_REGISTERS. List frame pointer late and fixed registers last. Note that, in general, we prefer registers listed in CALL_USED_REGISTERS, keeping the others - available for storage of persistent values. */ + available for storage of persistent values. + + Three different versions of REG_ALLOC_ORDER have been tried: + + If the order is edx, ecx, eax, ... it produces a slightly faster compiler, + but slower code on simple functions returning values in eax. + + If the order is eax, ecx, edx, ... it causes reload to abort when compiling + perl 4.036 due to not being able to create a DImode register (to hold a 2 + word union). + + If the order is eax, edx, ecx, ... it produces better code for simple + functions, and a slightly slower compiler. Users complained about the code + generated by allocating edx first, so restore the 'natural' order of things. */ #define REG_ALLOC_ORDER \ -/*ax,cx,dx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \ -{ 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } +/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \ +{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } + +/* A C statement (sans semicolon) to choose the order in which to + allocate hard registers for pseudo-registers local to a basic + block. + + Store the desired register order in the array `reg_alloc_order'. + Element 0 should be the register to allocate first; element 1, the + next register; and so on. + + The macro body should not assume anything about the contents of + `reg_alloc_order' before execution of the macro. + + On most machines, it is not necessary to define this macro. */ + +#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc () /* Macro to conditionally modify fixed_regs/call_used_regs. */ #define CONDITIONAL_REGISTER_USAGE \ @@ -381,6 +462,27 @@ extern int target_flags; /* Place in which caller passes the structure value address. 0 means push the value on the stack like an argument. */ #define STRUCT_VALUE 0 + +/* A C expression which can inhibit the returning of certain function + values in registers, based on the type of value. A nonzero value + says to return the function value in memory, just as large + structures are always returned. Here TYPE will be a C expression + of type `tree', representing the data type of the value. + + Note that values of mode `BLKmode' must be explicitly handled by + this macro. Also, the option `-fpcc-struct-return' takes effect + regardless of this macro. On most systems, it is possible to + leave the macro undefined; this causes a default definition to be + used, whose value is the constant 1 for `BLKmode' values, and 0 + otherwise. + + Do not use this macro to indicate that structures and unions + should always be returned in memory. You should instead use + `DEFAULT_PCC_STRUCT_RETURN' to indicate this. */ + +#define RETURN_IN_MEMORY(TYPE) \ + ((TYPE_MODE (TYPE) == BLKmode) || int_size_in_bytes (TYPE) > 12) + /* Define the classes of registers for register constraints in the machine description. Also define ranges of constants. @@ -448,7 +550,7 @@ enum reg_class 0x3, /* AD_REGS */ \ 0xf, /* Q_REGS */ \ 0x10, 0x20, /* SIREG, DIREG */ \ - 0x1007f, /* INDEX_REGS */ \ + 0x07f, /* INDEX_REGS */ \ 0x100ff, /* GENERAL_REGS */ \ 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \ 0xff00, /* FLOAT_REGS */ \ @@ -459,7 +561,6 @@ enum reg_class reg number REGNO. This could be a conditional expression or could index an array. */ -extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; #define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO]) /* When defined, the compiler allows registers explicitly used in the @@ -591,6 +692,32 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; #define CLASS_MAX_NREGS(CLASS, MODE) \ (FLOAT_CLASS_P (CLASS) ? 1 : \ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + +/* A C expression whose value is nonzero if pseudos that have been + assigned to registers of class CLASS would likely be spilled + because registers of CLASS are needed for spill registers. + + The default value of this macro returns 1 if CLASS has exactly one + register and zero otherwise. On most machines, this default + should be used. Only define this macro to some other expression + if pseudo allocated by `local-alloc.c' end up in memory because + their hard registers were needed for spill regisers. If this + macro returns nonzero for those classes, those pseudos will only + be allocated by `global.c', which knows how to reallocate the + pseudo to another register. If there would not be another + register available for reallocation, you should not change the + definition of this macro since the only effect of such a + definition would be to slow down register allocation. */ + +#define CLASS_LIKELY_SPILLED_P(CLASS) \ + (((CLASS) == AREG) \ + || ((CLASS) == DREG) \ + || ((CLASS) == CREG) \ + || ((CLASS) == BREG) \ + || ((CLASS) == AD_REGS) \ + || ((CLASS) == SIREG) \ + || ((CLASS) == DIREG)) + /* Stack layout; function entry, exit and calling. */ @@ -762,6 +889,102 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; } \ } +/* A C statement or compound statement to output to FILE some + assembler code to initialize basic-block profiling for the current + object module. This code should call the subroutine + `__bb_init_func' once per object module, passing it as its sole + argument the address of a block allocated in the object module. + + The name of the block is a local symbol made with this statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you + can take a short cut in the definition of this macro and use the + name that you know will result. + + The first word of this block is a flag which will be nonzero if the + object module has already been initialized. So test this word + first, and do not call `__bb_init_func' if the flag is nonzero. */ + +#undef FUNCTION_BLOCK_PROFILER +#define FUNCTION_BLOCK_PROFILER(STREAM, LABELNO) \ +do \ + { \ + static int num_func = 0; \ + rtx xops[8]; \ + char block_table[80], false_label[80]; \ + \ + ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \ + ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \ + \ + xops[0] = const0_rtx; \ + xops[1] = gen_rtx (SYMBOL_REF, VOIDmode, block_table); \ + xops[2] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, false_label)); \ + xops[3] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, "__bb_init_func")); \ + xops[4] = gen_rtx (MEM, Pmode, xops[1]); \ + xops[5] = stack_pointer_rtx; \ + xops[6] = GEN_INT (4); \ + xops[7] = gen_rtx (REG, Pmode, 0); /* eax */ \ + \ + CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \ + CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \ + \ + output_asm_insn (AS2(cmp%L4,%0,%4), xops); \ + output_asm_insn (AS1(jne,%2), xops); \ + \ + if (!flag_pic) \ + output_asm_insn (AS1(push%L1,%1), xops); \ + else \ + { \ + output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ + output_asm_insn (AS1 (push%L7,%7), xops); \ + } \ + \ + output_asm_insn (AS1(call,%P3), xops); \ + output_asm_insn (AS2(add%L0,%6,%5), xops); \ + ASM_OUTPUT_INTERNAL_LABEL (STREAM, "LPBZ", num_func); \ + num_func++; \ + } \ +while (0) + + +/* A C statement or compound statement to increment the count + associated with the basic block number BLOCKNO. Basic blocks are + numbered separately from zero within each compilation. The count + associated with block number BLOCKNO is at index BLOCKNO in a + vector of words; the name of this array is a local symbol made + with this statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you + can take a short cut in the definition of this macro and use the + name that you know will result. */ + +#define BLOCK_PROFILER(STREAM, BLOCKNO) \ +do \ + { \ + rtx xops[1], cnt_rtx; \ + char counts[80]; \ + \ + ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \ + cnt_rtx = gen_rtx (SYMBOL_REF, VOIDmode, counts); \ + SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \ + \ + if (BLOCKNO) \ + cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \ + \ + if (flag_pic) \ + cnt_rtx = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, cnt_rtx); \ + \ + xops[0] = gen_rtx (MEM, SImode, cnt_rtx); \ + output_asm_insn (AS1(inc%L0,%0), xops); \ + } \ +while (0) + /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in functions that have frame pointers. @@ -925,36 +1148,35 @@ do { \ After reload, it makes no difference, since pseudo regs have been eliminated by then. */ -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index or if - it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) \ - (REGNO (X) < STACK_POINTER_REGNUM \ +/* Non strict versions, pseudos are ok */ +#define REG_OK_FOR_INDEX_NONSTRICT_P(X) \ + (REGNO (X) < STACK_POINTER_REGNUM \ || REGNO (X) >= FIRST_PSEUDO_REGISTER) -/* Nonzero if X is a hard reg that can be used as a base reg - of if it is a pseudo reg. */ - /* ?wfs */ - -#define REG_OK_FOR_BASE_P(X) \ - (REGNO (X) <= STACK_POINTER_REGNUM \ - || REGNO (X) == ARG_POINTER_REGNUM \ - || REGNO(X) >= FIRST_PSEUDO_REGISTER) +#define REG_OK_FOR_BASE_NONSTRICT_P(X) \ + (REGNO (X) <= STACK_POINTER_REGNUM \ + || REGNO (X) == ARG_POINTER_REGNUM \ + || REGNO (X) >= FIRST_PSEUDO_REGISTER) -#define REG_OK_FOR_STRREG_P(X) \ +#define REG_OK_FOR_STRREG_NONSTRICT_P(X) \ (REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER) -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) -#define REG_OK_FOR_STRREG_P(X) \ +/* Strict versions, hard registers only */ +#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) +#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#define REG_OK_FOR_STRREG_STRICT_P(X) \ (REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X))) +#ifndef REG_OK_STRICT +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X) +#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X) +#define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_NONSTRICT_P(X) + +#else +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X) +#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X) +#define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_STRICT_P(X) #endif /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression @@ -980,62 +1202,22 @@ do { \ #define LEGITIMATE_CONSTANT_P(X) 1 -#define GO_IF_INDEXABLE_BASE(X, ADDR) \ - if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR - -#define LEGITIMATE_INDEX_REG_P(X) \ - (GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) - -/* Return 1 if X is an index or an index times a scale. */ - -#define LEGITIMATE_INDEX_P(X) \ - (LEGITIMATE_INDEX_REG_P (X) \ - || (GET_CODE (X) == MULT \ - && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && (INTVAL (XEXP (X, 1)) == 2 \ - || INTVAL (XEXP (X, 1)) == 4 \ - || INTVAL (XEXP (X, 1)) == 8))) - -/* Go to ADDR if X is an index term, a base reg, or a sum of those. */ - -#define GO_IF_INDEXING(X, ADDR) \ -{ if (LEGITIMATE_INDEX_P (X)) goto ADDR; \ - GO_IF_INDEXABLE_BASE (X, ADDR); \ - if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \ - { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \ - if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \ - { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } } - -/* We used to allow this, but it isn't ever used. - || ((GET_CODE (X) == POST_DEC || GET_CODE (X) == POST_INC) \ - && REG_P (XEXP (X, 0)) \ - && REG_OK_FOR_STRREG_P (XEXP (X, 0))) \ -*/ +#ifdef REG_OK_STRICT +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ \ + if (legitimate_address_p (MODE, X, 1)) \ + goto ADDR; \ +} -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +#else +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ { \ - if (CONSTANT_ADDRESS_P (X) \ - && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \ + if (legitimate_address_p (MODE, X, 0)) \ goto ADDR; \ - GO_IF_INDEXING (X, ADDR); \ - if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - { \ - rtx x0 = XEXP (X, 0); \ - if (! flag_pic || ! SYMBOLIC_CONST (XEXP (X, 1))) \ - { GO_IF_INDEXING (x0, ADDR); } \ - else if (x0 == pic_offset_table_rtx) \ - goto ADDR; \ - else if (GET_CODE (x0) == PLUS) \ - { \ - if (XEXP (x0, 0) == pic_offset_table_rtx) \ - { GO_IF_INDEXABLE_BASE (XEXP (x0, 1), ADDR); } \ - if (XEXP (x0, 1) == pic_offset_table_rtx) \ - { GO_IF_INDEXABLE_BASE (XEXP (x0, 0), ADDR); } \ - } \ - } \ } +#endif + /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. This macro is used in only one place: `memory_address' in explow.c. @@ -1057,38 +1239,13 @@ do { \ When -fpic is used, special handling is needed for symbolic references. See comments by legitimize_pic_address in i386.c for details. */ -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ extern rtx legitimize_pic_address (); \ - int ch = (X) != (OLDX); \ - if (flag_pic && SYMBOLIC_CONST (X)) \ - { \ - (X) = legitimize_pic_address (X, 0); \ - if (memory_address_p (MODE, X)) \ - goto WIN; \ - } \ - if (GET_CODE (X) == PLUS) \ - { if (GET_CODE (XEXP (X, 0)) == MULT) \ - ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \ - if (GET_CODE (XEXP (X, 1)) == MULT) \ - ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \ - if (ch && GET_CODE (XEXP (X, 1)) == REG \ - && GET_CODE (XEXP (X, 0)) == REG) \ - goto WIN; \ - if (flag_pic && SYMBOLIC_CONST (XEXP (X, 1))) \ - ch = 1, (X) = legitimize_pic_address (X, 0); \ - if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \ - if (GET_CODE (XEXP (X, 0)) == REG) \ - { register rtx temp = gen_reg_rtx (Pmode); \ - register rtx val = force_operand (XEXP (X, 1), temp); \ - if (val != temp) emit_move_insn (temp, val); \ - XEXP (X, 1) = temp; \ - goto WIN; } \ - else if (GET_CODE (XEXP (X, 1)) == REG) \ - { register rtx temp = gen_reg_rtx (Pmode); \ - register rtx val = force_operand (XEXP (X, 0), temp); \ - if (val != temp) emit_move_insn (temp, val); \ - XEXP (X, 0) = temp; \ - goto WIN; }}} +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ +{ \ + rtx orig_x = (X); \ + (X) = legitimize_address (X, OLDX, MODE); \ + if (memory_address_p (MODE, X)) \ + goto WIN; \ +} /* Nonzero if the constant value X is a legitimate general operand when generating PIC code. It is given that flag_pic is on and @@ -1312,7 +1469,6 @@ while (0) stored from the compare operation. Note that we can't use "rtx" here since it hasn't been defined! */ -extern struct rtx_def *i386_compare_op0, *i386_compare_op1; extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); /* Tell final.c how to eliminate redundant test instructions. */ @@ -1658,6 +1814,60 @@ extern char *qi_high_reg_name[]; #define RET return "" #define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx)) +/* Functions in i386.c */ +extern void override_options (); +extern void order_regs_for_local_alloc (); +extern void output_op_from_reg (); +extern void output_to_reg (); +extern char *singlemove_string (); +extern char *output_move_double (); +extern char *output_move_memory (); +extern char *output_move_pushmem (); +extern int standard_80387_constant_p (); +extern char *output_move_const_single (); +extern int symbolic_operand (); +extern int call_insn_operand (); +extern int expander_call_insn_operand (); +extern int symbolic_reference_mentioned_p (); +extern void emit_pic_move (); +extern void function_prologue (); +extern int simple_386_epilogue (); +extern void function_epilogue (); +extern int legitimate_address_p (); +extern struct rtx_def *legitimize_pic_address (); +extern struct rtx_def *legitimize_address (); +extern void print_operand (); +extern void print_operand_address (); +extern void notice_update_cc (); +extern void split_di (); +extern int binary_387_op (); +extern int shift_op (); +extern int VOIDmode_compare_op (); +extern char *output_387_binary_op (); +extern char *output_fix_trunc (); +extern char *output_float_compare (); +extern char *output_fp_cc0_set (); +extern void save_386_machine_status (); +extern void restore_386_machine_status (); +extern void clear_386_stack_locals (); +extern struct rtx_def *assign_386_stack_local (); + +/* Variables in i386.c */ +extern char *i386_reg_alloc_order; /* register allocation order */ +extern char *hi_reg_name[]; /* names for 16 bit regs */ +extern char *qi_reg_name[]; /* names for 8 bit regs (low) */ +extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */ +extern enum reg_class regclass_map[]; /* smalled class containing REGNO */ +extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */ +extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */ + +/* External variables used */ +extern int optimize; /* optimization level */ +extern int obey_regdecls; /* TRUE if stupid register allocation */ + +/* External functions used */ +extern struct rtx_def *force_operand (); + /* Local variables: version-control: t |