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
aeb4f5ef
Commit
aeb4f5ef
authored
May 12, 2000
by
Nick Clifton
Committed by
Nick Clifton
May 12, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add movdi pattern to FR30 port.
From-SVN: r33885
parent
1d11bf18
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
262 additions
and
13 deletions
+262
-13
gcc/ChangeLog
+19
-0
gcc/config/fr30/fr30-protos.h
+3
-0
gcc/config/fr30/fr30.c
+197
-10
gcc/config/fr30/fr30.h
+6
-3
gcc/config/fr30/fr30.md
+37
-0
No files found.
gcc/ChangeLog
View file @
aeb4f5ef
2000
-
05
-
12
Nick
Clifton
<
nickc
@cygnus
.
com
>
*
config
/
fr30
/
fr30
.
c
(
fr30_move_double
)
:
New
function
:
Emit
code
to
move
a
double
word
value
.
(
di_operand
)
:
New
function
:
Return
true
if
the
operand
is
suitbale
for
a
double
word
move
operation
.
(
nonimmediate_di_operand
)
:
New
function
:
Return
true
if
the
operand
is
a
DImode
register
or
MEM
.
*
config
/
fr30
/
fr30
.
h
(
PREDICATE_CODES
)
:
Add
di_operand
and
nonimmediate_di_operand
.
*
config
/
fr30
/
fr30
-
protos
.
h
Add
fr30_move_double
,
di_operand
,
and
nonimmediate_di_operand
.
*
config
/
fr30
/
fr30
.
md
(
movdi
)
:
New
pattern
.
Required
because
other
patterns
generate
DImode
results
.
(
movdi_insn
)
:
New
pattern
.
2000
-
05
-
12
Richard
Henderson
<
rth
@cygnus
.
com
>
*
config
/
alpha
/
alpha
.
c
(
struct
shadow_summary
)
:
Define
...
...
gcc/config/fr30/fr30-protos.h
View file @
aeb4f5ef
...
...
@@ -26,6 +26,7 @@ extern unsigned int fr30_compute_frame_size PARAMS ((int, int));
extern
int
fr30_check_multiple_regs
PARAMS
((
rtx
*
,
int
,
int
));
extern
void
fr30_print_operand
PARAMS
((
FILE
*
,
rtx
,
int
));
extern
void
fr30_print_operand_address
PARAMS
((
FILE
*
,
rtx
));
extern
rtx
fr30_move_double
PARAMS
((
rtx
*
));
#ifdef TREE_CODE
extern
rtx
fr30_va_arg
PARAMS
((
tree
,
tree
));
#endif
/* TREE_CODE */
...
...
@@ -36,6 +37,8 @@ extern int add_immediate_operand PARAMS ((rtx, Mmode));
extern
int
high_register_operand
PARAMS
((
rtx
,
Mmode
));
extern
int
low_register_operand
PARAMS
((
rtx
,
Mmode
));
extern
int
call_operand
PARAMS
((
rtx
,
Mmode
));
extern
int
di_operand
PARAMS
((
rtx
,
Mmode
));
extern
int
nonimmediate_di_operand
PARAMS
((
rtx
,
Mmode
));
#undef Mmode
#endif
/* HAVE_MACHINE_MODES */
#endif
/* RTX_CODE */
...
...
gcc/config/fr30/fr30.c
View file @
aeb4f5ef
...
...
@@ -24,10 +24,8 @@ Boston, MA 02111-1307, USA. */
/*}}}*/
/*{{{ Includes */
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
/* so that MIn and MAX are defined before machmode.h */
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
...
...
@@ -44,7 +42,7 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "except.h"
#include "function.h"
#include "
fr30-protos
.h"
#include "
tm_p
.h"
/*}}}*/
/*{{{ Function Prologues & Epilogues */
...
...
@@ -839,8 +837,7 @@ low_register_operand (operand, mode)
{
return
(
GET_CODE
(
operand
)
==
REG
&&
REGNO
(
operand
)
<=
7
&&
REGNO
(
operand
)
>=
0
);
&&
REGNO
(
operand
)
<=
7
);
}
/* Returns true if OPERAND is suitable for use in a CALL insn. */
...
...
@@ -854,6 +851,56 @@ call_operand (operand, mode)
||
GET_CODE
(
XEXP
(
operand
,
0
))
==
REG
));
}
/* Returns TRUE if OP is a valid operand of a DImode operation. */
int
di_operand
(
op
,
mode
)
rtx
op
;
Mmode
mode
;
{
if
(
register_operand
(
op
,
mode
))
return
TRUE
;
if
(
mode
!=
VOIDmode
&&
GET_MODE
(
op
)
!=
VOIDmode
&&
GET_MODE
(
op
)
!=
DImode
)
return
FALSE
;
if
(
GET_CODE
(
op
)
==
SUBREG
)
op
=
SUBREG_REG
(
op
);
switch
(
GET_CODE
(
op
))
{
case
CONST_DOUBLE
:
case
CONST_INT
:
return
TRUE
;
case
MEM
:
return
memory_address_p
(
DImode
,
XEXP
(
op
,
0
));
default
:
return
FALSE
;
}
}
/* Returns TRUE if OP is a DImode register or MEM. */
int
nonimmediate_di_operand
(
op
,
mode
)
rtx
op
;
Mmode
mode
;
{
if
(
register_operand
(
op
,
mode
))
return
TRUE
;
if
(
mode
!=
VOIDmode
&&
GET_MODE
(
op
)
!=
VOIDmode
&&
GET_MODE
(
op
)
!=
DImode
)
return
FALSE
;
if
(
GET_CODE
(
op
)
==
SUBREG
)
op
=
SUBREG_REG
(
op
);
if
(
GET_CODE
(
op
)
==
MEM
)
return
memory_address_p
(
DImode
,
XEXP
(
op
,
0
));
return
FALSE
;
}
/* Returns true iff all the registers in the operands array
are in descending or ascending order. */
int
...
...
@@ -864,9 +911,9 @@ fr30_check_multiple_regs (operands, num_operands, descending)
{
if
(
descending
)
{
int
prev_regno
=
-
1
;
unsigned
int
prev_regno
=
0
;
while
(
num_operands
--
)
while
(
num_operands
--
)
{
if
(
GET_CODE
(
operands
[
num_operands
])
!=
REG
)
return
0
;
...
...
@@ -879,9 +926,9 @@ fr30_check_multiple_regs (operands, num_operands, descending)
}
else
{
int
prev_regno
=
CONDITION_CODE_REGNUM
;
unsigned
int
prev_regno
=
CONDITION_CODE_REGNUM
;
while
(
num_operands
--
)
while
(
num_operands
--
)
{
if
(
GET_CODE
(
operands
[
num_operands
])
!=
REG
)
return
0
;
...
...
@@ -897,6 +944,146 @@ fr30_check_multiple_regs (operands, num_operands, descending)
}
/*}}}*/
/*{{{ Instruction Output Routines */
/* Output a double word move.
It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
On the FR30 we are contrained by the fact that it does not
support offsetable addresses, and so we have to load the
address of the secnd word into the second destination register
before we can use it. */
rtx
fr30_move_double
(
operands
)
rtx
*
operands
;
{
rtx
src
=
operands
[
1
];
rtx
dest
=
operands
[
0
];
enum
rtx_code
src_code
=
GET_CODE
(
src
);
enum
rtx_code
dest_code
=
GET_CODE
(
dest
);
enum
machine_mode
mode
=
GET_MODE
(
dest
);
rtx
val
;
start_sequence
();
if
(
dest_code
==
REG
)
{
if
(
src_code
==
REG
)
{
int
reverse
=
(
REGNO
(
dest
)
==
REGNO
(
src
)
+
1
);
/* We normally copy the low-numbered register first. However, if
the first register of operand 0 is the same as the second register
of operand 1, we must copy in the opposite order. */
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
operand_subword
(
dest
,
reverse
,
TRUE
,
mode
),
operand_subword
(
src
,
reverse
,
TRUE
,
mode
)));
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
operand_subword
(
dest
,
!
reverse
,
TRUE
,
mode
),
operand_subword
(
src
,
!
reverse
,
TRUE
,
mode
)));
}
else
if
(
src_code
==
MEM
)
{
rtx
addr
=
XEXP
(
src
,
0
);
int
dregno
=
REGNO
(
dest
);
rtx
dest0
;
rtx
dest1
;
rtx
new_mem
;
/* If the high-address word is used in the address, we
must load it last. Otherwise, load it first. */
int
reverse
=
(
refers_to_regno_p
(
dregno
,
dregno
+
1
,
addr
,
0
)
!=
0
);
if
(
GET_CODE
(
addr
)
!=
REG
)
abort
();
dest0
=
operand_subword
(
dest
,
reverse
,
TRUE
,
mode
);
dest1
=
operand_subword
(
dest
,
!
reverse
,
TRUE
,
mode
);
if
(
reverse
)
{
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
dest1
,
change_address
(
src
,
SImode
,
addr
)));
emit_insn
(
gen_rtx_SET
(
SImode
,
dest0
,
gen_rtx_REG
(
SImode
,
REGNO
(
addr
))));
emit_insn
(
gen_rtx_SET
(
SImode
,
dest0
,
plus_constant
(
dest0
,
UNITS_PER_WORD
)));
new_mem
=
gen_rtx_MEM
(
SImode
,
dest0
);
MEM_COPY_ATTRIBUTES
(
new_mem
,
src
);
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
dest0
,
new_mem
));
}
else
{
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
dest0
,
change_address
(
src
,
SImode
,
addr
)));
emit_insn
(
gen_rtx_SET
(
SImode
,
dest1
,
gen_rtx_REG
(
SImode
,
REGNO
(
addr
))));
emit_insn
(
gen_rtx_SET
(
SImode
,
dest1
,
plus_constant
(
dest1
,
UNITS_PER_WORD
)));
new_mem
=
gen_rtx_MEM
(
SImode
,
dest1
);
MEM_COPY_ATTRIBUTES
(
new_mem
,
src
);
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
dest1
,
new_mem
));
}
}
else
if
(
src_code
==
CONST_INT
||
src_code
==
CONST_DOUBLE
)
{
rtx
words
[
2
];
split_double
(
src
,
&
words
[
0
],
&
words
[
1
]);
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
operand_subword
(
dest
,
0
,
TRUE
,
mode
),
words
[
0
]));
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
operand_subword
(
dest
,
1
,
TRUE
,
mode
),
words
[
1
]));
}
}
else
if
(
src_code
==
REG
&&
dest_code
==
MEM
)
{
rtx
addr
=
XEXP
(
dest
,
0
);
rtx
src0
;
rtx
src1
;
if
(
GET_CODE
(
addr
)
!=
REG
)
abort
();
src0
=
operand_subword
(
src
,
0
,
TRUE
,
mode
);
src1
=
operand_subword
(
src
,
1
,
TRUE
,
mode
);
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
change_address
(
dest
,
SImode
,
addr
),
src0
));
if
(
REGNO
(
addr
)
==
STACK_POINTER_REGNUM
)
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
change_address
(
dest
,
SImode
,
plus_constant
(
stack_pointer_rtx
,
UNITS_PER_WORD
)),
src1
));
else
if
(
REGNO
(
addr
)
==
FRAME_POINTER_REGNUM
)
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
change_address
(
dest
,
SImode
,
plus_constant
(
frame_pointer_rtx
,
UNITS_PER_WORD
)),
src1
));
else
{
rtx
new_mem
;
/* We need a scratch register to hold the value of 'address + 4'.
We ought to allow gcc to find one for us, but for now, just
push one of the source registers. */
emit_insn
(
gen_movsi_push
(
src0
));
emit_insn
(
gen_movsi_internal
(
src0
,
addr
));
emit_insn
(
gen_addsi_small_int
(
src0
,
src0
,
GEN_INT
(
UNITS_PER_WORD
)));
new_mem
=
gen_rtx_MEM
(
SImode
,
src0
);
MEM_COPY_ATTRIBUTES
(
new_mem
,
dest
);
emit_insn
(
gen_rtx_SET
(
VOIDmode
,
new_mem
,
src1
));
emit_insn
(
gen_movsi_pop
(
src0
));
}
}
else
/* This should have been prevented by the contraints on movdi_insn. */
abort
();
val
=
gen_sequence
();
end_sequence
();
return
val
;
}
/*}}}*/
/* Local Variables: */
/* folded-file: t */
...
...
gcc/config/fr30/fr30.h
View file @
aeb4f5ef
...
...
@@ -84,7 +84,7 @@ extern int target_flags;
{ "small-model", TARGET_SMALL_MODEL_MASK, "Assume small address space" }, \
{ "no-small-model", - TARGET_SMALL_MODEL_MASK, "" }, \
{ "no-lsim", 0, "" }, \
{ "", TARGET_DEFAULT } \
{ "", TARGET_DEFAULT
, ""
} \
}
#define TARGET_VERSION fprintf (stderr, " (fr30)");
...
...
@@ -889,9 +889,10 @@ enum reg_class
into the stack)
- if the type is a structure or union. */
#define MUST_PASS_IN_STACK(MODE,TYPE) \
#define MUST_PASS_IN_STACK(MODE,
TYPE) \
(((MODE) == BLKmode) \
|| ((TYPE) != 0 \
|| ((TYPE) != NULL \
&& TYPE_SIZE (TYPE) != NULL \
&& (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
|| TREE_CODE (TYPE) == RECORD_TYPE \
|| TREE_CODE (TYPE) == UNION_TYPE \
...
...
@@ -1763,6 +1764,8 @@ extern struct rtx_def * fr30_compare_op1;
{ "call_operand", { MEM }}, \
{ "fp_displacement_operand", { CONST_INT }}, \
{ "sp_displacement_operand", { CONST_INT }}, \
{ "di_operand", { CONST_INT, CONST_DOUBLE, REG, MEM }}, \
{ "nonimmediate_di_operand", { REG, MEM }}, \
{ "add_immediate_operand", { REG, CONST_INT }},
/*}}}*/
...
...
gcc/config/fr30/fr30.md
View file @
aeb4f5ef
...
...
@@ -368,6 +368,43 @@
)
;;}}}
;;{{{ 8 Byte Moves
;; Note - the FR30 does not have an 8 byte load/store instruction
;; but we have to support this pattern because some other patterns
;; (eg muldisi2) can produce a DImode result.
;; (This code is stolen from the M32R port.)
(define_expand "movdi"
[
(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"
/
* Everything except mem = const or mem = mem can be done easily. *
/
if (GET_CODE (operands
[
0
]
) == MEM)
operands
[
1
]
= force_reg (DImode, operands
[
1
]
);
")
;; We use an insn and a split so that we can generate
;; RTL rather than text from fr30_move_double().
(define_insn "
*
movdi_insn"
[
(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,m,r")
(match_operand:DI 1 "di_operand" "r,m,r,nF"))]
"register_operand (operands
[
0
]
, DImode) || register_operand (operands
[
1
]
, DImode)"
"#"
[
(set_attr "length" "4,8,12,12")
]
)
(define_split
[
(set (match_operand:DI 0 "nonimmediate_di_operand" "")
(match_operand:DI 1 "di_operand" ""))]
"reload_completed"
[
(match_dup 2)
]
"operands
[
2
]
= fr30_move_double (operands);")
;;}}}
;;{{{ Load & Store Multiple Registers
;; The load multiple and store multiple patterns are implemented
...
...
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