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
b9654711
Commit
b9654711
authored
Jun 29, 1993
by
Steve Chamberlain
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Major rework.
From-SVN: r4792
parent
75d98655
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1215 additions
and
669 deletions
+1215
-669
gcc/config/sh/sh.c
+756
-388
gcc/config/sh/sh.h
+201
-91
gcc/config/sh/sh.md
+251
-178
gcc/config/sh/t-sh
+1
-11
gcc/config/sh/xm-sh.h
+6
-1
No files found.
gcc/config/sh/sh.c
View file @
b9654711
...
@@ -39,10 +39,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -39,10 +39,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
static
int
add_constant
();
static
int
add_constant
();
static
int
dump_constants
();
int
dump_constants
();
int
current_function_anonymous_args
;
int
current_function_anonymous_args
;
extern
int
current_function_pretend_args_size
;
extern
int
current_function_pretend_args_size
;
extern
char
*
version_string
;
extern
int
flag_traditional
;
enum
attr_cpu
sh_cpu
;
/* target cpu */
/* Global variables for machine-dependent things. */
/* Global variables for machine-dependent things. */
...
@@ -80,6 +85,8 @@ enum reg_class reg_class_from_letter[] =
...
@@ -80,6 +85,8 @@ enum reg_class reg_class_from_letter[] =
};
};
/* Local label counter, used for constants in the pool and inside
/* Local label counter, used for constants in the pool and inside
pattern branches. */
pattern branches. */
...
@@ -92,40 +99,55 @@ static int pc;
...
@@ -92,40 +99,55 @@ static int pc;
#define MUST_DUMP_LEVEL 1000
#define MUST_DUMP_LEVEL 1000
static
int
dumpnext
;
static
int
dumpnext
;
/* Functions for generating procedure prologue and epilogue code */
void
push
(
rn
)
{
emit_insn
(
gen_push
(
gen_rtx
(
REG
,
SImode
,
rn
)));
}
void
pop
(
rn
)
{
emit_insn
(
gen_pop
(
gen_rtx
(
REG
,
SImode
,
rn
)));
}
/* Adjust the stack and return the number of bytes taken to do it */
/* Adjust the stack and return the number of bytes taken to do it */
static
int
static
void
output_stack_adjust
(
file
,
direction
,
size
)
output_stack_adjust
(
direction
,
size
)
FILE
*
file
;
int
direction
;
int
direction
;
int
size
;
int
size
;
{
{
int
code_size
;
if
(
size
)
if
(
size
>
127
)
{
{
fprintf
(
file
,
"
\t
mov.l LK%d,r13
\n
"
,
rtx
val
=
GEN_INT
(
size
);
add_constant
(
GEN_INT
(
size
*
direction
),
SImode
))
;
rtx
insn
;
fprintf
(
file
,
"
\t
add r13,r15
\n
"
);
if
(
size
>
120
)
code_size
+=
4
;
}
else
if
(
size
)
{
{
fprintf
(
file
,
"
\t
add #%d,r15
\n
"
,
direction
*
size
);
rtx
nval
=
gen_rtx
(
REG
,
SImode
,
13
);
code_size
+=
2
;
emit_insn
(
gen_movsi
(
nval
,
val
));
val
=
nval
;
}
if
(
direction
>
0
)
insn
=
gen_addsi3
(
stack_pointer_rtx
,
stack_pointer_rtx
,
val
);
else
insn
=
gen_subsi3
(
stack_pointer_rtx
,
stack_pointer_rtx
,
val
);
emit_insn
(
insn
);
}
}
return
code_size
;
}
}
/* Generate code to push the regs specified in the mask, and return
/* Generate code to push the regs specified in the mask, and return
the number of bytes the insns take. */
the number of bytes the insns take. */
static
int
static
void
push_regs
(
f
,
mask
)
push_regs
(
mask
)
FILE
*
f
;
int
mask
;
int
mask
;
{
{
int
i
;
int
i
;
...
@@ -135,154 +157,25 @@ push_regs (f, mask)
...
@@ -135,154 +157,25 @@ push_regs (f, mask)
{
{
if
(
mask
&
(
1
<<
i
))
if
(
mask
&
(
1
<<
i
))
{
{
fprintf
(
f
,
"
\t
mov.l r%d,@-r15
\n
"
,
i
);
push
(
i
);
size
+=
2
;
}
}
}
}
return
size
;
}
}
/* Working out the right code to use for an epilogue can get quite
/*
hairy, since there are only certain insns which can go in the delay
Print an instruction which would have gone into a delay slot
slot, and there may or may not be a delay insn provided already.
after an instructiuon, but couldn't because the instruction expanded
into a sequence where putting the slot insn at the end wouldn't work.
We generate a canonical list of the instructions to use to perform
*/
the exit, massage that and output from that list */
/* The structure of a canonical element. */
typedef
struct
{
enum
epi_type
{
STACK_ADJUST
,
/* add i to stack pointer */
POP
,
/* pop into register i */
RTS
,
/* rts instruction */
DELAY
,
/* delay slot instruction */
NOP
,
/* a nop */
DELETED
,
}
type
;
int
i
;
}
epilogue_insn
;
static
epilogue_insn
epilogue_vec
[
20
];
static
int
epilogue_vec_len
;
static
void
set_epilogue_insn
(
type
,
l
)
enum
epi_type
type
;
int
l
;
{
epilogue_vec
[
epilogue_vec_len
].
type
=
type
;
epilogue_vec
[
epilogue_vec_len
].
i
=
l
;
epilogue_vec_len
++
;
}
/* Delete an insn from the epilogue list. */
static
void
delete_epilogue_insn
(
n
)
int
n
;
{
int
j
;
for
(
j
=
n
;
j
<
epilogue_vec_len
;
j
++
)
epilogue_vec
[
j
]
=
epilogue_vec
[
j
+
1
];
epilogue_vec_len
--
;
}
/* Run through the epilogue list and optimize it. */
static
void
optimize_epilogue_vec
()
{
int
i
;
/* Turn two adds in a row into one add and kill empty adds */
for
(
i
=
0
;
i
<
epilogue_vec_len
-
1
;
i
++
)
{
if
(
epilogue_vec
[
i
].
type
==
STACK_ADJUST
&&
epilogue_vec
[
i
+
1
].
type
==
STACK_ADJUST
)
{
epilogue_vec
[
i
].
i
+=
epilogue_vec
[
i
+
1
].
i
;
delete_epilogue_insn
(
i
+
1
);
}
if
(
epilogue_vec
[
i
].
type
==
STACK_ADJUST
&&
epilogue_vec
[
i
].
i
==
0
)
delete_epilogue_insn
(
i
);
}
/* If the instruction after the RTS is a nop, see if it can be
changed */
for
(
i
=
1
;
i
<
epilogue_vec_len
-
1
;
i
++
)
{
if
(
epilogue_vec
[
i
].
type
==
RTS
&&
epilogue_vec
[
i
+
1
].
type
==
NOP
)
{
epilogue_vec
[
i
+
1
]
=
epilogue_vec
[
i
-
1
];
delete_epilogue_insn
(
i
-
1
);
}
}
/* Delete all the instructions after the rts's delay slot */
for
(
i
=
0
;
i
<
epilogue_vec_len
;
i
++
)
{
if
(
epilogue_vec
[
i
].
type
==
RTS
)
{
int
j
;
for
(
j
=
i
+
2
;
j
<
epilogue_vec_len
;
j
++
)
epilogue_vec
[
j
].
type
=
DELETED
;
return
;
}
}
}
/* Dump out the insns in epilogue vector. */
static
void
void
output_epilogue_vec
()
print_slot
(
insn
)
rtx
insn
;
{
{
int
i
;
final_scan_insn
(
XVECEXP
(
insn
,
0
,
1
),
asm_out_file
,
optimize
,
0
,
1
);
for
(
i
=
0
;
i
<
epilogue_vec_len
;
i
++
)
{
switch
(
epilogue_vec
[
i
].
type
)
{
case
STACK_ADJUST
:
fprintf
(
asm_out_file
,
"
\t
add #%d,r15
\n
"
,
epilogue_vec
[
i
].
i
);
break
;
case
NOP
:
INSN_DELETED_P
(
XVECEXP
(
insn
,
0
,
1
))
=
1
;
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
break
;
case
DELAY
:
final_scan_insn
(
XEXP
(
current_function_epilogue_delay_list
,
0
),
asm_out_file
,
1
,
0
,
1
);
break
;
case
DELETED
:
fprintf
(
asm_out_file
,
"
\t
!delete_epilogue_insnd
\n
"
);
break
;
case
RTS
:
fprintf
(
asm_out_file
,
"
\t
rts
\n
"
);
break
;
case
POP
:
fprintf
(
asm_out_file
,
"
\t
mov.l @r15+,r%d
\n
"
,
epilogue_vec
[
i
].
i
);
break
;
}
}
epilogue_vec_len
=
0
;
}
}
/* Number of bytes pushed for anonymous args */
/* Number of bytes pushed for anonymous args */
...
@@ -311,159 +204,14 @@ calc_live_regs (count)
...
@@ -311,159 +204,14 @@ calc_live_regs (count)
return
live_regs_mask
;
return
live_regs_mask
;
}
}
/* Generate a procedure prologue. */
void
output_prologue
(
f
,
frame_size
)
FILE
*
f
;
int
frame_size
;
{
int
live_regs_mask
;
int
d
;
pc
=
0
;
/* This only happens when an arg has been split, part in
registers, part in memory. Allocate the stack space so there is
somewhere to put the value */
output_stack_adjust
(
f
,
-
1
,
current_function_pretend_args_size
);
live_regs_mask
=
calc_live_regs
(
&
d
);
extra_push
=
0
;
if
(
current_function_anonymous_args
)
static
int
{
need_slot
(
insn
)
/* Push arg regs as if they'd been provided by caller in stack */
rtx
insn
;
int
i
;
for
(
i
=
0
;
i
<
NPARM_REGS
;
i
++
)
{
int
rn
=
NPARM_REGS
+
FIRST_PARM_REG
-
i
-
1
;
if
(
i
>
NPARM_REGS
-
current_function_args_info
)
break
;
fprintf
(
f
,
"
\t
mov.l r%d,@-r15
\n
"
,
rn
);
extra_push
+=
4
;
pc
+=
2
;
}
}
if
(
frame_pointer_needed
)
{
/* Don't need to push the fp with the rest of the registers. */
live_regs_mask
&=
~
(
1
<<
FRAME_POINTER_REGNUM
);
pc
+=
push_regs
(
f
,
live_regs_mask
);
if
(
regs_ever_live
[
PR_REG
])
{
fprintf
(
f
,
"
\t
sts.l pr,@-r15
\n
"
);
pc
+=
2
;
}
fprintf
(
f
,
"
\t
mov.l r14,@-r15
\n
"
);
fprintf
(
f
,
"
\t
mov r15,r14
\n
"
);
pc
+=
4
;
pc
+=
output_stack_adjust
(
f
,
-
1
,
frame_size
);
}
else
{
pc
+=
push_regs
(
f
,
live_regs_mask
);
if
(
regs_ever_live
[
PR_REG
])
{
fprintf
(
f
,
"
\t
sts.l pr,@-r15
\n
"
);
pc
+=
2
;
}
pc
+=
output_stack_adjust
(
f
,
-
1
,
frame_size
);
}
}
/* Generate a procedure epilogue. */
void
output_epilogue
(
f
,
frame_size
)
FILE
*
f
;
int
frame_size
;
{
{
int
live_regs_mask
=
0
;
return
(
insn
&&
!
INSN_ANNULLED_BRANCH_P
(
XVECEXP
(
insn
,
0
,
0
)));
int
d
;
int
i
;
rtx
delay_insn
;
live_regs_mask
=
calc_live_regs
(
&
d
);
/* See if the delay insn is really ok for the slot. */
if
(
current_function_epilogue_delay_list
)
{
delay_insn
=
PATTERN
(
XEXP
(
current_function_epilogue_delay_list
,
0
));
if
(
GET_CODE
(
delay_insn
)
==
SET
&&
SET_DEST
(
delay_insn
)
==
stack_pointer_rtx
)
{
/* Can not use this instruction in the delay slot because
it changes the stack pointer, so emit it now. */
final_scan_insn
(
XEXP
(
current_function_epilogue_delay_list
,
0
),
asm_out_file
,
1
,
0
,
1
);
current_function_epilogue_delay_list
=
0
;
}
}
/* Reclaim the room for the automatics. */
output_stack_adjust
(
f
,
1
,
frame_size
);
/* Make the frame pointer. */
if
(
frame_pointer_needed
)
{
fprintf
(
f
,
"
\t
mov r14,r15
\n
"
);
fprintf
(
f
,
"
\t
mov.l @r15+,r14
\n
"
);
live_regs_mask
&=
~
(
1
<<
FRAME_POINTER_REGNUM
);
}
/* Get the PR register if it was clobbered in the function. */
if
(
regs_ever_live
[
PR_REG
])
fprintf
(
f
,
"
\t
lds.l @r15+,pr
\n
"
);
/* Pop all the registers */
for
(
i
=
0
;
i
<
FIRST_PSEUDO_REGISTER
;
i
++
)
{
int
j
=
(
FIRST_PSEUDO_REGISTER
-
1
)
-
i
;
if
(
live_regs_mask
&
(
1
<<
j
))
{
set_epilogue_insn
(
POP
,
j
);
}
}
/* Need to adjust the stack by some amount of bytes since we've pushed
some of the args which normally come in registers */
set_epilogue_insn
(
STACK_ADJUST
,
extra_push
);
/* Need to adjust the stack by some amount of bytes if there
an arg has been split part register and part stack */
set_epilogue_insn
(
STACK_ADJUST
,
current_function_pretend_args_size
);
set_epilogue_insn
(
RTS
,
0
);
/* Got here without dumping a register pop into the delay slot */
if
(
current_function_epilogue_delay_list
)
{
set_epilogue_insn
(
DELAY
,
0
);
}
set_epilogue_insn
(
NOP
,
0
);
optimize_epilogue_vec
();
output_epilogue_vec
();
dump_constants
(
0
);
current_function_anonymous_args
=
0
;
}
}
/* Print the operand address in x to the stream */
/* Print the operand address in x to the stream */
...
@@ -478,7 +226,6 @@ print_operand_address (stream, x)
...
@@ -478,7 +226,6 @@ print_operand_address (stream, x)
case
REG
:
case
REG
:
fprintf
(
stream
,
"@%s"
,
reg_names
[
REGNO
(
x
)]);
fprintf
(
stream
,
"@%s"
,
reg_names
[
REGNO
(
x
)]);
break
;
break
;
case
PLUS
:
case
PLUS
:
{
{
rtx
base
=
XEXP
(
x
,
0
);
rtx
base
=
XEXP
(
x
,
0
);
...
@@ -501,12 +248,14 @@ print_operand_address (stream, x)
...
@@ -501,12 +248,14 @@ print_operand_address (stream, x)
break
;
break
;
case
REG
:
case
REG
:
fprintf
(
stream
,
"@(
%s
,%s)"
,
fprintf
(
stream
,
"@(
r0
,%s)"
,
reg_names
[
REGNO
(
base
)],
reg_names
[
MAX
(
REGNO
(
base
),
REGNO
(
index
))]);
reg_names
[
REGNO
(
index
)]);
break
;
break
;
default
:
default
:
debug_rtx
(
x
);
abort
();
abort
();
}
}
}
}
...
@@ -529,12 +278,15 @@ print_operand_address (stream, x)
...
@@ -529,12 +278,15 @@ print_operand_address (stream, x)
/* Print operand x (an rtx) in assembler syntax to file stream
/* Print operand x (an rtx) in assembler syntax to file stream
according to modifier code.
according to modifier code.
'.' print a .s if insn needs delay slot
'*' print a local label
'*' print a local label
'^' increment the local label number
'^' increment the local label number
'!' dump the constant table
'!' dump the constant table
'#' output a nop if there is nothing to put in the delay slot
'#' output a nop if there is nothing to put in the delay slot
'R' print the next register or memory location along, ie the lsw in
'R' print the next register or memory location along, ie the lsw in
a double word value
a double word value
'O' print a constant without the #
'M' print a constant as its negative
'I' put something into the constant pool and print its label */
'I' put something into the constant pool and print its label */
void
void
...
@@ -545,6 +297,12 @@ print_operand (stream, x, code)
...
@@ -545,6 +297,12 @@ print_operand (stream, x, code)
{
{
switch
(
code
)
switch
(
code
)
{
{
case
'.'
:
if
(
need_slot
(
final_sequence
))
fprintf
(
stream
,
".s"
);
break
;
case
'*'
:
case
'*'
:
fprintf
(
stream
,
"LF%d"
,
lf
);
fprintf
(
stream
,
"LF%d"
,
lf
);
break
;
break
;
...
@@ -562,11 +320,18 @@ print_operand (stream, x, code)
...
@@ -562,11 +320,18 @@ print_operand (stream, x, code)
fprintf
(
stream
,
"
\n\t
or r0,r0
\t
!wasted slot"
);
fprintf
(
stream
,
"
\n\t
or r0,r0
\t
!wasted slot"
);
}
}
break
;
break
;
case
'O'
:
fprintf
(
asm_out_file
,
"%d"
,
INTVAL
(
x
));
break
;
case
'I'
:
case
'I'
:
fprintf
(
asm_out_file
,
"LK%d"
,
add_constant
(
x
,
SImode
));
fprintf
(
asm_out_file
,
"LK%d"
,
add_constant
(
x
,
SImode
));
break
;
break
;
case
'M'
:
fprintf
(
asm_out_file
,
"#%d"
,
-
INTVAL
(
x
));
break
;
case
'R'
:
case
'R'
:
/* Next location along in memory or register*/
/* Next location along in memory or register*/
switch
(
GET_CODE
(
x
))
switch
(
GET_CODE
(
x
))
...
@@ -610,7 +375,7 @@ initial_elimination_offset (from, to)
...
@@ -610,7 +375,7 @@ initial_elimination_offset (from, to)
{
{
int
regs_saved
;
int
regs_saved
;
int
d
=
calc_live_regs
(
&
regs_saved
);
int
d
=
calc_live_regs
(
&
regs_saved
);
int
total_saved_regs_space
=
(
regs_saved
+
regs_ever_live
[
PR_REG
]
)
*
4
;
int
total_saved_regs_space
=
(
regs_saved
)
*
4
;
int
total_auto_space
=
get_frame_size
();
int
total_auto_space
=
get_frame_size
();
...
@@ -630,22 +395,12 @@ initial_elimination_offset (from, to)
...
@@ -630,22 +395,12 @@ initial_elimination_offset (from, to)
}
}
}
}
delay_slots_for_epilogue
()
{
/* We need to find something to fill the epilogue if there won't be
any instructions to make the stack or pop registers which can be
moved into the slot */
int
d
;
calc_live_regs
(
&
d
);
return
!
(
get_frame_size
()
+
d
);
}
/* Prepare operands for a move define_expand; specifically, one of the
/* Prepare operands for a move define_expand; specifically, one of the
operands must be in a register */
operands must be in a register. Take this chance to remove
addressing modes which can't be coped with very well. */
void
int
prepare_move_operands
(
operands
,
mode
)
prepare_move_operands
(
operands
,
mode
)
rtx
operands
[];
rtx
operands
[];
enum
machine_mode
mode
;
enum
machine_mode
mode
;
...
@@ -653,11 +408,33 @@ prepare_move_operands (operands, mode)
...
@@ -653,11 +408,33 @@ prepare_move_operands (operands, mode)
/* One of the operands has to be a register */
/* One of the operands has to be a register */
if
((
!
register_operand
(
operands
[
0
],
mode
)
if
((
!
register_operand
(
operands
[
0
],
mode
)
&&
!
register_operand
(
operands
[
1
],
mode
))
&&
!
register_operand
(
operands
[
1
],
mode
))
||
GET_CODE
(
operands
[
1
])
==
PLUS
)
||
GET_CODE
(
operands
[
1
])
==
PLUS
)
{
{
/* copy the source to a register */
/* copy the source to a register */
operands
[
1
]
=
copy_to_mode_reg
(
mode
,
operands
[
1
]);
operands
[
1
]
=
copy_to_mode_reg
(
mode
,
operands
[
1
]);
}
}
/* If we've got a negative index, break it down */
if
(
GET_CODE
(
operands
[
0
])
==
MEM
&&
!
reload_in_progress
)
{
rtx
inside
=
XEXP
(
operands
[
0
],
0
);
if
(
GET_CODE
(
inside
)
==
PLUS
)
{
rtx
inside1
=
XEXP
(
inside
,
1
);
if
(
GET_CODE
(
inside1
)
==
CONST_INT
&&
INTVAL
(
inside1
)
<
0
)
{
/* Catch this now and break it into bits, it will only cause
problems later */
rtx
sub
=
copy_to_mode_reg
(
SImode
,
inside
);
XEXP
(
operands
[
0
],
0
)
=
sub
;
}
}
}
return
0
;
}
}
...
@@ -666,8 +443,8 @@ prepare_move_operands (operands, mode)
...
@@ -666,8 +443,8 @@ prepare_move_operands (operands, mode)
rtx
rtx
prepare_scc_operands
(
code
)
prepare_scc_operands
(
code
)
{
{
if
(
GET_CODE
(
sh_compare_op0
)
!=
REG
if
(
GET_CODE
(
sh_compare_op0
)
!=
REG
||
REGNO
(
sh_compare_op0
)
!=
T_REG
)
||
REGNO
(
sh_compare_op0
)
!=
T_REG
)
{
{
/* First need a compare insn */
/* First need a compare insn */
emit_insn
(
gen_rtx
(
SET
,
SImode
,
emit_insn
(
gen_rtx
(
SET
,
SImode
,
...
@@ -675,84 +452,155 @@ prepare_scc_operands (code)
...
@@ -675,84 +452,155 @@ prepare_scc_operands (code)
gen_rtx
(
code
,
SImode
,
sh_compare_op0
,
gen_rtx
(
code
,
SImode
,
sh_compare_op0
,
sh_compare_op1
)));
sh_compare_op1
)));
}
}
return
gen_rtx
(
REG
,
SImode
,
T_REG
);
return
gen_rtx
(
REG
,
SImode
,
T_REG
);
}
}
/* Functions to output assembly */
/* Functions to output assembly */
/* Return a sequence of instructions to perform DI move, taking into
/* Return a sequence of instructions to perform DI or DF move.
account overlapping source and dest registers */
Since the SH cannot move a DI or DF in one instruction, we have
to take care when we see overlapping source and dest registers.
*/
char
*
char
*
output_movedouble
(
operands
,
mode
)
output_movedouble
(
operands
,
mode
)
rtx
operands
[];
rtx
operands
[];
enum
machine_mode
mode
;
enum
machine_mode
mode
;
{
{
if
(
register_operand
(
operands
[
0
],
mode
)
rtx
dst
=
operands
[
0
];
&&
register_operand
(
operands
[
1
],
mode
))
rtx
src
=
operands
[
1
];
int
lowfirst
;
if
(
register_operand
(
dst
,
mode
)
&&
register_operand
(
src
,
mode
))
{
{
if
(
REGNO
(
operands
[
1
]
)
==
MACH_REG
)
if
(
REGNO
(
src
)
==
MACH_REG
)
return
"sts mach,%0
\n\t
sts macl,%R0"
;
return
"sts mach,%0
\n\t
sts macl,%R0"
;
if
(
REGNO
(
operands
[
1
])
>
REGNO
(
operands
[
0
]))
{
/*
return
"mov %1,%0
\n\t
mov %R1,%R0"
;
when mov.d r1,r2 do r2->r3 then r1->r2
}
when mov.d r1,r0 do r1->r0 then r2->r1
*/
if
(
REGNO
(
src
)
+
1
==
REGNO
(
dst
))
return
"mov %1,%0
\n\t
mov %R1,%R0 ! cr"
;
else
else
{
return
"mov %R1,%R0
\n\t
mov %1,%0 "
;
return
"mov %R1,%R0
\n\t
mov %1,%0"
;
}
}
if
(
GET_CODE
(
operands
[
1
])
==
CONST_INT
)
}
else
if
(
GET_CODE
(
src
)
==
CONST_INT
)
{
{
if
(
INTVAL
(
operands
[
1
]
)
<
0
)
if
(
INTVAL
(
src
)
<
0
)
return
"mov #-1,%0
\n\t
mov %1,%R0"
;
return
"mov #-1,%0
\n\t
mov %1,%R0"
;
else
else
return
"mov #0,%0
\n\t
mov %1,%R0"
;
return
"mov #0,%0
\n\t
mov %1,%R0"
;
}
}
if
(
GET_CODE
(
operands
[
1
]
)
==
MEM
)
else
if
(
GET_CODE
(
src
)
==
MEM
)
{
{
int
idxreg
=
-
1
;
int
ptrreg1
=
-
1
;
rtx
inside
=
XEXP
(
operands
[
1
],
0
);
int
ptrreg2
=
-
1
;
int
dreg
=
REGNO
(
dst
);
rtx
inside
=
XEXP
(
src
,
0
);
if
(
GET_CODE
(
inside
)
==
REG
)
if
(
GET_CODE
(
inside
)
==
REG
)
idxreg
=
REGNO
(
inside
);
{
ptrreg1
=
REGNO
(
inside
);
}
else
if
(
GET_CODE
(
inside
)
==
PLUS
)
else
if
(
GET_CODE
(
inside
)
==
PLUS
)
{
{
rtx
lhs
=
XEXP
(
inside
,
0
);
rtx
lhs
=
XEXP
(
inside
,
0
);
rtx
rhs
=
XEXP
(
inside
,
1
);
rtx
rhs
=
XEXP
(
inside
,
1
);
if
(
GET_CODE
(
lhs
)
==
REG
)
if
(
GET_CODE
(
lhs
)
==
REG
)
idxreg
=
REGNO
(
lhs
);
ptrreg1
=
REGNO
(
lhs
);
else
if
(
GET_CODE
(
rhs
)
==
REG
)
if
(
GET_CODE
(
rhs
)
==
REG
)
idxreg
=
REGNO
(
rhs
);
ptrreg2
=
REGNO
(
rhs
);
}
else
else
abort
();
abort
();
if
((
ptrreg1
>=
0
&&
ptrreg2
>=
0
)
&&
(
dreg
==
ptrreg1
||
dreg
==
ptrreg2
||
dreg
+
1
==
ptrreg1
||
dreg
+
1
==
ptrreg2
))
{
/* This move clobbers both index registers,
calculate the sum in one register. */
fprintf
(
asm_out_file
,
" add %s,%s ! special fix
\n
"
,
reg_names
[
ptrreg2
],
reg_names
[
ptrreg1
]);
if
(
dreg
==
ptrreg1
)
{
/* Copy into dreg+1 first. */
fprintf
(
asm_out_file
,
" mov.l @(4,%s),%s
\n
"
,
reg_names
[
ptrreg1
],
reg_names
[
dreg
+
1
]);
fprintf
(
asm_out_file
,
" mov.l @(%s),%s
\n
"
,
reg_names
[
ptrreg1
],
reg_names
[
dreg
]);
}
}
else
else
abort
();
{
/* Copy into dreg first. */
fprintf
(
asm_out_file
,
" mov.l @(%s),%s
\n
"
,
reg_names
[
ptrreg1
],
reg_names
[
dreg
]);
fprintf
(
asm_out_file
,
" mov.l @(4,%s),%s
\n
"
,
reg_names
[
ptrreg1
],
reg_names
[
dreg
+
1
]);
if
(
REGNO
(
operands
[
0
])
!=
idxreg
)
}
warning
(
"generated complex amode"
);
return
""
;
}
/* Work out the safe way to copy */
if
(
dreg
==
ptrreg1
)
{
{
/* The dest register is mentioned in the addressing mode,
/* Copy into the second half first */
so print them the other way around */
return
"mov.l %R1,%R0
\n\t
mov.l %1,%0 ! cr"
;
return
"mov.l %1,%0
\n\t
mov.l %R1,%R0 ! one way"
;
}
}
return
"mov.l %R1,%R0
\n\t
mov.l %1,%0 ! other way"
;
}
}
return
"mov.l %
R1,%R0
\n\t
mov.l %1,%
0"
;
return
"mov.l %
1,%0
\n\t
mov.l %R1,%R
0"
;
}
}
/* Emit assembly to shift reg by k bits */
/* Emit assembly to shift reg by k bits */
char
*
char
*
output_shift
(
string
,
reg
,
k
)
output_shift
(
string
,
reg
,
k
,
code
)
char
*
string
;
char
*
string
;
rtx
reg
;
rtx
reg
;
rtx
k
;
rtx
k
;
int
code
;
{
{
int
s
=
INTVAL
(
k
);
int
s
=
INTVAL
(
k
);
if
(
code
==
ASHIFT
&&
s
==
31
)
{
/* Shift left by 31 moving into the t bit, clearing and rotating the other way */
fprintf
(
asm_out_file
,
"
\t
rotr r%d
\n
"
,
REGNO
(
reg
));
fprintf
(
asm_out_file
,
"
\t
mov #0,r%d
\n
"
,
REGNO
(
reg
));
fprintf
(
asm_out_file
,
"
\t
rotcr r%d
\n
"
,
REGNO
(
reg
));
s
=
0
;
}
if
(
code
==
LSHIFTRT
&&
s
==
31
)
{
fprintf
(
asm_out_file
,
"
\t
rotl r%d
\n
"
,
REGNO
(
reg
));
fprintf
(
asm_out_file
,
"
\t
mov #0,r%d
\n
"
,
REGNO
(
reg
));
fprintf
(
asm_out_file
,
"
\t
rotcl r%d
\n
"
,
REGNO
(
reg
));
s
=
0
;
}
while
(
s
)
while
(
s
)
{
{
char
*
out
;
char
*
out
;
...
@@ -785,51 +633,171 @@ output_shift (string, reg, k)
...
@@ -785,51 +633,171 @@ output_shift (string, reg, k)
}
}
/* Return the text of the branch instruction which matches its length
/* Return the text of the branch instruction which matches its length
attribute. */
attribute.
This gets tricky if we have an insn in the delay slot of a branch
and the branch needs more than 1 insn to complete.*/
char
*
char
*
output_branch
(
logic
,
insn
)
output_branch
(
logic
,
insn
)
int
logic
;
int
logic
;
rtx
*
insn
;
rtx
insn
;
{
{
extern
rtx
recog_operand
[];
extern
rtx
recog_operand
[];
int
label
=
lf
++
;
int
label
=
lf
++
;
int
rn
=
-
1
;
int
need_save
;
switch
(
get_attr_length
(
insn
))
switch
(
get_attr_length
(
insn
))
{
{
case
2
:
case
2
:
/* Simple branch in range -200..+200 bytes */
/* Simple branch in range -200..+200 bytes */
return
logic
?
"bt %l0"
:
"bf %l0"
;
return
logic
?
"bt%. %l0"
:
"bf%. %l0"
;
case
6
:
/* Branch in range -4000..+4000 bytes */
{
rtx
oldop
=
recog_operand
[
0
];
if
(
need_slot
(
final_sequence
))
{
fprintf
(
asm_out_file
,
"
\t
b%c.s
\t
LF%d
\n
"
,
logic
?
'f'
:
't'
,
label
);
print_slot
(
final_sequence
);
}
else
{
fprintf
(
asm_out_file
,
"
\t
b%c
\t
LF%d
\n
"
,
logic
?
'f'
:
't'
,
label
);
}
recog_operand
[
0
]
=
oldop
;
case
6
:
/* Branch in range -4000..+4000 bytes */
fprintf
(
asm_out_file
,
"
\t
b%c
\t
LF%d
\n
"
,
logic
?
'f'
:
't'
,
label
);
output_asm_insn
(
"bra %l0 ! 12 bit cond "
,
recog_operand
);
output_asm_insn
(
"bra %l0 ! 12 bit cond "
,
recog_operand
);
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
label
=
dump_constants
(
label
);
label
=
dump_constants
(
label
);
fprintf
(
asm_out_file
,
"LF%d:
\n
"
,
label
);
fprintf
(
asm_out_file
,
"LF%d:
\n
"
,
label
);
}
return
""
;
return
""
;
case
8
:
case
8
:
/* Branches a long way away */
/* Branches a long way away */
{
rtx
oldop
=
recog_operand
[
0
];
if
(
need_slot
(
final_sequence
))
{
fprintf
(
asm_out_file
,
"
\t
b%c.s
\t
LF%d
\n
"
,
logic
?
'f'
:
't'
,
label
);
print_slot
(
final_sequence
);
}
else
{
fprintf
(
asm_out_file
,
"
\t
b%c
\t
LF%d
\n
"
,
logic
?
'f'
:
't'
,
label
);
fprintf
(
asm_out_file
,
"
\t
b%c
\t
LF%d
\n
"
,
logic
?
'f'
:
't'
,
label
);
output_asm_insn
(
"mov.l %I0,r13"
,
recog_operand
);
}
fprintf
(
asm_out_file
,
"
\t
jmp @r13 ! 32 cond
\n
"
);
recog_operand
[
0
]
=
oldop
;
/* We use r13 as a scratch */
need_save
=
0
;
rn
=
13
;
if
(
need_save
)
fprintf
(
asm_out_file
,
"
\t
push r%d
\n
"
,
rn
);
fprintf
(
asm_out_file
,
"
\t
mov.l LK%d,r%d
\n
"
,
add_constant
(
oldop
,
SImode
),
rn
);
fprintf
(
asm_out_file
,
"
\t
jmp @r%d ! 32 cond
\n
"
,
rn
);
if
(
need_save
)
fprintf
(
asm_out_file
,
"
\t
pop r%d
\n
"
,
rn
);
else
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
fprintf
(
asm_out_file
,
"LF%d:
\n
"
,
label
);
fprintf
(
asm_out_file
,
"LF%d:
\n
"
,
label
);
return
""
;
return
""
;
}
}
}
return
"bad"
;
return
"bad"
;
}
}
/* Predicates used by the templates */
/* Predicates used by the templates */
/* Non zero if op is an immediate ok for a byte index */
int
byte_index_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
return
(
GET_CODE
(
op
)
==
CONST_INT
&&
INTVAL
(
op
)
>=
0
&&
INTVAL
(
op
)
<=
15
);
}
/* Non zero if OP is a pop operand */
int
pop_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
if
(
GET_CODE
(
op
)
!=
MEM
)
return
0
;
if
(
GET_MODE
(
op
)
!=
mode
)
return
0
;
op
=
XEXP
(
op
,
0
);
if
(
GET_CODE
(
op
)
!=
POST_INC
)
return
0
;
return
XEXP
(
op
,
0
)
==
stack_pointer_rtx
;
}
/* Non zero if OP is an immediate which can be made from two insns. */
int
painful_immediate_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
if
(
GET_CODE
(
op
)
==
CONST_INT
)
{
int
i
=
INTVAL
(
op
);
if
(
i
>
127
&&
i
<
255
)
return
1
;
/* two adds */
}
return
0
;
}
/* Non zero if OP can be source of a simple move operation. */
int
general_movsrc_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
if
(
GET_CODE
(
op
)
==
REG
||
GET_CODE
(
op
)
==
SUBREG
||
(
GET_CODE
(
op
)
==
CONST_INT
&&
CONST_OK_FOR_I
(
INTVAL
(
op
)))
||
GET_CODE
(
op
)
==
MEM
)
return
general_operand
(
op
,
mode
);
return
0
;
}
/* Nonzero if OP is a normal arithmetic register. */
/* Nonzero if OP is a normal arithmetic register. */
int
int
arith_reg_operand
(
op
,
mode
)
arith_reg_operand
(
op
,
mode
)
rtx
op
;
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
mode
;
{
{
...
@@ -897,7 +865,7 @@ ok_shift_value (p)
...
@@ -897,7 +865,7 @@ ok_shift_value (p)
return
1
;
return
1
;
default
:
default
:
if
(
TARGET_FASTCODE
)
if
(
TARGET_FASTCODE
)
return
INTVAL
(
p
)
>=
0
;
return
INTVAL
(
p
)
>=
0
;
}
}
}
}
return
0
;
return
0
;
...
@@ -1078,7 +1046,10 @@ int target_insn_smallest_size;
...
@@ -1078,7 +1046,10 @@ int target_insn_smallest_size;
int
target_pc
;
int
target_pc
;
int
target_insn_range
;
int
target_insn_range
;
int
current_pc
;
int
current_pc
;
int
table_size
;
int
pool_bytes
;
int
last_uid
;
int
last_pc
;
void
void
adjust_insn_length
(
insn
,
insn_lengths
)
adjust_insn_length
(
insn
,
insn_lengths
)
...
@@ -1086,9 +1057,22 @@ adjust_insn_length (insn, insn_lengths)
...
@@ -1086,9 +1057,22 @@ adjust_insn_length (insn, insn_lengths)
short
*
insn_lengths
;
short
*
insn_lengths
;
{
{
int
uid
=
INSN_UID
(
insn
);
int
uid
=
INSN_UID
(
insn
);
rtx
body
=
PATTERN
(
insn
);
current_pc
+=
insn_lengths
[
uid
];
current_pc
+=
insn_lengths
[
uid
];
if
(
GET_CODE
(
body
)
==
SEQUENCE
)
{
int
i
;
for
(
i
=
0
;
i
<
XVECLEN
(
body
,
0
);
i
++
)
{
adjust_insn_length
(
XVECEXP
(
body
,
0
,
i
),
insn_lengths
);
}
}
else
{
if
(
has_constant_table
(
insn
))
if
(
has_constant_table
(
insn
))
{
{
if
(
current_pc
>=
target_insn_range
)
if
(
current_pc
>=
target_insn_range
)
...
@@ -1110,7 +1094,7 @@ adjust_insn_length (insn, insn_lengths)
...
@@ -1110,7 +1094,7 @@ adjust_insn_length (insn, insn_lengths)
/* Add the stuff from this insn to what will go in the
/* Add the stuff from this insn to what will go in the
growing table. */
growing table. */
table_size
+=
get_attr_constantsize
(
insn
);
pool_bytes
+=
get_attr_constantsize
(
insn
);
/* The target shinks to its smallest natural size */
/* The target shinks to its smallest natural size */
insn_lengths
[
target_insn_uid
]
=
target_insn_smallest_size
;
insn_lengths
[
target_insn_uid
]
=
target_insn_smallest_size
;
...
@@ -1118,7 +1102,7 @@ adjust_insn_length (insn, insn_lengths)
...
@@ -1118,7 +1102,7 @@ adjust_insn_length (insn, insn_lengths)
/* The current insn grows to be its larger size plust the
/* The current insn grows to be its larger size plust the
table size. */
table size. */
insn_lengths
[
uid
]
=
get_attr_largestsize
(
insn
)
+
table_size
;
insn_lengths
[
uid
]
=
get_attr_largestsize
(
insn
)
+
pool_bytes
;
}
}
/* Current insn becomes the target. */
/* Current insn becomes the target. */
...
@@ -1126,26 +1110,31 @@ adjust_insn_length (insn, insn_lengths)
...
@@ -1126,26 +1110,31 @@ adjust_insn_length (insn, insn_lengths)
target_insn_smallest_size
=
get_attr_smallestsize
(
insn
);
target_insn_smallest_size
=
get_attr_smallestsize
(
insn
);
}
}
}
}
}
/* Dump out the pending constant pool.
/* Dump out the pending constant pool.
If label provided then insert an branch in the middle of the table
If label provided then insert an branch in the middle of the table
*/
*/
static
int
int
dump_constants
(
label
)
dump_constants
(
label
)
{
{
int
i
;
int
i
;
int
rlabel
=
label
;
int
rlabel
=
label
;
int
size
=
0
;
int
size
=
0
;
for
(
i
=
0
;
i
<
pool_size
;
i
++
)
if
(
pool_size
)
{
{
pool_node
*
p
=
pool_vector
+
i
;
fprintf
(
asm_out_file
,
"
\n\t
! constants - waited %d
\n
"
,
pc
-
first_pc
);
fprintf
(
asm_out_file
,
"
\n\t
! constants - waited %d
\n
"
,
pc
-
first_pc
);
fprintf
(
asm_out_file
,
"
\t
.align
\t
2
\n
"
);
fprintf
(
asm_out_file
,
"
\t
.align
\t
2
\n
"
);
for
(
i
=
0
;
i
<
pool_size
;
i
++
)
{
pool_node
*
p
=
pool_vector
+
i
;
fprintf
(
asm_out_file
,
"LK%d:"
,
p
->
number
);
fprintf
(
asm_out_file
,
"LK%d:"
,
p
->
number
);
size
+=
GET_MODE_SIZE
(
p
->
mode
);
size
+=
GET_MODE_SIZE
(
p
->
mode
);
...
@@ -1166,16 +1155,20 @@ dump_constants (label)
...
@@ -1166,16 +1155,20 @@ dump_constants (label)
/* After 200 bytes of table, stick in another branch */
/* After 200 bytes of table, stick in another branch */
if
(
label
&&
size
>
200
)
if
(
label
&&
size
>
200
)
{
{
rlabel
=
lf
++
;
rlabel
=
lf
++
;
fprintf
(
asm_out_file
,
"LF%d:
\t
bra LF%d
\n
"
,
label
,
rlabel
);
fprintf
(
asm_out_file
,
"LF%d:
\t
bra LF%d
\n
"
,
label
,
rlabel
);
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
fprintf
(
asm_out_file
,
"
\t
or r0,r0
\n
"
);
label
=
0
;
label
=
0
;
}
}
fprintf
(
asm_out_file
,
"
\n
"
);
}
}
}
pool_size
=
0
;
pool_size
=
0
;
current_pc
=
0
;
current_pc
=
0
;
pc
=
0
;
pool_bytes
=
0
;
target_insn_range
=
0
;
target_insn_range
=
0
;
return
rlabel
;
return
rlabel
;
...
@@ -1196,7 +1189,7 @@ output_movepcrel (insn, operands, mode)
...
@@ -1196,7 +1189,7 @@ output_movepcrel (insn, operands, mode)
fprintf
(
asm_out_file
,
"
\t
mov.l LK%d,r%d
\n
"
,
fprintf
(
asm_out_file
,
"
\t
mov.l LK%d,r%d
\n
"
,
add_constant
(
operands
[
1
],
mode
),
rn
);
add_constant
(
operands
[
1
],
mode
),
rn
);
if
(
GET_MODE_SIZE
(
mode
)
>
4
)
if
(
GET_MODE_SIZE
(
mode
)
>
4
)
{
{
fprintf
(
asm_out_file
,
fprintf
(
asm_out_file
,
"
\t
mov.l LK%d+4,r%d
\n
"
,
"
\t
mov.l LK%d+4,r%d
\n
"
,
...
@@ -1204,6 +1197,16 @@ output_movepcrel (insn, operands, mode)
...
@@ -1204,6 +1197,16 @@ output_movepcrel (insn, operands, mode)
rn
+
1
);
rn
+
1
);
}
}
/* This may have been the last move in the function, so nothing
took its constant table, we may be able to move it past the end
of the function (after the rts) if we are careful */
if
(
target_insn_uid
==
INSN_UID
(
insn
)
&&
current_pc
<
target_insn_range
)
return
""
;
/* If this instruction is as small as it can be, there can be no
/* If this instruction is as small as it can be, there can be no
constant table attached to it. */
constant table attached to it. */
if
(
get_attr_length
(
insn
)
!=
get_attr_smallestsize
(
insn
))
if
(
get_attr_length
(
insn
)
!=
get_attr_smallestsize
(
insn
))
...
@@ -1222,7 +1225,7 @@ output_movepcrel (insn, operands, mode)
...
@@ -1222,7 +1225,7 @@ output_movepcrel (insn, operands, mode)
/* Dump out interesting debug info */
/* Dump out interesting debug info */
void
rtx
final_prescan_insn
(
insn
,
opvec
,
noperands
)
final_prescan_insn
(
insn
,
opvec
,
noperands
)
rtx
insn
;
rtx
insn
;
rtx
*
opvec
;
rtx
*
opvec
;
...
@@ -1247,7 +1250,6 @@ final_prescan_insn (insn, opvec, noperands)
...
@@ -1247,7 +1250,6 @@ final_prescan_insn (insn, opvec, noperands)
}
}
pc
+=
get_attr_length
(
insn
);
pc
+=
get_attr_length
(
insn
);
if
(
pool_size
&&
pc
-
first_pc
>
MUST_DUMP_LEVEL
)
if
(
pool_size
&&
pc
-
first_pc
>
MUST_DUMP_LEVEL
)
{
{
/* For some reason we have not dumped out a constant table, and
/* For some reason we have not dumped out a constant table, and
...
@@ -1263,7 +1265,373 @@ final_prescan_insn (insn, opvec, noperands)
...
@@ -1263,7 +1265,373 @@ final_prescan_insn (insn, opvec, noperands)
fprintf
(
asm_out_file
,
"LF%d:
\n
"
,
label
);
fprintf
(
asm_out_file
,
"LF%d:
\n
"
,
label
);
fprintf
(
asm_out_file
,
"
\t
!constant table end
\n
"
);
fprintf
(
asm_out_file
,
"
\t
!constant table end
\n
"
);
}
}
}
/* Block move stuff stolen from m88k*/
/* Emit code to perform a block move. Choose the best method.
OPERANDS[0] is the destination.
OPERANDS[1] is the source.
OPERANDS[2] is the size.
OPERANDS[3] is the alignment safe to use. */
/* Emit code to perform a block move with an offset sequence of ld/st
instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
known constants. DEST and SRC are registers. OFFSET is the known
starting point for the output pattern. */
static
enum
machine_mode
mode_from_align
[]
=
{
VOIDmode
,
QImode
,
HImode
,
VOIDmode
,
SImode
,
VOIDmode
,
VOIDmode
,
VOIDmode
,
DImode
};
static
void
block_move_sequence
(
dest
,
dest_mem
,
src
,
src_mem
,
size
,
align
,
offset
)
rtx
dest
,
dest_mem
;
rtx
src
,
src_mem
;
int
size
;
int
align
;
int
offset
;
{
rtx
temp
[
2
];
enum
machine_mode
mode
[
2
];
int
amount
[
2
];
int
active
[
2
];
int
phase
=
0
;
int
next
;
int
offset_ld
=
offset
;
int
offset_st
=
offset
;
active
[
0
]
=
active
[
1
]
=
FALSE
;
/* Establish parameters for the first load and for the second load if
it is known to be the same mode as the first. */
amount
[
0
]
=
amount
[
1
]
=
align
;
mode
[
0
]
=
mode_from_align
[
align
];
temp
[
0
]
=
gen_reg_rtx
(
mode
[
0
]);
if
(
size
>=
2
*
align
)
{
mode
[
1
]
=
mode
[
0
];
temp
[
1
]
=
gen_reg_rtx
(
mode
[
1
]);
}
do
{
rtx
srcp
,
dstp
;
next
=
phase
;
phase
=
!
phase
;
if
(
size
>
0
)
{
/* Change modes as the sequence tails off. */
if
(
size
<
amount
[
next
])
{
amount
[
next
]
=
(
size
>=
4
?
4
:
(
size
>=
2
?
2
:
1
));
mode
[
next
]
=
mode_from_align
[
amount
[
next
]];
temp
[
next
]
=
gen_reg_rtx
(
mode
[
next
]);
}
size
-=
amount
[
next
];
srcp
=
gen_rtx
(
MEM
,
MEM_IN_STRUCT_P
(
src_mem
)
?
mode
[
next
]
:
BLKmode
,
gen_rtx
(
PLUS
,
Pmode
,
src
,
gen_rtx
(
CONST_INT
,
SImode
,
offset_ld
)));
RTX_UNCHANGING_P
(
srcp
)
=
RTX_UNCHANGING_P
(
src_mem
);
MEM_VOLATILE_P
(
srcp
)
=
MEM_VOLATILE_P
(
src_mem
);
MEM_IN_STRUCT_P
(
srcp
)
=
1
;
emit_insn
(
gen_rtx
(
SET
,
VOIDmode
,
temp
[
next
],
srcp
));
offset_ld
+=
amount
[
next
];
active
[
next
]
=
TRUE
;
}
if
(
active
[
phase
])
{
active
[
phase
]
=
FALSE
;
dstp
=
gen_rtx
(
MEM
,
MEM_IN_STRUCT_P
(
dest_mem
)
?
mode
[
phase
]
:
BLKmode
,
gen_rtx
(
PLUS
,
Pmode
,
dest
,
gen_rtx
(
CONST_INT
,
SImode
,
offset_st
)));
RTX_UNCHANGING_P
(
dstp
)
=
RTX_UNCHANGING_P
(
dest_mem
);
MEM_VOLATILE_P
(
dstp
)
=
MEM_VOLATILE_P
(
dest_mem
);
MEM_IN_STRUCT_P
(
dstp
)
=
1
;
emit_insn
(
gen_rtx
(
SET
,
VOIDmode
,
dstp
,
temp
[
phase
]));
offset_st
+=
amount
[
phase
];
}
}
while
(
active
[
next
]);
}
void
expand_block_move
(
dest_mem
,
src_mem
,
operands
)
rtx
dest_mem
;
rtx
src_mem
;
rtx
*
operands
;
{
int
align
=
INTVAL
(
operands
[
3
]);
int
constp
=
(
GET_CODE
(
operands
[
2
])
==
CONST_INT
);
int
bytes
=
(
constp
?
INTVAL
(
operands
[
2
])
:
0
);
#if 0
if (constp && bytes <= 0)
return;
if (align > 4)
align = 4;
if (constp && bytes <= 3 * align)
block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
bytes, align, 0);
#if 0
else if (constp && bytes <= best_from_align[target][align])
block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
bytes, align);
else if (constp && align == 4 && TARGET_88100)
block_move_loop (operands[0], dest_mem, operands[1], src_mem,
bytes, align);
#endif
else
#endif
{
emit_library_call
(
gen_rtx
(
SYMBOL_REF
,
Pmode
,
"memcpy"
),
0
,
VOIDmode
,
3
,
operands
[
0
],
Pmode
,
operands
[
1
],
Pmode
,
operands
[
2
],
SImode
);
}
}
override_options
()
{
sh_cpu
=
CPU_SH0
;
if
(
TARGET_SH1
)
sh_cpu
=
CPU_SH1
;
if
(
TARGET_SH2
)
sh_cpu
=
CPU_SH2
;
if
(
TARGET_SH3
)
sh_cpu
=
CPU_SH3
;
}
/* Stuff taken from m88k.c */
/* Output to FILE the start of the assembler file. */
struct
option
{
char
*
string
;
int
*
variable
;
int
on_value
;
};
static
int
output_option
(
file
,
sep
,
type
,
name
,
indent
,
pos
,
max
)
FILE
*
file
;
char
*
sep
;
char
*
type
;
char
*
name
;
char
*
indent
;
int
pos
;
int
max
;
{
if
(
strlen
(
sep
)
+
strlen
(
type
)
+
strlen
(
name
)
+
pos
>
max
)
{
fprintf
(
file
,
indent
);
return
fprintf
(
file
,
"%s%s"
,
type
,
name
);
}
return
pos
+
fprintf
(
file
,
"%s%s%s"
,
sep
,
type
,
name
);
}
static
struct
{
char
*
name
;
int
value
;
}
m_options
[]
=
TARGET_SWITCHES
;
static
void
output_options
(
file
,
f_options
,
f_len
,
W_options
,
W_len
,
pos
,
max
,
sep
,
indent
,
term
)
FILE
*
file
;
struct
option
*
f_options
;
struct
option
*
W_options
;
int
f_len
,
W_len
;
int
pos
;
int
max
;
char
*
sep
;
char
*
indent
;
char
*
term
;
{
register
int
j
;
if
(
optimize
)
pos
=
output_option
(
file
,
sep
,
"-O"
,
""
,
indent
,
pos
,
max
);
if
(
write_symbols
!=
NO_DEBUG
)
pos
=
output_option
(
file
,
sep
,
"-g"
,
""
,
indent
,
pos
,
max
);
if
(
flag_traditional
)
pos
=
output_option
(
file
,
sep
,
"-traditional"
,
""
,
indent
,
pos
,
max
);
if
(
profile_flag
)
pos
=
output_option
(
file
,
sep
,
"-p"
,
""
,
indent
,
pos
,
max
);
if
(
profile_block_flag
)
pos
=
output_option
(
file
,
sep
,
"-a"
,
""
,
indent
,
pos
,
max
);
for
(
j
=
0
;
j
<
f_len
;
j
++
)
if
(
*
f_options
[
j
].
variable
==
f_options
[
j
].
on_value
)
pos
=
output_option
(
file
,
sep
,
"-f"
,
f_options
[
j
].
string
,
indent
,
pos
,
max
);
for
(
j
=
0
;
j
<
W_len
;
j
++
)
if
(
*
W_options
[
j
].
variable
==
W_options
[
j
].
on_value
)
pos
=
output_option
(
file
,
sep
,
"-W"
,
W_options
[
j
].
string
,
indent
,
pos
,
max
);
for
(
j
=
0
;
j
<
sizeof
m_options
/
sizeof
m_options
[
0
];
j
++
)
if
(
m_options
[
j
].
name
[
0
]
!=
'\0'
&&
m_options
[
j
].
value
>
0
&&
((
m_options
[
j
].
value
&
target_flags
)
==
m_options
[
j
].
value
))
pos
=
output_option
(
file
,
sep
,
"-m"
,
m_options
[
j
].
name
,
indent
,
pos
,
max
);
fprintf
(
file
,
term
);
}
void
output_file_start
(
file
,
f_options
,
f_len
,
W_options
,
W_len
)
FILE
*
file
;
struct
option
*
f_options
;
struct
option
*
W_options
;
int
f_len
,
W_len
;
{
register
int
pos
;
output_file_directive
(
file
,
main_input_filename
);
/* Switch to the data section so that the coffsem symbol and the
gcc2_compiled. symbol aren't in the text section. */
data_section
();
pos
=
fprintf
(
file
,
"
\n
! Hitachi SH cc1 (%s) arguments:"
,
version_string
);
output_options
(
file
,
f_options
,
f_len
,
W_options
,
W_len
,
pos
,
75
,
" "
,
"
\n
! "
,
"
\n\n
"
);
}
/* Code to generate prologue and epilogue sequences */
void
sh_expand_prologue
()
{
int
live_regs_mask
;
int
d
;
live_regs_mask
=
calc_live_regs
(
&
d
);
output_stack_adjust
(
-
1
,
current_function_pretend_args_size
);
if
(
current_function_anonymous_args
)
{
/* Push arg regs as if they'd been provided by caller in stack */
int
i
;
for
(
i
=
0
;
i
<
NPARM_REGS
;
i
++
)
{
int
rn
=
NPARM_REGS
+
FIRST_PARM_REG
-
i
-
1
;
if
(
i
>
NPARM_REGS
-
current_function_args_info
)
break
;
push
(
rn
);
extra_push
+=
4
;
}
}
if
(
frame_pointer_needed
)
{
push_regs
(
live_regs_mask
);
emit_insn
(
gen_movsi
(
frame_pointer_rtx
,
stack_pointer_rtx
));
}
else
{
push_regs
(
live_regs_mask
);
}
output_stack_adjust
(
-
1
,
get_frame_size
());
}
void
sh_expand_epilogue
()
{
int
live_regs_mask
;
int
d
;
int
i
;
live_regs_mask
=
calc_live_regs
(
&
d
);
if
(
frame_pointer_needed
)
{
emit_insn
(
gen_movsi
(
stack_pointer_rtx
,
frame_pointer_rtx
));
}
else
{
output_stack_adjust
(
1
,
get_frame_size
());
}
/* Pop all the registers */
for
(
i
=
0
;
i
<
FIRST_PSEUDO_REGISTER
;
i
++
)
{
int
j
=
(
FIRST_PSEUDO_REGISTER
-
1
)
-
i
;
if
(
live_regs_mask
&
(
1
<<
j
))
{
pop
(
j
);
}
}
output_stack_adjust
(
1
,
extra_push
+
current_function_pretend_args_size
);
extra_push
=
0
;
current_function_anonymous_args
=
0
;
}
}
/* Return the cost of a shift */
int
shiftcosts
(
RTX
)
rtx
RTX
;
{
/* If shift by a non constant, then this will be expensive. */
if
(
GET_CODE
(
XEXP
(
RTX
,
1
))
!=
CONST_INT
)
return
20
;
/* otherwise, it will be very cheap if by one of the constants
we can cope with. */
if
(
CONST_OK_FOR_K
(
INTVAL
(
XEXP
(
RTX
,
1
))))
return
1
;
/* otherwise it will be several insns. */
return
4
;
}
/* Return the cost of a multiply */
int
multcosts
(
RTX
)
rtx
RTX
;
{
/* If we we're aiming at small code, then just count the number of
insns in a multiply call sequence, otherwise, count all the insnsn
inside the call. */
if
(
TARGET_SMALLCODE
)
return
3
;
return
30
;
}
gcc/config/sh/sh.h
View file @
b9654711
...
@@ -49,18 +49,37 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -49,18 +49,37 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
extern
int
target_flags
;
extern
int
target_flags
;
#define ISIZE_BIT 1
#define ISIZE_BIT 1
#define FAST_BIT 2
#define FAST_BIT 2
#define MULSI3_BIT 4
#define MAC_BIT 8
#define MAC_BIT 8
#define RTL_BIT 16
#define RTL_BIT 16
#define DT_BIT 32
#define DT_BIT 32
#define DALIGN_BIT 64
#define DALIGN_BIT 64
#define SH0_BIT 128
#define SH1_BIT 256
#define SH2_BIT 512
#define SH3_BIT 1024
#define C_BIT 2048
#define R_BIT (1<<12)
#define SPACE_BIT (1<<13)
/* Nonzero if we should generate code using type 0 insns */
#define TARGET_SH0 (target_flags & SH0_BIT)
/* Nonzero if we should generate code using type 1 insns */
#define TARGET_SH1 (target_flags & SH1_BIT)
/* Nonzero if we should generate code using muls.l insn */
/* Nonzero if we should generate code using type 2 insns */
#define TARGET_HAS_MULSI3 (target_flags & MULSI3_BIT)
#define TARGET_SH2 (target_flags & SH2_BIT)
/* Nonzero if we should generate code using type 3 insns */
#define TARGET_SH3 (target_flags & SH3_BIT)
/* Nonzero if we should generate faster code rather than smaller code */
/* Nonzero if we should generate faster code rather than smaller code */
#define TARGET_FASTCODE (target_flags & FAST_BIT)
#define TARGET_FASTCODE (target_flags & FAST_BIT)
/* Nonzero if we should generate faster code rather than smaller code */
#define TARGET_SMALLCODE (target_flags & SPACE_BIT)
/* Nonzero if we should dump out instruction size info */
/* Nonzero if we should dump out instruction size info */
#define TARGET_DUMPISIZE (target_flags & ISIZE_BIT)
#define TARGET_DUMPISIZE (target_flags & ISIZE_BIT)
...
@@ -70,27 +89,42 @@ extern int target_flags;
...
@@ -70,27 +89,42 @@ extern int target_flags;
/* Nonzero if we should dump the rtl in the assembly file. */
/* Nonzero if we should dump the rtl in the assembly file. */
#define TARGET_DUMP_RTL (target_flags & RTL_BIT)
#define TARGET_DUMP_RTL (target_flags & RTL_BIT)
/* Nonzero if
the target has a decrement and test instruction .
*/
/* Nonzero if
we should dump the rtl somewher else.
*/
#define TARGET_
HAS_DT (target_flags & DT
_BIT)
#define TARGET_
DUMP_R (target_flags & R
_BIT)
/* Nonzero to align doubles on 64 bit boundaries */
/* Nonzero to align doubles on 64 bit boundaries */
#define TARGET_ALIGN_DOUBLE (target_flags & DALIGN_BIT)
#define TARGET_ALIGN_DOUBLE (target_flags & DALIGN_BIT)
/* Nonzero if Combine dumping wanted */
#define TARGET_CDUMP (target_flags & C_BIT)
#define TARGET_SWITCHES \
#define TARGET_SWITCHES \
{ {"isize", ( ISIZE_BIT) },\
{ {"isize", ( ISIZE_BIT) },\
{"space", (-FAST_BIT) },\
{"space", ( SPACE_BIT) },\
{"hasmulsi", ( MULSI3_BIT) },\
{"0", ( SH0_BIT) },\
{"hasdt", ( DT_BIT) },\
{"1", ( SH1_BIT) },\
{"2", ( SH2_BIT) },\
{"3", ( SH3_BIT) },\
{"ac", ( MAC_BIT) },\
{"ac", ( MAC_BIT) },\
{"dalign", ( DALIGN_BIT) },\
{"dalign", ( DALIGN_BIT) },\
{"c", ( C_BIT) },\
{"r", ( RTL_BIT) },\
{"R", ( R_BIT) },\
{"", TARGET_DEFAULT} \
{"", TARGET_DEFAULT} \
}
}
#define TARGET_DEFAULT FAST_BIT
#define TARGET_DEFAULT FAST_BIT
#define OVERRIDE_OPTIONS override_options();
/* Target machine storage Layout. */
/* Target machine storage Layout. */
/* Define to use software floating point emulator for REAL_ARITHMETIC and
decimal <-> binary conversion. */
#define REAL_ARITHMETIC
/* Define this if most significant bit is lowest numbered
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 0
#define BITS_BIG_ENDIAN 0
...
@@ -163,8 +197,7 @@ extern int target_flags;
...
@@ -163,8 +197,7 @@ extern int target_flags;
r0-r3 scratch
r0-r3 scratch
r4-r7 args in and out
r4-r7 args in and out
r8-r11 call saved
r8-r12 call saved
r12
r13 assembler temp
r13 assembler temp
r14 frame pointer
r14 frame pointer
r15 stack pointer
r15 stack pointer
...
@@ -195,11 +228,9 @@ extern int target_flags;
...
@@ -195,11 +228,9 @@ extern int target_flags;
/* 1 for registers that have pervasive standard uses
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
and are not available for the register allocator. */
/* r0 r1 r2 r3 r4 r5 r6 r7 r8
/* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 ap pr t gbr mh ml */
r9 r10 r11 r12 r13 r14 r15 ap pr t gbr mh ml */
#define FIXED_REGISTERS \
#define FIXED_REGISTERS \
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, \
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1}
0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1}
/* 1 for registers not available across function calls.
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
These must include the FIXED_REGISTERS and also any
...
@@ -208,11 +239,9 @@ extern int target_flags;
...
@@ -208,11 +239,9 @@ extern int target_flags;
and the register where structure-value addresses are passed.
and the register where structure-value addresses are passed.
Aside from that, you can include as many other registers as you like. */
Aside from that, you can include as many other registers as you like. */
/* r0 r1 r2 r3 r4 r5 r6 r7 r8
/* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 ap pr t gbr mh ml */
r9 r10 r11 r12 r13 r14 r15 ap pr t gbr mh ml */
#define CALL_USED_REGISTERS \
#define CALL_USED_REGISTERS \
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, \
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1}
0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}
/* Return number of consecutive hard regs needed starting at reg REGNO
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
to hold something of mode MODE.
...
@@ -252,7 +281,9 @@ extern int target_flags;
...
@@ -252,7 +281,9 @@ extern int target_flags;
/* Value should be nonzero if functions must have frame pointers.
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may be accessed
Zero means the frame pointer need not be set up (and parms may be accessed
via the stack pointer) in functions that seem suitable. */
via the stack pointer) in functions that seem suitable. */
#define FRAME_POINTER_REQUIRED 0
#define FRAME_POINTER_REQUIRED (get_frame_size() > 1000)
/* Definitions for register eliminations.
/* Definitions for register eliminations.
...
@@ -288,12 +319,10 @@ extern int target_flags;
...
@@ -288,12 +319,10 @@ extern int target_flags;
/* Register in which the static-chain is passed to a function. */
/* Register in which the static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 13
#define STATIC_CHAIN_REGNUM 13
/* If the structure value address is not passed in a register, define
/* The register in which a struct value address is passed */
this as an expression returning an RTX for the place
where the address is passed. If it returns 0, the address is
#define STRUCT_VALUE_REGNUM 3
passed as an "invisible" first argument. */
#define STRUCT_VALUE 0
/* Define the classes of registers for register constraints in the
/* Define the classes of registers for register constraints in the
...
@@ -372,7 +401,7 @@ extern int regno_reg_class[];
...
@@ -372,7 +401,7 @@ extern int regno_reg_class[];
/* The order in which register should be allocated. */
/* The order in which register should be allocated. */
#define REG_ALLOC_ORDER \
#define REG_ALLOC_ORDER \
{ 1,2,3,
0,4,5,6,7
,8,9,10,11,12,13,14,15,16,17,18,19,20,21}
{ 1,2,3,
7,4,5,6,0
,8,9,10,11,12,13,14,15,16,17,18,19,20,21}
/* The class value for index registers, and the one for base regs. */
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS R0_REGS
#define INDEX_REG_CLASS R0_REGS
...
@@ -392,13 +421,13 @@ extern enum reg_class reg_class_from_letter[];
...
@@ -392,13 +421,13 @@ extern enum reg_class reg_class_from_letter[];
C is the letter, and VALUE is a constant value.
C is the letter, and VALUE is a constant value.
Return 1 if VALUE is in the range specified by C.
Return 1 if VALUE is in the range specified by C.
I: arithmetic operand -127..128, as used in add, sub, etc
I: arithmetic operand -127..128, as used in add, sub, etc
L: logical operand 0..255, as used in a
d
d, or, etc.
L: logical operand 0..255, as used in a
n
d, or, etc.
M: constant 1
M: constant 1
K: shift operand 1,2,8 or 16 */
K: shift operand 1,2,8 or 16 */
#define CONST_OK_FOR_I(VALUE) ((
VALUE)>= -128 && (VALUE
) <= 127)
#define CONST_OK_FOR_I(VALUE) ((
(int)(VALUE))>= -128 && ((int)(VALUE)
) <= 127)
#define CONST_OK_FOR_L(VALUE) ((
VALUE)>= 0 && (VALUE
) <= 255)
#define CONST_OK_FOR_L(VALUE) ((
(int)(VALUE))>= 0 && ((int)(VALUE)
) <= 255)
#define CONST_OK_FOR_M(VALUE) ((VALUE)==1)
#define CONST_OK_FOR_M(VALUE) ((VALUE)==1)
#define CONST_OK_FOR_K(VALUE) ((VALUE)==1||(VALUE)==2||(VALUE)==8||(VALUE)==16)
#define CONST_OK_FOR_K(VALUE) ((VALUE)==1||(VALUE)==2||(VALUE)==8||(VALUE)==16)
...
@@ -422,7 +451,7 @@ extern enum reg_class reg_class_from_letter[];
...
@@ -422,7 +451,7 @@ extern enum reg_class reg_class_from_letter[];
In general this is just CLASS; but on some machines
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class. */
in some cases it is preferable to use a more restrictive class. */
#define PREFERRED_RELOAD_CLASS(X, CLASS)
(CLASS)
#define PREFERRED_RELOAD_CLASS(X, CLASS)
CLASS
/* Return the register class of a scratch register needed to copy IN into
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
or out of a register in CLASS in MODE. If it can be done directly,
...
@@ -605,19 +634,13 @@ extern int current_function_anonymous_args;
...
@@ -605,19 +634,13 @@ extern int current_function_anonymous_args;
current_function_anonymous_args = 1;
current_function_anonymous_args = 1;
/* Generate assembly output for the start of a function. */
#define FUNCTION_PROLOGUE(STREAM, SIZE) \
output_prologue ((STREAM), (SIZE))
/* Call the function profiler with a given profile label. */
/* Call the function profiler with a given profile label. */
#define FUNCTION_PROFILER(STREAM,LABELNO) \
#define FUNCTION_PROFILER(STREAM,LABELNO) \
{ \
{ \
fprintf(STREAM, "\tsts.l pr,@-r15\n"); \
fprintf(STREAM, " trapa #5\n"); \
fprintf(STREAM, "\tjsr\tmcount\n"); \
fprintf(STREAM, " .align 2\n"); \
fprintf(STREAM, "\tor r0,r0\n"); \
fprintf(STREAM, " .long LP%d\n", (LABELNO)); \
fprintf(STREAM, "\t.long\tLP%d\n", (LABELNO)); \
}
}
...
@@ -628,16 +651,11 @@ extern int current_function_anonymous_args;
...
@@ -628,16 +651,11 @@ extern int current_function_anonymous_args;
#define EXIT_IGNORE_STACK 0
#define EXIT_IGNORE_STACK 0
/* Generate the assembly code for function exit. */
/* Generate the assembly code for function exit
Just dump out any accumulated constant table.*/
#define FUNCTION_EPILOGUE(STREAM, SIZE) \
#define FUNCTION_EPILOGUE(STREAM, SIZE) \
output_epilogue ((STREAM), (SIZE))
dump_constants(0);
#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \
(get_attr_in_delay_slot(INSN) == IN_DELAY_SLOT_YES)
#define DELAY_SLOTS_FOR_EPILOGUE \
delay_slots_for_epilogue();
/* Output assembler code for a block containing the constant parts
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.
of a trampoline, leaving space for the variable parts.
...
@@ -703,27 +721,19 @@ extern int current_function_anonymous_args;
...
@@ -703,27 +721,19 @@ extern int current_function_anonymous_args;
/* Maximum number of registers that can appear in a valid memory
/* Maximum number of registers that can appear in a valid memory
address. */
address. */
#define MAX_REGS_PER_ADDRESS
1
#define MAX_REGS_PER_ADDRESS
4
/* Recognize any constant value that is a valid address. */
/* Recognize any constant value that is a valid address. */
#define CONSTANT_ADDRESS_P(X) \
#define CONSTANT_ADDRESS_P(X) \
(GET_CODE (X) == LABEL_REF)
(GET_CODE (X) == LABEL_REF)
#if 0
|| GET_CODE (X) == SYMBOL_REF \
|| GET_CODE (X) == CONST_INT \
|| GET_CODE (X) == CONST)
#endif
/* Nonzero if the constant value X is a legitimate general operand.
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
On the SH, allow any
thing but a double */
On the SH, allow anything but a double */
#define LEGITIMATE_CONSTANT_P(X) \
#define LEGITIMATE_CONSTANT_P(X) (GET_CODE(X) != CONST_DOUBLE)
(GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode)
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
and check its validity for a certain class.
...
@@ -733,22 +743,30 @@ extern int current_function_anonymous_args;
...
@@ -733,22 +743,30 @@ extern int current_function_anonymous_args;
The symbol REG_OK_STRICT causes the latter definition to be used. */
The symbol REG_OK_STRICT causes the latter definition to be used. */
#ifndef REG_OK_STRICT
#ifndef REG_OK_STRICT
/* Nonzero if X is a hard reg that can be used as a base reg
/* Nonzero if X is a hard reg that can be used as a base reg
or if it is a pseudo reg. */
or if it is a pseudo reg. */
#define REG_OK_FOR_BASE_P(X) \
#define REG_OK_FOR_BASE_P(X) \
(REGNO(X) <= 16 || REGNO
(X) >= FIRST_PSEUDO_REGISTER)
(REGNO (X) <= 16 || REGNO
(X) >= FIRST_PSEUDO_REGISTER)
/* Nonzero if X is a hard reg that can be used as an index
/* Nonzero if X is a hard reg that can be used as an index
or if it is a pseudo reg. */
or if it is a pseudo reg. */
#define REG_OK_FOR_INDEX_P(X) \
#define REG_OK_FOR_INDEX_P(X) \
(REGNO(X)==0||REGNO(X)>=FIRST_PSEUDO_REGISTER)
(REGNO (X) == 0 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
#define REG_OK_FOR_PRE_POST_P(X) (REGNO(X) <= 16)
#define REG_OK_FOR_PRE_POST_P(X) \
(REGNO (X) <= 16)
#else
#else
/* Nonzero if X is a hard reg that can be used as a base reg. */
/* 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_BASE_P(X) \
REGNO_OK_FOR_BASE_P (REGNO (X))
/* Nonzero if X is a hard reg that can be used as an index. */
/* 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))
#define REG_OK_FOR_INDEX_P(X) \
REGNO_OK_FOR_INDEX_P (REGNO (X))
#define REG_OK_FOR_PRE_POST_P(X) \
#define REG_OK_FOR_PRE_POST_P(X) \
(REGNO (X) <= 16 || (unsigned) reg_renumber[REGNO (X)] <=16)
(REGNO (X) <= 16 || (unsigned) reg_renumber[REGNO (X)] <=16)
#endif
#endif
...
@@ -759,6 +777,7 @@ extern int current_function_anonymous_args;
...
@@ -759,6 +777,7 @@ extern int current_function_anonymous_args;
that wants to use this address.
that wants to use this address.
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
#define BASE_REGISTER_RTX_P(X) \
#define BASE_REGISTER_RTX_P(X) \
(GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
(GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
...
@@ -777,14 +796,20 @@ extern int current_function_anonymous_args;
...
@@ -777,14 +796,20 @@ extern int current_function_anonymous_args;
--REG
--REG
*/
*/
/* A legitimate index for a QI or HI is 0, SI and above can be any
/* The SH allows a displacement in a QI or HI amode, but only when the
number 0..64 */
other operand is R0. GCC doesn't handle this very well, so we forgo
all of that.
A legitimate index for a QI or HI is 0, SI and above can be any
number 0..63 */
#define GO_IF_LEGITIMATE_INDEX(MODE, REGNO, OP, LABEL) \
#define GO_IF_LEGITIMATE_INDEX(MODE, REGNO, OP, LABEL) \
do { \
do { \
if (GET_CODE (OP) == CONST_INT) \
if (GET_CODE (OP) == CONST_INT) \
{ \
{ \
if (GET_MODE_SIZE (MODE) < 4 && INTVAL(OP) == 0)\
if (0&&GET_MODE_SIZE (MODE) == 2 && ((unsigned)INTVAL(OP)) <=30)\
goto LABEL; \
if (0&&GET_MODE_SIZE (MODE) == 1 && ((unsigned)INTVAL(OP)) <=15)\
goto LABEL; \
goto LABEL; \
if (GET_MODE_SIZE (MODE) >=4 \
if (GET_MODE_SIZE (MODE) >=4 \
&& ((unsigned)INTVAL(OP)) < 64) \
&& ((unsigned)INTVAL(OP)) < 64) \
...
@@ -793,7 +818,6 @@ extern int current_function_anonymous_args;
...
@@ -793,7 +818,6 @@ extern int current_function_anonymous_args;
} while(0)
} while(0)
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
{ \
{ \
if (BASE_REGISTER_RTX_P (X)) \
if (BASE_REGISTER_RTX_P (X)) \
...
@@ -802,14 +826,20 @@ extern int current_function_anonymous_args;
...
@@ -802,14 +826,20 @@ extern int current_function_anonymous_args;
&& GET_CODE (XEXP (X, 0)) == REG \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_PRE_POST_P (XEXP (X, 0))) \
&& REG_OK_FOR_PRE_POST_P (XEXP (X, 0))) \
goto LABEL; \
goto LABEL; \
else if (GET_CODE (X) == PLUS
)
\
else if (GET_CODE (X) == PLUS
|| GET_CODE(X) == LO_SUM)
\
{ \
{ \
rtx xop0 = XEXP(X,0); \
rtx xop0 = XEXP(X,0); \
rtx xop1 = XEXP(X,1); \
rtx xop1 = XEXP(X,1); \
if (
BASE_REGISTER_RTX_P (xop0))
\
if (
GET_MODE_SIZE(MODE) >= 4 && BASE_REGISTER_RTX_P (xop0))
\
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL); \
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL); \
else if (BASE_REGISTER_RTX_P (xop1))
\
if (GET_MODE_SIZE(MODE) >= 4 && BASE_REGISTER_RTX_P (xop1))
\
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \
if (GET_MODE_SIZE(MODE)<=4) { \
if(BASE_REGISTER_RTX_P(xop1) && \
INDEX_REGISTER_RTX_P(xop0)) goto LABEL; \
if(INDEX_REGISTER_RTX_P(xop1) && \
BASE_REGISTER_RTX_P(xop0)) goto LABEL; \
} \
} \
} \
else if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_DEC) \
else if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_DEC) \
&& GET_CODE (XEXP (X, 0)) == REG \
&& GET_CODE (XEXP (X, 0)) == REG \
...
@@ -926,17 +956,21 @@ extern int current_function_anonymous_args;
...
@@ -926,17 +956,21 @@ extern int current_function_anonymous_args;
if (CONST_OK_FOR_I (INTVAL(RTX))) \
if (CONST_OK_FOR_I (INTVAL(RTX))) \
return 1; \
return 1; \
else \
else \
return
5
; \
return
8
; \
case CONST: \
case CONST: \
case LABEL_REF: \
case LABEL_REF: \
case SYMBOL_REF: \
case SYMBOL_REF: \
return
6
; \
return
5
; \
case CONST_DOUBLE: \
case CONST_DOUBLE: \
return 10;
return 10;
#define RTX_COSTS(X, CODE, OUTER_CODE) \
#define RTX_COSTS(X, CODE, OUTER_CODE) \
case MULT: \
case MULT: \
return COSTS_N_INSNS (TARGET_HAS_MULSI3 ? 2 : 20); \
return COSTS_N_INSNS (multcosts (X)); \
case ASHIFT: \
case ASHIFTRT: \
case LSHIFT: \
return COSTS_N_INSNS (shiftcosts (X)) ; \
case DIV: \
case DIV: \
case UDIV: \
case UDIV: \
case MOD: \
case MOD: \
...
@@ -954,14 +988,18 @@ extern int current_function_anonymous_args;
...
@@ -954,14 +988,18 @@ extern int current_function_anonymous_args;
*/
*/
#define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \
#define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \
((DSTCLASS ==T_REGS) ? 10 : 2
)
((DSTCLASS == T_REGS) ? 10 : 1
)
/* Assembler output control */
/* Assembler output control */
/* The text to go at the start of the assembler file */
/* The text to go at the start of the assembler file */
#define ASM_FILE_START(STREAM) \
#define ASM_FILE_START(STREAM) \
fprintf (STREAM,"! GCC for the Hitachi Super-H\n"); \
output_file_start (STREAM, f_options, sizeof f_options / sizeof f_options[0], \
output_file_directive (STREAM, main_input_filename);
W_options, sizeof W_options / sizeof W_options[0]);
#define ASM_FILE_END(STREAM) \
dump_constants(0);
#define ASM_APP_ON ""
#define ASM_APP_ON ""
#define ASM_APP_OFF ""
#define ASM_APP_OFF ""
...
@@ -971,8 +1009,77 @@ extern int current_function_anonymous_args;
...
@@ -971,8 +1009,77 @@ extern int current_function_anonymous_args;
/* Switch to the text or data segment. */
/* Switch to the text or data segment. */
#define TEXT_SECTION_ASM_OP ".text"
#define TEXT_SECTION_ASM_OP "\t.text"
#define DATA_SECTION_ASM_OP ".data"
#define DATA_SECTION_ASM_OP "\t.data"
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors\n"
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors\n"
#define EXTRA_SECTIONS in_ctors, in_dtors
#define EXTRA_SECTION_FUNCTIONS \
void \
ctors_section() \
{ \
if (in_section != in_ctors) \
{ \
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
in_section = in_ctors; \
} \
} \
void \
dtors_section() \
{ \
if (in_section != in_dtors) \
{ \
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
in_section = in_dtors; \
} \
}
#define ASM_OUTPUT_SECTION(file, nam) \
do { fprintf (file, "\t.section\t%s\n", nam); } while(0)
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { ctors_section(); fprintf(FILE,"\t.long\t_%s\n", NAME); } while (0)
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { dtors_section(); fprintf(FILE,"\t.long\t_%s\n", NAME); } while (0)
#undef DO_GLOBAL_CTORS_BODY
#define DO_GLOBAL_CTORS_BODY \
{ \
typedef (*pfunc)(); \
extern pfunc __ctors[]; \
extern pfunc __ctors_end[]; \
pfunc *p; \
for (p = __ctors; p < __ctors_end; p++) \
{ \
(*p)(); \
} \
}
#undef DO_GLOBAL_DTORS_BODY
#define DO_GLOBAL_DTORS_BODY \
{ \
typedef (*pfunc)(); \
extern pfunc __dtors[]; \
extern pfunc __dtors_end[]; \
pfunc *p; \
for (p = __dtors; p < __dtors_end; p++) \
{ \
(*p)(); \
} \
}
#define ASM_OUTPUT_REG_PUSH(file, v) \
fprintf (file, "\tmov.l r%s,-@r15\n", v);
#define ASM_OUTPUT_REG_POP(file, v) \
fprintf (file, "\tmov.l @r15+,r%s\n", v);
/* The assembler's names for the registers. RFP need not always be used as
/* The assembler's names for the registers. RFP need not always be used as
the Real framepointer; it can also be used as a normal general register.
the Real framepointer; it can also be used as a normal general register.
...
@@ -1049,21 +1156,19 @@ extern int current_function_anonymous_args;
...
@@ -1049,21 +1156,19 @@ extern int current_function_anonymous_args;
/* This is how to output an assembler line defining a `double' */
/* This is how to output an assembler line defining a `double' */
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
{ \
do { char dstr[30]; \
long t[2]; \
REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \
fprintf (FILE, "\t.double %s\n", dstr); \
fprintf (FILE, "\t.long\t0x%lx\n\t.long\t0x%lx\n", \
} while (0)
t[0], t[1]); \
} \
/* This is how to output an assembler line defining a `float' constant. */
/* This is how to output an assembler line defining a `float' constant. */
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
{
\
do { char dstr[30];
\
long t;
\
REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr);
\
REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);
\
fprintf (FILE, "\t.float %s\n", dstr);
\
fprintf (FILE, "\t.long\t0x%lx\n", t); \
} while (0)
} \
#define ASM_OUTPUT_INT(STREAM, EXP) \
#define ASM_OUTPUT_INT(STREAM, EXP) \
(fprintf (STREAM, "\t.long\t"), \
(fprintf (STREAM, "\t.long\t"), \
...
@@ -1136,7 +1241,7 @@ extern int current_function_anonymous_args;
...
@@ -1136,7 +1241,7 @@ extern int current_function_anonymous_args;
#define PRINT_OPERAND_ADDRESS(STREAM,X) print_operand_address (STREAM, X)
#define PRINT_OPERAND_ADDRESS(STREAM,X) print_operand_address (STREAM, X)
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '!')
((CHAR)
=='.' || (CHAR)
== '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '!')
/* Define the information needed to generate branch insns. This is stored
/* Define the information needed to generate branch insns. This is stored
...
@@ -1147,7 +1252,7 @@ extern struct rtx_def *sh_compare_op0;
...
@@ -1147,7 +1252,7 @@ extern struct rtx_def *sh_compare_op0;
extern
struct
rtx_def
*
sh_compare_op1
;
extern
struct
rtx_def
*
sh_compare_op1
;
extern
struct
rtx_def
*
prepare_scc_operands
();
extern
struct
rtx_def
*
prepare_scc_operands
();
extern
enum
attr_cpu
sh_cpu
;
/* target cpu */
/* Declare functions defined in sh.c and used in templates. */
/* Declare functions defined in sh.c and used in templates. */
...
@@ -1159,3 +1264,8 @@ extern char *output_movepcrel();
...
@@ -1159,3 +1264,8 @@ extern char *output_movepcrel();
#define ADJUST_INSN_LENGTH(insn, length) \
#define ADJUST_INSN_LENGTH(insn, length) \
adjust_insn_length (insn, insn_lengths)
adjust_insn_length (insn, insn_lengths)
gcc/config/sh/sh.md
View file @
b9654711
...
@@ -26,7 +26,12 @@
...
@@ -26,7 +26,12 @@
;; Attributes
;; Attributes
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_attr "type" "cbranch,ctable,jump,arith,other"
; Target CPU.
(define_attr "cpu" "sh0,sh1,sh2,sh3"
(const (symbol_ref "sh_cpu")))
(define_attr "type" "cbranch,ctable,jump,arith,other,load,store,move,smpy,dmpy,return,pload"
(const_string "other"))
(const_string "other"))
; If a conditional branch destination is within -100..100 bytes away
; If a conditional branch destination is within -100..100 bytes away
...
@@ -63,11 +68,23 @@
...
@@ -63,11 +68,23 @@
(const_int 6))
(const_int 6))
] (const_int 2)))
] (const_int 2)))
;; (define_function_unit {name} {num-units} {n-users} {test}
;; {ready-delay} {issue-delay}
[
{conflict-list}
]
)
(define_function_unit "memory" 1 1 (eq_attr "type" "load") 1 0)
(define_function_unit "mpy" 1 1 (eq_attr "type" "smpy") 3 0)
(define_function_unit "mpy" 1 1 (eq_attr "type" "dmpy") 5 0)
(define_attr "needs_delay_slot" "yes,no"
(define_attr "needs_delay_slot" "yes,no"
(cond
[
(eq_attr "type" "jump") (const_string "yes")
]
(cond
[
(eq_attr "type" "jump") (const_string "yes")
(eq_attr "type" "return") (const_string "yes")]
(const_string "no")))
(const_string "no")))
(define_delay
(eq_attr "needs_delay_slot" "yes")
[
(eq_attr "in_delay_slot" "yes") (nil) (nil)
]
)
(define_attr "dump" "yes,no,must" (const_string "no"))
(define_attr "dump" "yes,no,must" (const_string "no"))
(define_attr "constneed" "yes,no" (const_string "no"))
(define_attr "constneed" "yes,no" (const_string "no"))
(define_attr "smallestsize" "" (const_int 2))
(define_attr "smallestsize" "" (const_int 2))
...
@@ -77,15 +94,13 @@
...
@@ -77,15 +94,13 @@
(define_attr "in_delay_slot" "maybe,yes,no"
(define_attr "in_delay_slot" "maybe,yes,no"
(cond
[
(eq_attr "type" "cbranch") (const_string "no")
(cond
[
(eq_attr "type" "cbranch") (const_string "no")
(eq_attr "type" "jump") (const_string "no")
(eq_attr "type" "jump") (const_string "no")
(eq_attr "type" "pload") (const_string "no")
(eq_attr "type" "return") (const_string "no")
(eq_attr "length" "2") (const_string "yes")
(eq_attr "length" "2") (const_string "yes")
(eq_attr "length" "4,6,8,10,12") (const_string "no")
(eq_attr "length" "4,6,8,10,12") (const_string "no")
] (const_string "yes")))
] (const_string "yes")))
(define_delay (eq_attr "needs_delay_slot" "yes")
[
(eq_attr "in_delay_slot" "yes") (nil) (nil)
]
)
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; SImode signed integer comparisons
;; SImode signed integer comparisons
...
@@ -233,11 +248,13 @@
...
@@ -233,11 +248,13 @@
(set_attr "type" "arith")])
(set_attr "type" "arith")])
(define_insn "subsi3"
(define_insn "subsi3"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
[
(set (match_operand:SI 0 "arith_reg_operand" "=r
,r
")
(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
(minus:SI (match_operand:SI 1 "arith_reg_operand" "0
,0
")
(match_operand:SI 2 "arith_
reg_operand" "r
")))]
(match_operand:SI 2 "arith_
operand" "r,I
")))]
""
""
"sub %2,%0"
"@
sub %2,%0
add %M2,%0"
[
(set_attr "type" "arith")
]
)
[
(set_attr "type" "arith")
]
)
...
@@ -253,7 +270,8 @@
...
@@ -253,7 +270,8 @@
(zero_extend:SI
(zero_extend:SI
(match_operand:HI 2 "arith_reg_operand" "r"))))]
(match_operand:HI 2 "arith_reg_operand" "r"))))]
""
""
"mulu %2,%1")
"mulu %2,%1"
[
(set_attr "type" "smpy")
]
)
(define_insn ""
(define_insn ""
[
(set (reg:SI 21)
[
(set (reg:SI 21)
...
@@ -262,7 +280,8 @@
...
@@ -262,7 +280,8 @@
(sign_extend:SI
(sign_extend:SI
(match_operand:HI 2 "arith_reg_operand" "r"))))]
(match_operand:HI 2 "arith_reg_operand" "r"))))]
""
""
"muls %2,%1")
"muls %2,%1"
[
(set_attr "type" "smpy")
]
)
(define_expand "mulhisi3"
(define_expand "mulhisi3"
[
(set (reg:SI 21)
[
(set (reg:SI 21)
...
@@ -286,61 +305,6 @@
...
@@ -286,61 +305,6 @@
""
""
"")
"")
(define_insn ""
[
(set (reg:SI 21)
(mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
(match_operand:SI 2 "arith_reg_operand" "r")))]
"TARGET_HAS_MULSI3"
"muls.l %2,%1")
(define_expand "mulsi3"
[
(set (reg:SI 21)
(mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
(match_operand:SI 2 "arith_reg_operand" "r")))
(set (match_operand:SI 0 "arith_reg_operand" "=r")
(reg:SI 20))]
"TARGET_HAS_MULSI3"
"")
(define_insn ""
[
(set (reg:DI 20)
(mult:DI (sign_extend:DI
(match_operand:SI 1 "arith_reg_operand" "r"))
(sign_extend:DI
(match_operand:SI 2 "arith_reg_operand" "r"))))]
"TARGET_HAS_MULSI3"
"dmuls.l %2,%1")
(define_expand "mulsidi3"
[
(set (reg:DI 20)
(mult:DI (sign_extend:DI
(match_operand:SI 1 "arith_reg_operand" "r"))
(sign_extend:DI
(match_operand:SI 2 "arith_reg_operand" "r"))))
(set (match_operand:DI 0 "arith_reg_operand" "=r")
(reg:DI 20))]
"TARGET_HAS_MULSI3"
"")
(define_insn ""
[
(set (reg:DI 20)
(mult:DI (zero_extend:DI
(match_operand:SI 1 "arith_reg_operand" "r"))
(zero_extend:DI
(match_operand:SI 2 "arith_reg_operand" "r"))))]
"TARGET_HAS_MULSI3"
"dmulu.l %2,%1")
(define_expand "umulsidi3"
[
(set (reg:DI 20)
(mult:DI (zero_extend:DI
(match_operand:SI 1 "arith_reg_operand" "r"))
(zero_extend:DI
(match_operand:SI 2 "arith_reg_operand" "r"))))
(set (match_operand:DI 0 "arith_reg_operand" "=r")
(reg:DI 20))]
"TARGET_HAS_MULSI3"
"")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Logical operations
;; Logical operations
...
@@ -374,35 +338,71 @@
...
@@ -374,35 +338,71 @@
;; Shifts and rotates
;; Shifts and rotates
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn "rotlsi3_k"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
(rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
(const_int 1)))
(clobber (reg:SI 18))]
""
"rotl %0")
(define_expand "rotlsi3"
[
(parallel
[
(set (match_operand:SI 0 "arith_reg_operand" "")
(rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "immediate_operand" "")))
(clobber (reg:SI 18))])]
""
"{ if (GET_CODE(operands
[
2
]
) != CONST_INT || INTVAL(operands
[
2
]
) != 1) FAIL;}")
(define_insn "rotrsi3_k"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0")
(const_int 1)))
(clobber (reg:SI 18))]
""
"rotr %0")
(define_expand "rotrsi3"
[
(parallel
[
(set (match_operand:SI 0 "arith_reg_operand" "")
(rotatert:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "immediate_operand" "")))
(clobber (reg:SI 18))])]
""
"{ if (GET_CODE(operands
[
2
]
) != CONST_INT || INTVAL(operands
[
2
]
) != 1) FAIL;}")
(define_insn "ashlsi3_k"
(define_insn "ashlsi3_k"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
[
(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
(match_operand:SI 2 "immediate_operand" "L,n")))]
(match_operand:SI 2 "immediate_operand" "K,n")))
(clobber (reg:SI 18))]
""
""
"
*
return output_shift(
\"
shll
\"
, operands
[
0
]
, operands
[
2
]
);"
"
*
return output_shift(
\"
shll
\"
, operands
[
0
]
, operands
[
2
]
, ASHIFT
);"
[
(set_attr "length" "2,12")
[
(set_attr "length" "2,12")
(set_attr "in_delay_slot" "yes,no")
(set_attr "in_delay_slot" "yes,no")
(set_attr "type" "arith")])
(set_attr "type" "arith")])
(define_expand "ashlsi3"
(define_expand "ashlsi3"
[
(set (match_operand:SI 0 "arith_reg_operand" "")
[
(
parallel
[
(
set (match_operand:SI 0 "arith_reg_operand" "")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "immediate_operand" "")))]
(match_operand:SI 2 "immediate_operand" "")))
(clobber (reg:SI 18))])]
""
""
"if (!ok_shift_value(operands
[
2
]
)) FAIL;")
"if (!ok_shift_value(operands
[
2
]
, ASHIFT
)) FAIL;")
(define_insn "ashrsi3_k"
(define_insn "ashrsi3_k"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(const_int 1)))]
(const_int 1)))
(clobber (reg:SI 18))]
""
""
"shar %0"
"shar %0"
[
(set_attr "type" "arith")
]
)
[
(set_attr "type" "arith")
]
)
(define_expand "ashrsi3"
(define_expand "ashrsi3"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
[
(
parallel
[
(
set (match_operand:SI 0 "arith_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
(match_operand:SI 2 "nonmemory_operand" "M")))]
(match_operand:SI 2 "nonmemory_operand" "M")))
(clobber (reg:SI 18))])]
""
""
"
"
{
{
...
@@ -412,19 +412,21 @@
...
@@ -412,19 +412,21 @@
")
")
(define_insn "lshrsi3_k"
(define_insn "lshrsi3_k"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
[
(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
(match_operand:SI 2 "immediate_operand" "L")))]
(match_operand:SI 2 "immediate_operand" "K,n")))
(clobber (reg:SI 18))]
""
""
"
*
return output_shift (
\"
shlr
\"
, operands
[
0
]
, operands
[
2
]
);"
"
*
return output_shift (
\"
shlr
\"
, operands
[
0
]
, operands
[
2
]
, LSHIFTRT
);"
[
(set_attr "length" "12")
[
(set_attr "length" "
2,
12")
(set_attr "in_delay_slot" "no")
(set_attr "in_delay_slot" "
yes,
no")
(set_attr "type" "arith")])
(set_attr "type" "arith")])
(define_expand "lshrsi3"
(define_expand "lshrsi3"
[
(set (match_operand:SI 0 "arith_reg_operand" "")
[
(
parallel
[
(
set (match_operand:SI 0 "arith_reg_operand" "")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
(match_operand:SI 2 "nonmemory_operand" "")))
(clobber (reg:SI 18))])]
""
""
"if (!ok_shift_value (operands
[
2
]
)) FAIL; ")
"if (!ok_shift_value (operands
[
2
]
)) FAIL; ")
...
@@ -574,55 +576,99 @@
...
@@ -574,55 +576,99 @@
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn ""
(define_insn ""
[
(set (match_operand:SI 0 "push_operand" "=<")
[
(set (match_operand:SI 0 "push_operand" "=<
,<
")
(match_operand:SI 1 "arith_reg_operand" "r"))]
(match_operand:SI 1 "arith_reg_operand" "r
,l
"))]
""
""
"mov.l %1,%0")
"@
mov.l %1,%0
sts.l pr,%0"
[
(set_attr "type" "store")
]
)
(define_insn "
movsi_pcrel
"
(define_insn ""
[
(set
(match_operand:SI 0 "arith_reg_operand" "=r
")
[
(set
(match_operand:SI 0 "arith_reg_operand" "=r,l
")
(match_operand:SI 1 "
hard_immediate_operand" "i
"))]
(match_operand:SI 1 "
pop_operand" "=>,>
"))]
""
""
"
*
return output_movepcrel (insn, operands, SImode);"
"@
[
(set_attr "length" "2")
mov.l %1,%0
(set_attr "in_delay_slot" "no")
lds.l %1,pr"
(set_attr "constneed" "yes")
[
(set_attr "type" "load,pload")
]
)
(set_attr "smallestsize" "2")
(set_attr "largestsize" "8")])
(define_insn "push"
[
(set (mem:SI (pre_dec:SI (reg:SI 15)))
(match_operand:SI 0 "register_operand" "r,l"))]
""
"@
mov.l %0,@-r15
sts.l pr,@-r15")
(define_insn "pop"
[
(set (match_operand:SI 0 "register_operand" "=r,l")
(mem:SI (post_inc:SI (reg:SI 15))))]
""
"@
mov.l @r15+,%0
lds.l @r15+,pr"
[
(set_attr "type" "load,pload")
]
)
; some constants are easier to generate with alu operations
; rather than loading from memory
(define_split
[
(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "painful_immediate_operand" "i"))]
""
[
(set (match_dup 0) (const_int 127))
(set (match_dup 0) (plus:SI (match_dup 0)
(match_dup 2)))]
"operands
[
2
]
= GEN_INT (INTVAL(operands
[
1
]
) - 127);" )
(define_insn "movsi_i"
(define_insn "movsi_i"
[
(set (match_operand:SI 0 "general_operand" "=r,r,r,m,l,r,r,r,t")
[
(set (match_operand:SI 0 "general_operand" "=r,r,r,m,l,r,r,r,t
,x
")
(match_operand:SI 1 "general_
operand" "r,I,m,r,r,l,t,x
,r"))]
(match_operand:SI 1 "general_
movsrc_operand" "r,I,m,r,r,l,t,x,r
,r"))]
""
""
"@
"@
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov.l %1,%0
mov.l %1,%0
mov.l %1,%0
mov.l %1,%0
mov
%1,%0
lds
%1,%0
mov
%1,%0
sts
%1,%0
movt %0
movt %0
sts %1,%0
sts %1,%0
tst %1,%1
\;
bt T%
*\;bra F%*
\;
sett
\;
T%
*:clrt\;F%*
:%^"
tst %1,%1
\;
bt T%
*\;bra F%*
\;
sett
\;
T%
*:clrt\;F%*
:%^
[
(set_attr "length" "2,2,2,2,2,2,2,2,10")
]
)
lds %1,%0"
[
(set_attr "length" "2,2,2,2,2,2,2,2,10,2")
(set_attr "type" "move,move,load,pload,move,move,move,move,move,move")])
(define_insn "movsi_pcrel"
[
(set (match_operand:SI 0 "arith_reg_operand" "=r")
(match_operand:SI 1 "hard_immediate_operand" "i"))]
""
"
*
return output_movepcrel (insn, operands, SImode);"
[
(set_attr "length" "2")
(set_attr "in_delay_slot" "no")
(set_attr "constneed" "yes")
(set_attr "smallestsize" "2")
(set_attr "largestsize" "8")
(set_attr "type" "load")])
(define_expand "movsi"
(define_expand "movsi"
[
(set (match_operand:SI 0 "general_operand" "")
[
(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
(match_operand:SI 1 "general_operand" ""))]
""
""
"{
prepare_move_operands(operands, SImode)
; } ")
"{
if(prepare_move_operands(operands, SImode)) DONE
; } ")
(define_insn "movqi_i"
(define_insn "movqi_i"
[
(set (match_operand:QI 0 "general_operand" "=r,r,
z
,m,r,m,r,r")
[
(set (match_operand:QI 0 "general_operand" "=r,r,
r
,m,r,m,r,r")
(match_operand:QI 1 "general_operand" "r,n,m,
z
,m,r,x,t"))]
(match_operand:QI 1 "general_operand" "r,n,m,
r
,m,r,x,t"))]
""
""
"@
"@
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov.b %1,%0
!4
mov.b %1,%0
mov.b %1,%0
!5
mov.b %1,%0
mov.b %1,%0
!6
mov.b %1,%0
mov.b %1,%0
! 7
mov.b %1,%0
sts %1,%0
sts %1,%0
movt %0")
movt %0")
...
@@ -641,7 +687,8 @@
...
@@ -641,7 +687,8 @@
(set_attr "in_delay_slot" "no")
(set_attr "in_delay_slot" "no")
(set_attr "constneed" "yes")
(set_attr "constneed" "yes")
(set_attr "smallestsize" "2")
(set_attr "smallestsize" "2")
(set_attr "largestsize" "8")])
(set_attr "largestsize" "8")
(set_attr "type" "load")])
(define_insn "movhi_i"
(define_insn "movhi_i"
[
(set (match_operand:HI 0 "general_operand" "=r,r,m,z,m,r,r")
[
(set (match_operand:HI 0 "general_operand" "=r,r,m,z,m,r,r")
...
@@ -654,7 +701,8 @@
...
@@ -654,7 +701,8 @@
mov.w %1,%0
mov.w %1,%0
mov.w %1,%0
mov.w %1,%0
sts %1,%0
sts %1,%0
movt %0")
movt %0"
[
(set_attr "type" "move,load,store,load,store,move,move")
]
)
(define_expand "movhi"
(define_expand "movhi"
[
(set (match_operand:HI 0 "general_operand" "")
[
(set (match_operand:HI 0 "general_operand" "")
...
@@ -667,7 +715,8 @@
...
@@ -667,7 +715,8 @@
(match_operand:DI 1 "arith_reg_operand" "r"))]
(match_operand:DI 1 "arith_reg_operand" "r"))]
""
""
"mov.l %R1,%0
\;
mov.l %1,%0"
"mov.l %R1,%0
\;
mov.l %1,%0"
[
(set_attr "length" "4")
]
)
[
(set_attr "length" "4")
(set_attr "type" "store")])
(define_insn "movdi_pcrel"
(define_insn "movdi_pcrel"
[
(set (match_operand:DI 0 "arith_reg_operand" "=r")
[
(set (match_operand:DI 0 "arith_reg_operand" "=r")
...
@@ -679,14 +728,17 @@
...
@@ -679,14 +728,17 @@
(set_attr "constneed" "yes")
(set_attr "constneed" "yes")
(set_attr "smallestsize" "4")
(set_attr "smallestsize" "4")
(set_attr "constantsize" "8")
(set_attr "constantsize" "8")
(set_attr "largestsize" "18")])
(set_attr "largestsize" "18")
(set_attr "type" "load")])
(define_insn "movdi_k"
(define_insn "movdi_k"
[
(set (match_operand:DI 0 "general_operand" "=r,r,m,r,r,m,r")
[
(set (match_operand:DI 0 "general_operand" "=r,r,m,r,r,m,r")
(match_operand:DI 1 "general_operand" "r,m,r,I,m,r,x"))]
(match_operand:DI 1 "general_operand" "r,m,r,I,m,r,x"))]
""
""
"
*
return output_movedouble(operands, DImode);"
"
*
return output_movedouble(operands, DImode);"
[
(set_attr "length" "4")
]
)
[
(set_attr "length" "4")
(set_attr "type" "move,load,store,move,load,store,load")])
(define_expand "movdi"
(define_expand "movdi"
[
(set (match_operand:DI 0 "general_operand" "")
[
(set (match_operand:DI 0 "general_operand" "")
...
@@ -699,7 +751,8 @@
...
@@ -699,7 +751,8 @@
(match_operand:DF 1 "arith_reg_operand" "r"))]
(match_operand:DF 1 "arith_reg_operand" "r"))]
""
""
"mov.l %R1,%0
\;
mov.l %1,%0"
"mov.l %R1,%0
\;
mov.l %1,%0"
[
(set_attr "length" "4")
]
)
[
(set_attr "length" "4")
(set_attr "type" "store")])
(define_insn "movdf_pcrel"
(define_insn "movdf_pcrel"
[
(set (match_operand:DF 0 "arith_reg_operand" "=r")
[
(set (match_operand:DF 0 "arith_reg_operand" "=r")
...
@@ -711,14 +764,16 @@
...
@@ -711,14 +764,16 @@
(set_attr "constneed" "yes")
(set_attr "constneed" "yes")
(set_attr "smallestsize" "4")
(set_attr "smallestsize" "4")
(set_attr "constantsize" "8")
(set_attr "constantsize" "8")
(set_attr "largestsize" "18")])
(set_attr "largestsize" "18")
(set_attr "type" "load")])
(define_insn "movdf_k"
(define_insn "movdf_k"
[
(set (match_operand:DF 0 "general_operand" "=r,r,m")
[
(set (match_operand:DF 0 "general_operand" "=r,r,m")
(match_operand:DF 1 "general_operand" "r,m,r"))]
(match_operand:DF 1 "general_operand" "r,m,r"))]
""
""
"
*
return output_movedouble(operands, DFmode);"
"
*
return output_movedouble(operands, DFmode);"
[
(set_attr "length" "4")
]
)
[
(set_attr "length" "4")
(set_attr "type" "move,load,store")])
(define_expand "movdf"
(define_expand "movdf"
[
(set (match_operand:DF 0 "general_operand" "")
[
(set (match_operand:DF 0 "general_operand" "")
...
@@ -730,7 +785,8 @@
...
@@ -730,7 +785,8 @@
[
(set (match_operand:SF 0 "push_operand" "=<")
[
(set (match_operand:SF 0 "push_operand" "=<")
(match_operand:SF 1 "arith_reg_operand" "r"))]
(match_operand:SF 1 "arith_reg_operand" "r"))]
""
""
"mov.l %1,%0")
"mov.l %1,%0"
[
(set_attr "type" "store")
]
)
(define_insn "movsf_pcrel"
(define_insn "movsf_pcrel"
[
(set (match_operand:SF 0 "arith_reg_operand" "=r")
[
(set (match_operand:SF 0 "arith_reg_operand" "=r")
...
@@ -741,7 +797,8 @@
...
@@ -741,7 +797,8 @@
(set_attr "in_delay_slot" "no")
(set_attr "in_delay_slot" "no")
(set_attr "constneed" "yes")
(set_attr "constneed" "yes")
(set_attr "smallestsize" "2")
(set_attr "smallestsize" "2")
(set_attr "largestsize" "8")])
(set_attr "largestsize" "8")
(set_attr "type" "load")])
(define_insn "movsf_i"
(define_insn "movsf_i"
[
(set (match_operand:SF 0 "general_operand" "=r,r,r,m,l,r,m,r")
[
(set (match_operand:SF 0 "general_operand" "=r,r,r,m,l,r,m,r")
...
@@ -752,10 +809,11 @@
...
@@ -752,10 +809,11 @@
mov %1,%0
mov %1,%0
mov.l %1,%0
mov.l %1,%0
mov.l %1,%0
mov.l %1,%0
lds %1,%0
sts %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0"
mov %1,%0
[
(set_attr "type" "move,move,load,store,move,move,move,move")
]
)
mov %1,%0")
(define_expand "movsf"
(define_expand "movsf"
[
(set (match_operand:SF 0 "general_operand" "")
[
(set (match_operand:SF 0 "general_operand" "")
...
@@ -1037,7 +1095,7 @@
...
@@ -1037,7 +1095,7 @@
[
(set (pc)
[
(set (pc)
(match_operand:SI 0 "arith_reg_operand" "r"))]
(match_operand:SI 0 "arith_reg_operand" "r"))]
""
""
"jmp @%0"
"jmp @%0
%#
"
[
(set_attr "needs_delay_slot" "yes")
[
(set_attr "needs_delay_slot" "yes")
(set_attr "in_delay_slot" "no")
(set_attr "in_delay_slot" "no")
(set_attr "length" "4")])
(set_attr "length" "4")])
...
@@ -1065,6 +1123,31 @@
...
@@ -1065,6 +1123,31 @@
(set_attr "type" "jump")
(set_attr "type" "jump")
(set_attr "dump" "no")])
(set_attr "dump" "no")])
(define_insn "return"
[
(return)
]
"reload_completed"
"rts %#"
[
(set_attr "type" "return")
(set_attr "needs_delay_slot" "yes")
(set_attr "dump" "yes")])
(define_expand "prologue"
[
(const_int 0)
]
""
"sh_expand_prologue (); DONE;")
(define_expand "epilogue"
[
(return)
]
""
"sh_expand_epilogue ();")
(define_insn "blockage"
[
(unspec_volatile [(const_int 0)
]
0)]
""
""
[
(set_attr "length" "0")
]
)
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Scc instructions
;; Scc instructions
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
...
@@ -1136,6 +1219,9 @@
...
@@ -1136,6 +1219,9 @@
""
""
"operands
[
1
]
= prepare_scc_operands (EQ);")
"operands
[
1
]
= prepare_scc_operands (EQ);")
; these patterns give better code then gcc invents if
; left to its own devices
(define_insn "anddi3"
(define_insn "anddi3"
[
(set (match_operand:DI 0 "arith_reg_operand" "=r")
[
(set (match_operand:DI 0 "arith_reg_operand" "=r")
(and:DI (match_operand:DI 1 "arith_reg_operand" "%0")
(and:DI (match_operand:DI 1 "arith_reg_operand" "%0")
...
@@ -1174,63 +1260,13 @@
...
@@ -1174,63 +1260,13 @@
""
""
"
"
{
{
rtx src_ptr = copy_to_mode_reg(Pmode,XEXP(operands
[
1
]
, 0));
rtx dest_mem = operands
[
0
]
;
rtx dst_ptr = copy_to_mode_reg(Pmode,XEXP(operands
[
0
]
, 0));
rtx src_mem = operands
[
1
]
;
int maxsize = GET_CODE (operands
[
2
]
) == CONST_INT
operands
[
0
]
= copy_to_mode_reg (SImode, XEXP (operands
[
0
]
, 0));
? MAX (INTVAL (operands
[
2
]
), INTVAL (operands
[
3
]
)) : 1;
operands
[
1
]
= copy_to_mode_reg (SImode, XEXP (operands
[
1
]
, 0));
enum machine_mode mode =
expand_block_move (dest_mem, src_mem, operands);
(maxsize >= 4) ? SImode :
(maxsize >= 2) ? HImode :
QImode;
rtx tmpreg = gen_reg_rtx(mode);
rtx increment = GEN_INT(GET_MODE_SIZE(mode));
rtx length = operands
[
2
]
;
rtx label = gen_label_rtx();
rtx end_src_ptr = gen_reg_rtx(Pmode);
/
* If done first rtl emmiting stage we can't generate a loop *
/
/
*
if (!rtx_equal_function_value_matters)
FAIL;
*
/
if (GET_CODE (length) != CONST_INT)
length = convert_to_mode (Pmode, length, 1);
if (!arith_operand (length, SImode))
length = force_reg (SImode, length);
emit_insn(gen_rtx(SET,
VOIDmode,
end_src_ptr,
gen_rtx(PLUS, Pmode, src_ptr, length)));
emit_label(label);
emit_move_insn(tmpreg, gen_rtx(MEM, mode, src_ptr));
emit_insn(gen_rtx(SET,
VOIDmode,
src_ptr,
gen_rtx(PLUS, Pmode, src_ptr, increment)));
emit_move_insn(gen_rtx(MEM, mode, dst_ptr), tmpreg);
emit_insn(gen_rtx(SET,
VOIDmode,
dst_ptr,
gen_rtx(PLUS, Pmode, dst_ptr, increment)));
sh_compare_op0 = src_ptr;
sh_compare_op1 = end_src_ptr;
emit_insn(gen_cmpeqsi_t(src_ptr, end_src_ptr));
emit_jump_insn(gen_bne(label));
emit_insn(gen_rtx(SET, VOIDmode, dst_ptr, dst_ptr));
DONE;
DONE;
}
}")
")
...
@@ -1262,4 +1298,41 @@
...
@@ -1262,4 +1298,41 @@
"REGNO(operands
[
1
]
) != REGNO(operands
[
0
]
)"
"REGNO(operands
[
1
]
) != REGNO(operands
[
0
]
)"
"mov.l @%1+,%0")
"mov.l @%1+,%0")
(define_peephole
[
(set (match_operand:QI 0 "register_operand" "=r")
(match_operand:QI 1 "general_operand" "g"))
(set (match_operand:SI 2 "register_operand" "=r")
(sign_extend:SI (match_dup 0)))]
"REGNO(operands
[
0
]
) == REGNO(operands
[
2
]
)"
"mov.b %1,%0")
(define_peephole
[
(set (match_operand:QI 0 "register_operand" "=r")
(match_operand:QI 1 "general_operand" "g"))
(set (match_operand:SI 2 "register_operand" "=r")
(sign_extend:SI (match_dup 0)))]
"REGNO(operands
[
0
]
) != REGNO(operands
[
2
]
)
&& dead_or_set_p (insn, operands
[
0
]
)"
"mov.b %1,%2")
; notice when a mov.b could be done with a displacement
(define_peephole
[
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 0)
(match_operand:SI 1 "byte_index_operand" "i")))
(set (mem:QI (match_dup 0)) (reg:QI 0))]
"dead_or_set_p(insn, operands
[
0
]
)"
"mov.b r0,@(%O1,%0)")
(define_peephole
[
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 0)
(match_operand:SI 1 "byte_index_operand" "i")))
(set (reg:QI 0) (mem:QI (match_dup 0)))]
"dead_or_set_p(insn, operands
[
0
]
)"
"mov.b @(%O1,%0),r0")
gcc/config/sh/t-sh
View file @
b9654711
LIBGCC1 = libgcc1.null
LIBGCC1 = libgcc1.null
T_CFLAGS = -DDONT_HAVE_STDIO -DDONT_HAVE_SETJMP -Dinhibit_libc
T_CFLAGS = -DDONT_HAVE_STDIO -DDONT_HAVE_SETJMP -Dinhibit_libc
LIBGCC2_CFLAGS=-g -fno-omit-frame-pointer -O2 $(GCC_CFLAGS)
LIBGCC2_CFLAGS=-g -O5 $(GCC_CFLAGS)
# These are really part of libgcc1, but this will cause them to be
# built correctly, so... [taken from t-ose68k]
LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
gcc/config/sh/xm-sh.h
View file @
b9654711
/* Configuration for GNU C-compiler for Hitachi SH.
/* Configuration for GNU C-compiler for Hitachi SH.
Copyright (C) 1993 Free Software Foundation, Inc.
Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
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
it under the terms of the GNU General Public License as published by
...
@@ -26,6 +26,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
...
@@ -26,6 +26,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define HOST_BITS_PER_INT 32
#define HOST_BITS_PER_INT 32
#define HOST_BITS_PER_LONG 32
#define HOST_BITS_PER_LONG 32
/* If compiled with GNU C, use the built-in alloca. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#endif
/* target machine dependencies.
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
#include "tm.h"
...
...
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