Commit 3b3c6a3f by Michael Meissner

Add -mno-wide-multiply, -mno-move, make addresses more compatible with other parts of compiler.

From-SVN: r7989
parent e8e1942a
/* Subroutines for insn-output.c for Intel 80386.
Copyright (C) 1988, 1992 Free Software Foundation, Inc.
/* Subroutines for insn-output.c for Intel X86.
Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc.
This file is part of GNU CC.
......@@ -243,16 +243,21 @@ asm_add (n, x)
rtx x;
{
rtx xops[2];
xops[1] = x;
if (n < 0)
xops[0] = x;
if (n == -1)
output_asm_insn (AS1 (dec%L0,%0), xops);
else if (n == 1)
output_asm_insn (AS1 (inc%L0,%0), xops);
else if (n < 0)
{
xops[0] = GEN_INT (-n);
output_asm_insn (AS2 (sub%L0,%0,%1), xops);
xops[1] = GEN_INT (-n);
output_asm_insn (AS2 (sub%L0,%1,%0), xops);
}
else if (n > 0)
{
xops[0] = GEN_INT (n);
output_asm_insn (AS2 (add%L0,%0,%1), xops);
xops[1] = GEN_INT (n);
output_asm_insn (AS2 (add%L0,%1,%0), xops);
}
}
......@@ -741,111 +746,6 @@ symbolic_reference_mentioned_p (op)
return 0;
}
/* Return a legitimate reference for ORIG (an address) using the
register REG. If REG is 0, a new pseudo is generated.
There are three types of references that must be handled:
1. Global data references must load the address from the GOT, via
the PIC reg. An insn is emitted to do this load, and the reg is
returned.
2. Static data references must compute the address as an offset
from the GOT, whose base is in the PIC reg. An insn is emitted to
compute the address into a reg, and the reg is returned. Static
data objects have SYMBOL_REF_FLAG set to differentiate them from
global data objects.
3. Constant pool addresses must be handled special. They are
considered legitimate addresses, but only if not used with regs.
When printed, the output routines know to print the reference with the
PIC reg, even though the PIC reg doesn't appear in the RTL.
GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
reg also appears in the address (except for constant pool references,
noted above).
"switch" statements also require special handling when generating
PIC code. See comments by the `casesi' insn in i386.md for details. */
rtx
legitimize_pic_address (orig, reg)
rtx orig;
rtx reg;
{
rtx addr = orig;
rtx new = orig;
if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
{
if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
reg = new = orig;
else
{
if (reg == 0)
reg = gen_reg_rtx (Pmode);
if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
else
new = gen_rtx (MEM, Pmode,
gen_rtx (PLUS, Pmode,
pic_offset_table_rtx, orig));
emit_move_insn (reg, new);
}
current_function_uses_pic_offset_table = 1;
return reg;
}
else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
{
rtx base;
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
if (GET_CODE (addr) != PLUS)
abort ();
}
if (XEXP (addr, 0) == pic_offset_table_rtx)
return orig;
if (reg == 0)
reg = gen_reg_rtx (Pmode);
base = legitimize_pic_address (XEXP (addr, 0), reg);
addr = legitimize_pic_address (XEXP (addr, 1),
base == reg ? NULL_RTX : reg);
if (GET_CODE (addr) == CONST_INT)
return plus_constant (base, INTVAL (addr));
if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
{
base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
addr = XEXP (addr, 1);
}
return gen_rtx (PLUS, Pmode, base, addr);
}
return new;
}
/* Emit insns to move operands[1] into operands[0]. */
void
emit_pic_move (operands, mode)
rtx *operands;
enum machine_mode mode;
{
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
operands[1] = (rtx) force_reg (SImode, operands[1]);
else
operands[1] = legitimize_pic_address (operands[1], temp);
}
/* This function generates the assembly code for function entry.
FILE is an stdio stream to output the code to.
SIZE is an int: how many units of temporary storage to allocate. */
......@@ -939,6 +839,7 @@ simple_386_epilogue ()
return nregs == 0 || ! frame_pointer_needed;
}
/* This function generates the assembly code for function exit.
FILE is an stdio stream to output the code to.
SIZE is an int: how many units of temporary storage to deallocate. */
......@@ -1012,7 +913,7 @@ function_epilogue (file, size)
{
/* On i486, mov & pop is faster than "leave". */
if (TARGET_486)
if (!TARGET_386)
{
xops[0] = frame_pointer_rtx;
output_asm_insn (AS2 (mov%L2,%0,%2), xops);
......@@ -1051,6 +952,523 @@ function_epilogue (file, size)
else
output_asm_insn ("ret", xops);
}
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
The MODE argument is the machine mode for the MEM expression
that wants to use this address.
On x86, legitimate addresses are:
base movl (base),reg
displacement movl disp,reg
base + displacement movl disp(base),reg
index + base movl (base,index),reg
(index + base) + displacement movl disp(base,index),reg
index*scale movl (,index,scale),reg
index*scale + disp movl disp(,index,scale),reg
index*scale + base movl (base,index,scale),reg
(index*scale + base) + disp movl disp(base,index,scale),reg
In each case, scale can be 1, 2, 4, 8. */
/* This is exactly the same as print_operand_addr, except that
it recognizes addresses instead of printing them.
It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should
convert common non-canonical forms to canonical form so that they will
be recognized. */
#define ADDR_INVALID(msg,insn) \
do { \
if (TARGET_DEBUG_ADDR) \
{ \
fprintf (stderr, msg); \
debug_rtx (insn); \
} \
} while (0)
int
legitimate_address_p (mode, addr, strict)
enum machine_mode mode;
register rtx addr;
int strict;
{
rtx base = NULL_RTX;
rtx indx = NULL_RTX;
rtx scale = NULL_RTX;
rtx disp = NULL_RTX;
if (TARGET_DEBUG_ADDR)
{
fprintf (stderr,
"\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
GET_MODE_NAME (mode), strict);
debug_rtx (addr);
}
if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
base = addr; /* base reg */
else if (GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0);
rtx op1 = XEXP (addr, 1);
enum rtx_code code0 = GET_CODE (op0);
enum rtx_code code1 = GET_CODE (op1);
if (code0 == REG || code0 == SUBREG)
{
if (code1 == REG || code1 == SUBREG)
{
indx = op0; /* index + base */
base = op1;
}
else
{
base = op0; /* base + displacement */
disp = op1;
}
}
else if (code0 == MULT)
{
indx = XEXP (op0, 0);
scale = XEXP (op0, 1);
if (code1 == REG || code1 == SUBREG)
base = op1; /* index*scale + base */
else
disp = op1; /* index*scale + disp */
}
else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
{
indx = XEXP (XEXP (op0, 0), 0); /* index*scale + base + disp */
scale = XEXP (XEXP (op0, 0), 1);
base = XEXP (op0, 1);
disp = op1;
}
else if (code0 == PLUS)
{
indx = XEXP (op0, 0); /* index + base + disp */
base = XEXP (op0, 1);
disp = op1;
}
else
{
ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
return FALSE;
}
}
else if (GET_CODE (addr) == MULT)
{
indx = XEXP (addr, 0); /* index*scale */
scale = XEXP (addr, 1);
}
else
disp = addr; /* displacement */
/* Validate base register */
if (base)
{
if (GET_CODE (base) == SUBREG)
{
if (GET_CODE (SUBREG_REG (base)) != REG || SUBREG_WORD (base) != 0)
{
ADDR_INVALID ("Base SUBREG is not of a REG.\n", base);
return FALSE;
}
base = SUBREG_REG (base);
}
if (GET_CODE (base) != REG
|| ( strict && !REG_OK_FOR_BASE_STRICT_P (base))
|| (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
{
ADDR_INVALID ("Base is not valid.\n", base);
return FALSE;
}
}
/* Validate index register */
if (indx)
{
if (GET_CODE (indx) == SUBREG)
{
if (GET_CODE (SUBREG_REG (indx)) != REG || SUBREG_WORD (indx) != 0)
{
ADDR_INVALID ("Index SUBREG is not of a REG.", indx);
return FALSE;
}
indx = SUBREG_REG (indx);
}
if (GET_CODE (indx) != REG
|| ( strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
|| (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
{
ADDR_INVALID ("Index is not valid.\n", indx);
return FALSE;
}
}
else if (scale)
abort (); /* scale w/o index illegal */
/* Validate scale factor */
if (scale)
{
HOST_WIDE_INT value;
if (GET_CODE (scale) != CONST_INT)
{
ADDR_INVALID ("Scale is not valid.\n", scale);
return FALSE;
}
value = INTVAL (scale);
if (value != 1 && value != 2 && value != 4 && value != 8)
{
ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
return FALSE;
}
}
/* Validate displacement */
if (disp)
{
if (!CONSTANT_ADDRESS_P (disp))
{
ADDR_INVALID ("Displacement is not valid.\n", disp);
return FALSE;
}
if (GET_CODE (disp) == CONST_DOUBLE)
{
ADDR_INVALID ("Displacement is a const_double.\n", disp);
return FALSE;
}
if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx
&& (indx != pic_offset_table_rtx || scale != NULL_RTX))
{
ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
return FALSE;
}
if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
&& (base != NULL_RTX || indx != NULL_RTX))
{
ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
return FALSE;
}
}
if (TARGET_DEBUG_ADDR)
fprintf (stderr, "Address is valid.\n");
/* Everything looks valid, return true */
return TRUE;
}
/* Return a legitimate reference for ORIG (an address) using the
register REG. If REG is 0, a new pseudo is generated.
There are three types of references that must be handled:
1. Global data references must load the address from the GOT, via
the PIC reg. An insn is emitted to do this load, and the reg is
returned.
2. Static data references must compute the address as an offset
from the GOT, whose base is in the PIC reg. An insn is emitted to
compute the address into a reg, and the reg is returned. Static
data objects have SYMBOL_REF_FLAG set to differentiate them from
global data objects.
3. Constant pool addresses must be handled special. They are
considered legitimate addresses, but only if not used with regs.
When printed, the output routines know to print the reference with the
PIC reg, even though the PIC reg doesn't appear in the RTL.
GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
reg also appears in the address (except for constant pool references,
noted above).
"switch" statements also require special handling when generating
PIC code. See comments by the `casesi' insn in i386.md for details. */
rtx
legitimize_pic_address (orig, reg)
rtx orig;
rtx reg;
{
rtx addr = orig;
rtx new = orig;
if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
{
if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
reg = new = orig;
else
{
if (reg == 0)
reg = gen_reg_rtx (Pmode);
if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
else
new = gen_rtx (MEM, Pmode,
gen_rtx (PLUS, Pmode,
pic_offset_table_rtx, orig));
emit_move_insn (reg, new);
}
current_function_uses_pic_offset_table = 1;
return reg;
}
else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
{
rtx base;
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
if (GET_CODE (addr) != PLUS)
abort ();
}
if (XEXP (addr, 0) == pic_offset_table_rtx)
return orig;
if (reg == 0)
reg = gen_reg_rtx (Pmode);
base = legitimize_pic_address (XEXP (addr, 0), reg);
addr = legitimize_pic_address (XEXP (addr, 1),
base == reg ? NULL_RTX : reg);
if (GET_CODE (addr) == CONST_INT)
return plus_constant (base, INTVAL (addr));
if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
{
base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
addr = XEXP (addr, 1);
}
return gen_rtx (PLUS, Pmode, base, addr);
}
return new;
}
/* Emit insns to move operands[1] into operands[0]. */
void
emit_pic_move (operands, mode)
rtx *operands;
enum machine_mode mode;
{
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
operands[1] = (rtx) force_reg (SImode, operands[1]);
else
operands[1] = legitimize_pic_address (operands[1], temp);
}
/* 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.
OLDX is the address as it was before break_out_memory_refs was called.
In some cases it is useful to look at this to decide what needs to be done.
MODE and WIN are passed so that this macro can use
GO_IF_LEGITIMATE_ADDRESS.
It is always safe for this macro to do nothing. It exists to recognize
opportunities to optimize the output.
For the 80386, we handle X+REG by loading X into a register R and
using R+REG. R will go in a general reg and indexing will be used.
However, if REG is a broken-out memory address or multiplication,
nothing needs to be done because REG can certainly go in a general reg.
When -fpic is used, special handling is needed for symbolic references.
See comments by legitimize_pic_address in i386.c for details. */
rtx
legitimize_address (x, oldx, mode)
register rtx x;
register rtx oldx;
enum machine_mode mode;
{
int changed = 0;
unsigned log;
if (TARGET_DEBUG_ADDR)
{
fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
debug_rtx (x);
}
if (flag_pic && SYMBOLIC_CONST (x))
return legitimize_pic_address (x, 0);
/* Canonicalize shifts by 0, 1, 2, 3 into multiply */
if (GET_CODE (x) == ASHIFT
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
{
changed = 1;
x = gen_rtx (MULT, Pmode,
force_reg (Pmode, XEXP (x, 0)),
GEN_INT (1 << log));
}
if (GET_CODE (x) == PLUS)
{
/* Canonicalize shifts by 0, 1, 2, 3 into multiply */
if (GET_CODE (XEXP (x, 0)) == ASHIFT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
{
changed = 1;
XEXP (x, 0) = gen_rtx (MULT, Pmode,
force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
GEN_INT (1 << log));
}
if (GET_CODE (XEXP (x, 1)) == ASHIFT
&& GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
&& (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
{
changed = 1;
XEXP (x, 1) = gen_rtx (MULT, Pmode,
force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
GEN_INT (1 << log));
}
/* Put multiply first if it isn't already */
if (GET_CODE (XEXP (x, 1)) == MULT)
{
rtx tmp = XEXP (x, 0);
XEXP (x, 0) = XEXP (x, 1);
XEXP (x, 1) = tmp;
changed = 1;
}
/* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be
created by virtual register instantiation, register elimination, and
similar optimizations. */
if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
{
changed = 1;
x = gen_rtx (PLUS, Pmode,
gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
XEXP (XEXP (x, 1), 1));
}
/* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
into (plus (plus (mult (reg) (const)) (reg)) (const)). */
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
&& CONSTANT_P (XEXP (x, 1)))
{
rtx constant, other;
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
{
constant = XEXP (x, 1);
other = XEXP (XEXP (XEXP (x, 0), 1), 1);
}
else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
{
constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
other = XEXP (x, 1);
}
else
constant = 0;
if (constant)
{
changed = 1;
x = gen_rtx (PLUS, Pmode,
gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
XEXP (XEXP (XEXP (x, 0), 1), 0)),
plus_constant (other, INTVAL (constant)));
}
}
if (changed && legitimate_address_p (mode, x, FALSE))
return x;
if (GET_CODE (XEXP (x, 0)) == MULT)
{
changed = 1;
XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
}
if (GET_CODE (XEXP (x, 1)) == MULT)
{
changed = 1;
XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
}
if (changed
&& GET_CODE (XEXP (x, 1)) == REG
&& GET_CODE (XEXP (x, 0)) == REG)
return x;
if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
{
changed = 1;
x = legitimize_pic_address (x, 0);
}
if (changed && legitimate_address_p (mode, x, FALSE))
return x;
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;
return x;
}
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;
return x;
}
}
return x;
}
/* Print an integer constant expression in assembler syntax. Addition
and subtraction are the only arithmetic that may appear in these
......@@ -1653,32 +2071,7 @@ binary_387_op (op, mode)
}
}
/* Return 1 if this is a valid conversion operation on a 387.
OP is the expression matched, and MODE is its mode. */
int
convert_387_op (op, mode)
register rtx op;
enum machine_mode mode;
{
if (mode != VOIDmode && mode != GET_MODE (op))
return 0;
switch (GET_CODE (op))
{
case FLOAT:
return GET_MODE (XEXP (op, 0)) == SImode;
case FLOAT_EXTEND:
return ((mode == DFmode && GET_MODE (XEXP (op, 0)) == SFmode)
|| (mode == XFmode && GET_MODE (XEXP (op, 0)) == DFmode)
|| (mode == XFmode && GET_MODE (XEXP (op, 0)) == SFmode));
default:
return 0;
}
}
/* Return 1 if this is a valid shift or rotate operation on a 386.
OP is the expression matched, and MODE is its mode. */
......
/* 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,66 +62,101 @@ 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}}
#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 is meant to be redefined in the host dependent files */
#define SUBTARGET_SWITCHES
......@@ -259,15 +294,30 @@ extern int target_flags;
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
/* Order in which to allocate registers. First allocate registers
for which no insn operand demands that register, next those that are
demanded by the least number of insns. List frame pointer late and fixed
egisters last. Note that, in general, we want to put nonsaved registers
late, but we put bx relatively early since it is not demanded by
any insn operand. */
/* Order in which to allocate registers. Each register must be
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.
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. */
#if 0
#define REG_ALLOC_ORDER \
/*si,di,bx,cx,dx,ax,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
{ 4, 5, 3, 2, 1, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
/*dx,cx,ax,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
{ 1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
#endif
/* Macro to conditionally modify fixed_regs/call_used_regs. */
#define CONDITIONAL_REGISTER_USAGE \
......@@ -925,36 +975,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 +1029,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 +1066,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
......@@ -1658,6 +1642,47 @@ 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 output_op_from_reg ();
extern void output_to_reg ();
extern char *singlemove_string ();
extern char *output_move_double ();
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 ();
/* 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
......
......@@ -48,13 +48,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|| (CHAR) == 'h' \
|| (CHAR) == 'z')
#define MASK_HALF_PIC 0x40000000 /* Mask for half-pic code */
#define MASK_HALF_PIC_DEBUG 0x20000000 /* Debug flag */
#define MASK_ELF 0x10000000 /* ELF not rose */
#define MASK_NO_IDENT 0x08000000 /* suppress .ident */
#define MASK_NO_UNDERSCORES 0x04000000 /* suppress leading _ */
#define MASK_LARGE_ALIGN 0x02000000 /* align to >word boundaries */
#define MASK_NO_MCOUNT 0x01000000 /* profiling uses mcount_ptr */
#define MASK_HALF_PIC 010000000000 /* Mask for half-pic code */
#define MASK_HALF_PIC_DEBUG 004000000000 /* Debug flag */
#define MASK_ELF 002000000000 /* ELF not rose */
#define MASK_NO_IDENT 001000000000 /* suppress .ident */
#define MASK_NO_UNDERSCORES 000400000000 /* suppress leading _ */
#define MASK_LARGE_ALIGN 000200000000 /* align to >word boundaries */
#define MASK_NO_MCOUNT 000100000000 /* profiling uses mcount_ptr */
#define TARGET_HALF_PIC (target_flags & MASK_HALF_PIC)
#define TARGET_DEBUG (target_flags & MASK_HALF_PIC_DEBUG)
......@@ -67,22 +67,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define TARGET_MCOUNT ((target_flags & MASK_NO_MCOUNT) == 0)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
{ "half-pic", MASK_HALF_PIC}, \
{ "no-half-pic", -MASK_HALF_PIC}, \
{ "debug-half-pic", MASK_HALF_PIC_DEBUG}, \
{ "debugb", MASK_HALF_PIC_DEBUG}, \
{ "elf", MASK_ELF}, \
{ "rose", -MASK_ELF}, \
{ "ident", -MASK_NO_IDENT}, \
{ "no-ident", MASK_NO_IDENT}, \
{ "underscores", -MASK_NO_UNDERSCORES}, \
{ "no-underscores", MASK_NO_UNDERSCORES}, \
{ "large-align", MASK_LARGE_ALIGN}, \
{ "no-large-align",-MASK_LARGE_ALIGN}, \
{ "mcount", -MASK_NO_MCOUNT}, \
{ "mcount-ptr", MASK_NO_MCOUNT}, \
{ "no-mcount", MASK_NO_MCOUNT},
#define SUBTARGET_SWITCHES \
{ "half-pic", MASK_HALF_PIC}, \
{ "no-half-pic", -MASK_HALF_PIC}, \
{ "debug-half-pic", MASK_HALF_PIC_DEBUG}, \
{ "debugb", MASK_HALF_PIC_DEBUG}, \
{ "elf", MASK_ELF}, \
{ "rose", -MASK_ELF}, \
{ "ident", -MASK_NO_IDENT}, \
{ "no-ident", MASK_NO_IDENT}, \
{ "underscores", -MASK_NO_UNDERSCORES}, \
{ "no-underscores", MASK_NO_UNDERSCORES}, \
{ "large-align", MASK_LARGE_ALIGN}, \
{ "no-large-align", -MASK_LARGE_ALIGN}, \
{ "mcount", -MASK_NO_MCOUNT}, \
{ "mcount-ptr", MASK_NO_MCOUNT}, \
{ "no-mcount", MASK_NO_MCOUNT},
/* OSF/rose uses stabs, not dwarf. */
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
......@@ -178,8 +178,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define WCHAR_TYPE "unsigned int"
#define WCHAR_TYPE_SIZE BITS_PER_WORD
/* Temporarily turn off long double being 96 bits. */
/* Define this macro if the system header files support C++ as well
as C. This macro inhibits the usual method of using system header
files in C++, which is to pretend that the file's contents are
enclosed in `extern "C" {...}'. */
#define NO_IMPLICIT_EXTERN_C
/* Turn off long double being 96 bits. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 64
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
......@@ -257,7 +264,7 @@ while (0)
expects to find the address. The name of this variable is `LP' followed by
the number LABELNO, so you would generate the name using `LP%d' in a
`fprintf'.
The details of how the address should be passed to `mcount' are determined
by your operating system environment, not by GNU CC. To figure them out,
compile a small program for profiling using the system's installed C
......@@ -530,60 +537,6 @@ while (0)
|| GET_CODE (X) == CONST_INT \
|| !HALF_PIC_ADDRESS_P (X))
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
The MODE argument is the machine mode for the MEM expression
that wants to use this address. */
#define GO_IF_LEGITIMATE_ADDRESS_ORIG(MODE, X, ADDR) \
{ \
if (CONSTANT_ADDRESS_P (X) \
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \
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); } \
} \
} \
}
#undef GO_IF_LEGITIMATE_ADDRESS
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ \
if (! HALF_PIC_P ()) \
{ \
GO_IF_LEGITIMATE_ADDRESS_ORIG(MODE, X, ADDR); \
} \
else \
{ \
if (CONSTANT_P (X) && ! HALF_PIC_ADDRESS_P (X)) \
goto ADDR; \
\
GO_IF_INDEXING (X, ADDR); \
if (GET_CODE (X) == PLUS) \
{ \
rtx x1 = XEXP (X, 1); \
\
if (CONSTANT_P (x1) && ! HALF_PIC_ADDRESS_P (x1)) \
{ \
rtx x0 = XEXP (X, 0); \
GO_IF_INDEXING (x0, ADDR); \
} \
} \
} \
}
/* 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
......@@ -616,7 +569,7 @@ while (0)
function named by the symbol (such as what section it is in).
The macro definition, if any, is executed immediately after the
rtl for DECL has been created and stored in `DECL_RTL (DECL)'.
rtl for DECL has been created and stored in `DECL_RTL (DECL)'.
The value of the rtl will be a `mem' whose address is a
`symbol_ref'.
......@@ -626,7 +579,7 @@ while (0)
information).
The best way to modify the name string is by adding text to the
beginning, with suitable punctuation to prevent any ambiguity.
beginning, with suitable punctuation to prevent any ambiguity.
Allocate the new name in `saveable_obstack'. You will have to
modify `ASM_OUTPUT_LABELREF' to remove and decode the added text
and output the name accordingly.
......@@ -753,7 +706,7 @@ while (0)
/* A C statement (sans semicolon) to output to the stdio stream
STREAM any text necessary for declaring the name NAME of an
initialized variable which is being defined. This macro must
output the label definition (perhaps using `ASM_OUTPUT_LABEL').
output the label definition (perhaps using `ASM_OUTPUT_LABEL').
The argument DECL is the `VAR_DECL' tree node representing the
variable.
......@@ -914,6 +867,12 @@ do \
if (flag_unroll_loops) \
fprintf ((STREAM), " -funroll-loops"); \
\
if (flag_schedule_insns) \
fprintf ((STREAM), " -fschedule-insns"); \
\
if (flag_schedule_insns_after_reload) \
fprintf ((STREAM), " -fschedule-insns2"); \
\
if (flag_force_mem) \
fprintf ((STREAM), " -fforce-mem"); \
\
......@@ -947,7 +906,18 @@ do \
if (TARGET_HALF_PIC) \
fprintf ((STREAM), " -mhalf-pic"); \
\
fprintf ((STREAM), (TARGET_486) ? " -m486" : " -m386"); \
if (!TARGET_MOVE) \
fprintf ((STREAM), " -mno-move"); \
\
if (TARGET_386) \
fprintf ((STREAM), " -m386"); \
\
else if (TARGET_486) \
fprintf ((STREAM), " -m486"); \
\
else \
fprintf ((STREAM), " -munknown-machine"); \
\
fprintf ((STREAM), (TARGET_ELF) ? " -melf\"\n" : " -mrose\"\n"); \
} \
} \
......@@ -957,7 +927,6 @@ while (0)
#define OBJECT_FORMAT_ROSE
/* Tell collect where the appropriate binaries are. */
#define REAL_LD_FILE_NAME "/usr/ccs/gcc/gld"
#define REAL_NM_FILE_NAME "/usr/ccs/bin/nm"
#define REAL_STRIP_FILE_NAME "/usr/ccs/bin/strip"
......@@ -985,62 +954,6 @@ while (0)
output_lang_identify (STREAM); \
}
/* This is how to output an assembler line defining a `double' constant.
Use "word" pseudos to avoid printing NaNs, infinity, etc. */
/* This is how to output an assembler line defining a `double' constant. */
#undef ASM_OUTPUT_DOUBLE
#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
do \
{ \
long value_long[2]; \
char dstr[30]; \
REAL_VALUE_TO_TARGET_DOUBLE (VALUE, value_long); \
REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
if (sizeof (int) == sizeof (long)) \
fprintf (STREAM, "\t.long\t0x%08x\t\t# %s\n\t.long\t0x%08x\n", \
value_long[0], dstr, value_long[1]); \
else \
fprintf (STREAM, "\t.long\t0x%08lx\t\t# %s\n\t.long\t0x%08lx\n", \
value_long[0], dstr, value_long[1]); \
} \
while (0)
/* This is how to output an assembler line defining a `float' constant. */
#undef ASM_OUTPUT_FLOAT
#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
do \
{ \
long value_long; \
char dstr[30]; \
REAL_VALUE_TO_TARGET_SINGLE (VALUE, value_long); \
REAL_VALUE_TO_DECIMAL (VALUE, "%.12g", dstr); \
if (sizeof (int) == sizeof (long)) \
fprintf (STREAM, "\t.long\t0x%08x\t\t# %s (float)\n", \
value_long, dstr); \
else \
fprintf (STREAM, "\t.long\t0x%08lx\t\t# %s (float)\n", \
value_long, dstr); \
} \
while (0)
/* This is how to output an assembler line for a `long double' constant. */
#undef ASM_OUTPUT_LONG_DOUBLE
#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
do { long l[3]; \
char dstr[30]; \
REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
if (sizeof (int) == sizeof (long)) \
fprintf (FILE, \
"\t.long\t0x%08x\t\t# %s\n\t.long\t0x%08x\n\t.long\t0x%08x\n", \
l[0], dstr, l[1], l[2]); \
else \
fprintf (FILE, \
"\t.long\t0x%08lx\t\t# %s\n\t.long\t0x%08lx\n\t.long\t0x%08lx\n", \
l[0], dstr, l[1], l[2]); \
} while (0)
/* Generate calls to memcpy, etc., not bcopy, etc. */
#define TARGET_MEM_FUNCTIONS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment