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
de86a82e
Commit
de86a82e
authored
Jul 07, 1992
by
Richard Stallman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
restore portion accidentally deleted last time
(but not the two functions intentionally deleted). From-SVN: r1485
parent
8d9bfdc5
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
354 additions
and
1 deletions
+354
-1
gcc/config/i860/i860.c
+354
-1
No files found.
gcc/config/i860/i860.c
View file @
de86a82e
/* Subroutines for insn-output.c for Intel 860
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
Derived from sparc.c.
Written by Richard Stallman (rms@ai.mit.edu).
Hacked substantially by Ron Guilmette (rfg@ncd.com) to cater
to the whims of the System V Release 4 assembler.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "flags.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
#include "insn-flags.h"
#include "output.h"
#include "recog.h"
#include "insn-attr.h"
#include <stdio.h>
static
rtx
find_addr_reg
();
#ifndef I860_REG_PREFIX
#define I860_REG_PREFIX ""
#endif
char
*
i860_reg_prefix
=
I860_REG_PREFIX
;
/* Save information from a "cmpxx" operation until the branch is emitted. */
rtx
i860_compare_op0
,
i860_compare_op1
;
/* Return non-zero if this pattern, can be evaluated safely, even if it
was not asked for. */
int
safe_insn_src_p
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
/* Just experimenting. */
/* No floating point src is safe if it contains an arithmetic
operation, since that operation may trap. */
switch
(
GET_CODE
(
op
))
{
case
CONST_INT
:
case
LABEL_REF
:
case
SYMBOL_REF
:
case
CONST
:
return
1
;
case
REG
:
return
1
;
case
MEM
:
return
CONSTANT_ADDRESS_P
(
XEXP
(
op
,
0
));
/* We never need to negate or complement constants. */
case
NEG
:
return
(
mode
!=
SFmode
&&
mode
!=
DFmode
);
case
NOT
:
case
ZERO_EXTEND
:
return
1
;
case
EQ
:
case
NE
:
case
LT
:
case
GT
:
case
LE
:
case
GE
:
case
LTU
:
case
GTU
:
case
LEU
:
case
GEU
:
case
MINUS
:
case
PLUS
:
return
(
mode
!=
SFmode
&&
mode
!=
DFmode
);
case
AND
:
case
IOR
:
case
XOR
:
case
LSHIFT
:
case
ASHIFT
:
case
ASHIFTRT
:
case
LSHIFTRT
:
if
((
GET_CODE
(
XEXP
(
op
,
0
))
==
CONST_INT
&&
!
SMALL_INT
(
XEXP
(
op
,
0
)))
||
(
GET_CODE
(
XEXP
(
op
,
1
))
==
CONST_INT
&&
!
SMALL_INT
(
XEXP
(
op
,
1
))))
return
0
;
return
1
;
default
:
return
0
;
}
}
/* Return 1 if REG is clobbered in IN.
Return 2 if REG is used in IN.
Return 3 if REG is both used and clobbered in IN.
Return 0 if neither. */
static
int
reg_clobbered_p
(
reg
,
in
)
rtx
reg
;
rtx
in
;
{
register
enum
rtx_code
code
;
if
(
in
==
0
)
return
0
;
code
=
GET_CODE
(
in
);
if
(
code
==
SET
||
code
==
CLOBBER
)
{
rtx
dest
=
SET_DEST
(
in
);
int
set
=
0
;
int
used
=
0
;
while
(
GET_CODE
(
dest
)
==
STRICT_LOW_PART
||
GET_CODE
(
dest
)
==
SUBREG
||
GET_CODE
(
dest
)
==
SIGN_EXTRACT
||
GET_CODE
(
dest
)
==
ZERO_EXTRACT
)
dest
=
XEXP
(
dest
,
0
);
if
(
dest
==
reg
)
set
=
1
;
else
if
(
GET_CODE
(
dest
)
==
REG
&&
refers_to_regno_p
(
REGNO
(
reg
),
REGNO
(
reg
)
+
HARD_REGNO_NREGS
(
reg
,
GET_MODE
(
reg
)),
SET_DEST
(
in
),
0
))
{
set
=
1
;
/* Anything that sets just part of the register
is considered using as well as setting it.
But note that a straight SUBREG of a single-word value
clobbers the entire value. */
if
(
dest
!=
SET_DEST
(
in
)
&&
!
(
GET_CODE
(
SET_DEST
(
in
))
==
SUBREG
||
UNITS_PER_WORD
>=
GET_MODE_SIZE
(
GET_MODE
(
dest
))))
used
=
1
;
}
if
(
code
==
SET
)
{
if
(
set
)
used
=
refers_to_regno_p
(
REGNO
(
reg
),
REGNO
(
reg
)
+
HARD_REGNO_NREGS
(
reg
,
GET_MODE
(
reg
)),
SET_SRC
(
in
),
0
);
else
used
=
refers_to_regno_p
(
REGNO
(
reg
),
REGNO
(
reg
)
+
HARD_REGNO_NREGS
(
reg
,
GET_MODE
(
reg
)),
in
,
0
);
}
return
set
+
used
*
2
;
}
if
(
refers_to_regno_p
(
REGNO
(
reg
),
REGNO
(
reg
)
+
HARD_REGNO_NREGS
(
reg
,
GET_MODE
(
reg
)),
in
,
0
))
return
2
;
return
0
;
}
/* Return non-zero if OP can be written to without screwing up
GCC's model of what's going on. It is assumed that this operand
appears in the dest position of a SET insn in a conditional
branch's delay slot. AFTER is the label to start looking from. */
int
operand_clobbered_before_used_after
(
op
,
after
)
rtx
op
;
rtx
after
;
{
/* Just experimenting. */
if
(
GET_CODE
(
op
)
==
CC0
)
return
1
;
if
(
GET_CODE
(
op
)
==
REG
)
{
rtx
insn
;
if
(
op
==
stack_pointer_rtx
)
return
0
;
/* Scan forward from the label, to see if the value of OP
is clobbered before the first use. */
for
(
insn
=
NEXT_INSN
(
after
);
insn
;
insn
=
NEXT_INSN
(
insn
))
{
if
(
GET_CODE
(
insn
)
==
NOTE
)
continue
;
if
(
GET_CODE
(
insn
)
==
INSN
||
GET_CODE
(
insn
)
==
JUMP_INSN
||
GET_CODE
(
insn
)
==
CALL_INSN
)
{
switch
(
reg_clobbered_p
(
op
,
PATTERN
(
insn
)))
{
default
:
return
0
;
case
1
:
return
1
;
case
0
:
break
;
}
}
/* If we reach another label without clobbering OP,
then we cannot safely write it here. */
else
if
(
GET_CODE
(
insn
)
==
CODE_LABEL
)
return
0
;
if
(
GET_CODE
(
insn
)
==
JUMP_INSN
)
{
if
(
condjump_p
(
insn
))
return
0
;
/* This is a jump insn which has already
been mangled. We can't tell what it does. */
if
(
GET_CODE
(
PATTERN
(
insn
))
==
PARALLEL
)
return
0
;
if
(
!
JUMP_LABEL
(
insn
))
return
0
;
/* Keep following jumps. */
insn
=
JUMP_LABEL
(
insn
);
}
}
return
1
;
}
/* In both of these cases, the first insn executed
for this op will be a orh whatever%h,%?r0,%?r31,
which is tolerable. */
if
(
GET_CODE
(
op
)
==
MEM
)
return
(
CONSTANT_ADDRESS_P
(
XEXP
(
op
,
0
)));
return
0
;
}
/* Return non-zero if this pattern, as a source to a "SET",
is known to yield an instruction of unit size. */
int
single_insn_src_p
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
switch
(
GET_CODE
(
op
))
{
case
CONST_INT
:
/* This is not always a single insn src, technically,
but output_delayed_branch knows how to deal with it. */
return
1
;
case
SYMBOL_REF
:
case
CONST
:
/* This is not a single insn src, technically,
but output_delayed_branch knows how to deal with it. */
return
1
;
case
REG
:
return
1
;
case
MEM
:
return
1
;
/* We never need to negate or complement constants. */
case
NEG
:
return
(
mode
!=
DFmode
);
case
NOT
:
case
ZERO_EXTEND
:
return
1
;
case
PLUS
:
case
MINUS
:
/* Detect cases that require multiple instructions. */
if
(
CONSTANT_P
(
XEXP
(
op
,
1
))
&&
!
(
GET_CODE
(
XEXP
(
op
,
1
))
==
CONST_INT
&&
SMALL_INT
(
XEXP
(
op
,
1
))))
return
0
;
case
EQ
:
case
NE
:
case
LT
:
case
GT
:
case
LE
:
case
GE
:
case
LTU
:
case
GTU
:
case
LEU
:
case
GEU
:
/* Not doing floating point, since they probably
take longer than the branch slot they might fill. */
return
(
mode
!=
SFmode
&&
mode
!=
DFmode
);
case
AND
:
if
(
GET_CODE
(
XEXP
(
op
,
1
))
==
NOT
)
{
rtx
arg
=
XEXP
(
XEXP
(
op
,
1
),
0
);
if
(
CONSTANT_P
(
arg
)
&&
!
(
GET_CODE
(
arg
)
==
CONST_INT
&&
(
SMALL_INT
(
arg
)
||
INTVAL
(
arg
)
&
0xffff
==
0
)))
return
0
;
}
case
IOR
:
case
XOR
:
/* Both small and round numbers take one instruction;
others take two. */
if
(
CONSTANT_P
(
XEXP
(
op
,
1
))
&&
!
(
GET_CODE
(
XEXP
(
op
,
1
))
==
CONST_INT
&&
(
SMALL_INT
(
XEXP
(
op
,
1
))
||
INTVAL
(
XEXP
(
op
,
1
))
&
0xffff
==
0
)))
return
0
;
case
LSHIFT
:
case
ASHIFT
:
case
ASHIFTRT
:
case
LSHIFTRT
:
return
1
;
case
SUBREG
:
if
(
SUBREG_WORD
(
op
)
!=
0
)
return
0
;
return
single_insn_src_p
(
SUBREG_REG
(
op
),
mode
);
/* Not doing floating point, since they probably
take longer than the branch slot they might fill. */
case
FLOAT_EXTEND
:
case
FLOAT_TRUNCATE
:
case
FLOAT
:
case
FIX
:
case
UNSIGNED_FLOAT
:
case
UNSIGNED_FIX
:
return
0
;
default
:
return
0
;
}
}
/* Return non-zero only if OP is a register of mode MODE,
or const0_rtx. */
...
...
@@ -1199,7 +1552,7 @@ sfmode_constant_to_ulong (x)
for saving all of the "preserved" registers (and use that number, i.e.
`80', to define STARTING_FRAME_OFFSET) if we wanted to save them in
the lower part of the frame. That could potentially be very wasteful,
and that
could cause serious problems when
compiling for embedded
and that
wastefulness could really hamper people
compiling for embedded
i860 targets with very tight limits on stack space. Thus, we choose
here to save the preserved registers in the upper part of the
frame, so that we can decide at the very last minute how much (or how
...
...
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