Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
3b3c6a3f
Commit
3b3c6a3f
authored
Aug 26, 1994
by
Michael Meissner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add -mno-wide-multiply, -mno-move, make addresses more compatible with other parts of compiler.
From-SVN: r7989
parent
e8e1942a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
764 additions
and
433 deletions
+764
-433
gcc/config/i386/i386.c
+533
-140
gcc/config/i386/i386.h
+178
-153
gcc/config/i386/osfrose.h
+53
-140
No files found.
gcc/config/i386/i386.c
View file @
3b3c6a3f
/* Subroutines for insn-output.c for Intel
803
86.
Copyright (C) 1988, 1992 Free Software Foundation, Inc.
/* Subroutines for insn-output.c for Intel
X
86.
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_4
86
)
if
(
!
TARGET_3
86
)
{
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
==========
\n
GO_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
==========
\n
LEGITIMIZE_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. */
...
...
gcc/config/i386/i386.h
View file @
3b3c6a3f
/* 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
...
...
gcc/config/i386/osfrose.h
View file @
3b3c6a3f
...
...
@@ -48,13 +48,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|| (CHAR) == 'h' \
|| (CHAR) == 'z')
#define MASK_HALF_PIC 0
x4
0000000
/* Mask for half-pic code */
#define MASK_HALF_PIC_DEBUG
0x2
0000000
/* Debug flag */
#define MASK_ELF 0
x1
0000000
/* ELF not rose */
#define MASK_NO_IDENT 0
x08
000000
/* suppress .ident */
#define MASK_NO_UNDERSCORES 0
x04
000000
/* suppress leading _ */
#define MASK_LARGE_ALIGN 0
x02
000000
/* align to >word boundaries */
#define MASK_NO_MCOUNT 0
x01
000000
/* profiling uses mcount_ptr */
#define MASK_HALF_PIC 0
1000
0000000
/* Mask for half-pic code */
#define MASK_HALF_PIC_DEBUG
00400
0000000
/* Debug flag */
#define MASK_ELF 0
0200
0000000
/* ELF not rose */
#define MASK_NO_IDENT 0
01000
000000
/* suppress .ident */
#define MASK_NO_UNDERSCORES 0
00400
000000
/* suppress leading _ */
#define MASK_LARGE_ALIGN 0
00200
000000
/* align to >word boundaries */
#define MASK_NO_MCOUNT 0
00100
000000
/* 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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment