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
994fe660
Commit
994fe660
authored
Aug 11, 2001
by
Ulrich Weigand
Committed by
Ulrich Weigand
Aug 11, 2001
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Coding style cleanup.
From-SVN: r44811
parent
f314b9b1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
511 additions
and
301 deletions
+511
-301
gcc/ChangeLog
+6
-0
gcc/config/s390/linux.h
+3
-3
gcc/config/s390/s390-protos.h
+31
-45
gcc/config/s390/s390.c
+434
-221
gcc/config/s390/s390.h
+22
-24
gcc/config/s390/s390.md
+15
-3
gcc/config/s390/t-linux
+0
-5
No files found.
gcc/ChangeLog
View file @
994fe660
2001
-
08
-
11
Ulrich
Weigand
<
uweigand
@de
.
ibm
.
com
>
2001
-
08
-
11
Ulrich
Weigand
<
uweigand
@de
.
ibm
.
com
>
*
s390
.
c
,
s390
.
h
,
s390
.
md
,
s390
-
protos
.
h
,
linux
.
h
,
t
-
linux
:
Clean
up
code
:
add
missing
comments
and
prototypes
,
fix
warnings
,
remove
obsolete
code
,
fix
spacing
to
conform
to
coding
style
.
2001
-
08
-
11
Ulrich
Weigand
<
uweigand
@de
.
ibm
.
com
>
*
config
/
s390
/
s390
.
c
(
targetm
)
:
Define
TARGET_ASM_OPEN_PAREN
*
config
/
s390
/
s390
.
c
(
targetm
)
:
Define
TARGET_ASM_OPEN_PAREN
and
TARGET_ASM_CLOSE_PAREN
.
and
TARGET_ASM_CLOSE_PAREN
.
(
regclass_map
)
:
CC
register
belongs
to
class
NO_REGS
.
(
regclass_map
)
:
CC
register
belongs
to
class
NO_REGS
.
...
...
gcc/config/s390/linux.h
View file @
994fe660
...
@@ -154,7 +154,7 @@ do { fprintf ((FILE), "%s\t", ASM_QUAD); \
...
@@ -154,7 +154,7 @@ do { fprintf ((FILE), "%s\t", ASM_QUAD); \
#undef ASM_OUTPUT_INT
#undef ASM_OUTPUT_INT
#define ASM_OUTPUT_INT(FILE, VALUE) \
#define ASM_OUTPUT_INT(FILE, VALUE) \
do { fprintf (FILE, "%s\t", ASM_LONG); \
do { fprintf (FILE, "%s\t", ASM_LONG); \
output_addr_const (FILE,
(VALUE));
\
output_addr_const (FILE,
(VALUE));
\
putc ('\n',FILE); \
putc ('\n',FILE); \
} while (0)
} while (0)
...
@@ -163,7 +163,7 @@ do { fprintf (FILE, "%s\t", ASM_LONG); \
...
@@ -163,7 +163,7 @@ do { fprintf (FILE, "%s\t", ASM_LONG); \
#define ASM_OUTPUT_SHORT(FILE, VALUE) \
#define ASM_OUTPUT_SHORT(FILE, VALUE) \
( fprintf (FILE, "%s ", ASM_SHORT), \
( fprintf (FILE, "%s ", ASM_SHORT), \
output_addr_const (FILE,
(VALUE)),
\
output_addr_const (FILE,
(VALUE)),
\
putc ('\n',FILE))
putc ('\n',FILE))
#define ASM_OUTPUT_CHAR(FILE, VALUE) \
#define ASM_OUTPUT_CHAR(FILE, VALUE) \
...
@@ -284,7 +284,7 @@ do { \
...
@@ -284,7 +284,7 @@ do { \
/* This is how to output a command to make the user-level label named NAME
/* This is how to output a command to make the user-level label named NAME
defined for reference from other files. */
defined for reference from other files. */
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
#define ASM_GLOBALIZE_LABEL(FILE,
NAME) \
(fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
(fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
...
...
gcc/config/s390/s390-protos.h
View file @
994fe660
...
@@ -19,70 +19,56 @@ along with GNU CC; see the file COPYING. If not, write to
...
@@ -19,70 +19,56 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
Boston, MA 02111-1307, USA. */
/* Declare functions in s390.c
and linux.c
*/
/* Declare functions in s390.c
.
*/
#ifdef RTX_CODE
extern
void
optimization_options
PARAMS
((
int
,
int
));
extern
int
s390_arg_frame_offset
PARAMS
((
void
));
#ifdef TREE_CODE
extern
void
s390_function_prologue
PARAMS
((
FILE
*
,
HOST_WIDE_INT
));
extern
void
init_cumulative_args
PARAMS
((
CUMULATIVE_ARGS
*
,
tree
,
rtx
,
int
));
extern
void
s390_function_epilogue
PARAMS
((
FILE
*
,
HOST_WIDE_INT
));
extern
void
s390_va_start
PARAMS
((
int
,
tree
,
rtx
));
#endif
/* TREE_CODE */
#ifdef RTX_CODE
extern
int
const0_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
const1_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
larl_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
fp_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
fp_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
s_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
s_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
larl_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_s_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_im8_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_s_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_s_or_im8_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_s_or_im8_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_x_or_im16_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_x_or_im16_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
r_or_im8_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
tmxx_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
bras_sym_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
bras_sym_operand
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
load_multiple_operation
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
load_multiple_operation
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
store_multiple_operation
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
store_multiple_operation
PARAMS
((
rtx
,
enum
machine_mode
));
extern
int
dead_p
PARAMS
((
rtx
,
rtx
));
extern
void
print_operand
PARAMS
((
FILE
*
,
rtx
,
char
));
extern
int
s390_match_ccmode
PARAMS
((
rtx
,
enum
machine_mode
));
extern
void
print_operand_address
PARAMS
((
FILE
*
,
rtx
));
extern
int
symbolic_reference_mentioned_p
PARAMS
((
rtx
));
extern
int
legitimate_pic_operand_p
PARAMS
((
rtx
));
extern
int
legitimate_pic_operand_p
PARAMS
((
rtx
));
extern
int
legitimate_constant_p
PARAMS
((
rtx
));
extern
int
legitimate_constant_p
PARAMS
((
rtx
));
extern
int
legitimate_address_p
PARAMS
((
enum
machine_mode
,
rtx
,
int
));
extern
rtx
legitimize_pic_address
PARAMS
((
rtx
,
rtx
));
extern
rtx
legitimize_address
PARAMS
((
rtx
,
rtx
,
enum
machine_mode
));
extern
void
emit_pic_move
PARAMS
((
rtx
*
,
enum
machine_mode
));
extern
int
unsigned_comparison_operator
PARAMS
((
rtx
));
extern
int
unsigned_jump_follows_p
PARAMS
((
rtx
));
extern
void
update_cc
PARAMS
((
rtx
,
rtx
));
extern
void
s390_initialize_trampoline
PARAMS
((
rtx
,
rtx
,
rtx
));
extern
void
s390_output_symbolic_const
PARAMS
((
FILE
*
,
rtx
));
extern
void
s390_output_symbolic_const
PARAMS
((
FILE
*
,
rtx
));
extern
void
print_operand_address
PARAMS
((
FILE
*
,
rtx
));
extern
void
print_operand
PARAMS
((
FILE
*
,
rtx
,
int
));
extern
int
s390_adjust_cost
PARAMS
((
rtx
,
rtx
,
rtx
,
int
));
extern
int
s390_adjust_cost
PARAMS
((
rtx
,
rtx
,
rtx
,
int
));
extern
int
s390_stop_dump_lit_p
PARAMS
((
rtx
));
extern
int
s390_stop_dump_lit_p
PARAMS
((
rtx
));
extern
void
s390_dump_literal_pool
PARAMS
((
rtx
,
rtx
));
extern
void
s390_dump_literal_pool
PARAMS
((
rtx
,
rtx
));
extern
void
s390_expand_eh_epilogue
PARAMS
((
rtx
,
rtx
,
rtx
));
extern
void
s390_trampoline_template
PARAMS
((
FILE
*
));
extern
void
s390_asm_output_external_libcall
PARAMS
((
FILE
*
,
rtx
));
extern
void
s390_initialize_trampoline
PARAMS
((
rtx
,
rtx
,
rtx
));
#endif
/* RTX_CODE */
#endif
/* RTX_CODE */
#ifdef TREE_CODE
#ifdef TREE_CODE
extern
void
s390_function_arg_advance
PARAMS
((
CUMULATIVE_ARGS
*
,
extern
void
s390_asm_output_pool_prologue
PARAMS
((
FILE
*
,
const
char
*
,
tree
,
int
));
enum
machine_mode
,
tree
,
int
));
extern
struct
rtx_def
*
s390_function_arg
PARAMS
((
CUMULATIVE_ARGS
*
,
enum
machine_mode
,
tree
,
int
));
extern
int
s390_function_arg_partial_nregs
PARAMS
((
CUMULATIVE_ARGS
*
,
enum
machine_mode
,
tree
,
int
));
extern
int
s390_function_arg_pass_by_reference
PARAMS
((
enum
machine_mode
,
tree
));
extern
int
s390_function_arg_pass_by_reference
PARAMS
((
enum
machine_mode
,
tree
));
extern
void
setup_incoming_varargs
PARAMS
((
CUMULATIVE_ARGS
*
,
extern
void
s390_function_arg_advance
PARAMS
((
CUMULATIVE_ARGS
*
,
enum
machine_mode
,
tree
,
int
));
enum
machine_mode
,
tree
,
extern
tree
s390_build_va_list
PARAMS
((
void
));
int
*
,
int
));
#ifdef RTX_CODE
extern
struct
rtx_def
*
s390_va_arg
PARAMS
((
tree
,
tree
));
extern
rtx
s390_function_arg
PARAMS
((
CUMULATIVE_ARGS
*
,
enum
machine_mode
,
tree
,
int
));
extern
union
tree_node
*
s390_build_va_list
PARAMS
((
void
));
extern
void
s390_va_start
PARAMS
((
int
,
tree
,
rtx
));
extern
void
s390_asm_output_pool_prologue
PARAMS
((
FILE
*
,
char
*
,
tree
,
int
));
extern
rtx
s390_va_arg
PARAMS
((
tree
,
tree
));
extern
void
encode_section_info
PARAMS
((
tree
));
#endif
/* RTX_CODE */
#endif
/* TREE_CODE */
#endif
/* TREE_CODE */
extern
void
s390_trampoline_template
PARAMS
((
FILE
*
));
extern
void
s390_function_prologue
PARAMS
((
FILE
*
,
HOST_WIDE_INT
));
extern
void
s390_function_epilogue
PARAMS
((
FILE
*
,
HOST_WIDE_INT
));
extern
void
s390_final_chunkify
PARAMS
((
int
));
extern
int
s390_arg_frame_offset
PARAMS
((
void
));
gcc/config/s390/s390.c
View file @
994fe660
...
@@ -70,6 +70,14 @@ int s390_function_count = 0;
...
@@ -70,6 +70,14 @@ int s390_function_count = 0;
emitted. */
emitted. */
rtx
s390_compare_op0
,
s390_compare_op1
;
rtx
s390_compare_op0
,
s390_compare_op1
;
/* Structure used to hold the components of a S/390 memory
address. A legitimate address on S/390 is of the general
form
base + index + displacement
where any of the components is optional.
base and index are registers of the class ADDR_REGS,
displacement is an unsigned 12-bit immediate constant. */
struct
s390_address
struct
s390_address
{
{
...
@@ -78,30 +86,41 @@ struct s390_address
...
@@ -78,30 +86,41 @@ struct s390_address
rtx
disp
;
rtx
disp
;
};
};
static
int
s390_match_ccmode_set
static
int
s390_match_ccmode_set
PARAMS
((
rtx
,
enum
machine_mode
));
PARAMS
((
rtx
set
,
int
req_mode
));
static
int
base_n_index_p
PARAMS
((
rtx
));
static
int
base_n_index_p
static
int
check_mode
PARAMS
((
rtx
,
enum
machine_mode
*
));
PARAMS
((
rtx
op
));
static
int
s390_decompose_address
PARAMS
((
rtx
,
struct
s390_address
*
,
int
));
static
int
check_mode
static
void
output_branch_condition
PARAMS
((
FILE
*
,
rtx
));
PARAMS
((
register
rtx
op
,
enum
machine_mode
*
mode
));
static
void
output_inverse_branch_condition
PARAMS
((
FILE
*
,
rtx
));
static
int
s390_decompose_address
static
int
reg_used_in_mem_p
PARAMS
((
int
,
rtx
));
PARAMS
((
register
rtx
addr
,
struct
s390_address
*
out
,
int
strict
));
static
int
addr_generation_dependency_p
PARAMS
((
rtx
,
rtx
));
static
int
check_mode
static
int
other_chunk
PARAMS
((
int
*
,
int
,
int
));
PARAMS
((
register
rtx
op
,
enum
machine_mode
*
mode
));
static
int
far_away
PARAMS
((
int
,
int
));
static
rtx
check_and_change_labels
PARAMS
((
rtx
,
int
*
));
static
void
s390_final_chunkify
PARAMS
((
int
));
static
int
save_fprs_p
PARAMS
((
void
));
static
int
cur_is_leaf_function
PARAMS
((
void
));
static
int
save_fprs
PARAMS
((
FILE
*
,
long
,
int
));
static
int
restore_fprs
PARAMS
((
FILE
*
,
long
,
int
));
static
void
s390_output_constant_pool
PARAMS
((
FILE
*
));
static
rtx
s390_force_const_mem_late
PARAMS
((
rtx
));
static
rtx
s390_force_const_mem_symbol
PARAMS
((
const
char
*
,
int
,
int
));
static
int
s390_function_arg_size
PARAMS
((
enum
machine_mode
,
tree
));
/* Return
TRUE or FALSE depending on whether every SET in INSN that
/* Return
true if SET either doesn't set the CC register, or else
set the CC register has source and destination with matching CC modes,
the source and destination have matching CC modes and that
and that the
CC mode is at least as constrained as REQ_MODE. */
CC mode is at least as constrained as REQ_MODE. */
static
int
static
int
s390_match_ccmode_set
(
set
,
req_mode
)
s390_match_ccmode_set
(
set
,
req_mode
)
rtx
set
;
rtx
set
;
int
req_mode
;
enum
machine_mode
req_mode
;
{
{
unsigned
int
set_mode
;
enum
machine_mode
set_mode
;
if
(
GET_CODE
(
set
)
!=
SET
)
if
(
GET_CODE
(
set
)
!=
SET
)
abort
();
abort
();
if
(
GET_CODE
(
SET_DEST
(
set
))
!=
REG
||
!
CC_REGNO_P
(
REGNO
(
SET_DEST
(
set
))))
if
(
GET_CODE
(
SET_DEST
(
set
))
!=
REG
||
!
CC_REGNO_P
(
REGNO
(
SET_DEST
(
set
))))
return
1
;
return
1
;
...
@@ -132,10 +151,14 @@ s390_match_ccmode_set (set, req_mode)
...
@@ -132,10 +151,14 @@ s390_match_ccmode_set (set, req_mode)
return
(
GET_MODE
(
SET_SRC
(
set
))
==
set_mode
);
return
(
GET_MODE
(
SET_SRC
(
set
))
==
set_mode
);
}
}
/* Return true if every SET in INSN that sets the CC register
has source and destination with matching CC modes and that
CC mode is at least as constrained as REQ_MODE. */
int
int
s390_match_ccmode
(
insn
,
req_mode
)
s390_match_ccmode
(
insn
,
req_mode
)
rtx
insn
;
rtx
insn
;
int
req_mode
;
enum
machine_mode
req_mode
;
{
{
int
i
;
int
i
;
...
@@ -154,10 +177,17 @@ s390_match_ccmode (insn, req_mode)
...
@@ -154,10 +177,17 @@ s390_match_ccmode (insn, req_mode)
return
1
;
return
1
;
}
}
/* Change optimizations to be performed, depending on the
optimization level.
LEVEL is the optimization level specified; 2 if `-O2' is
specified, 1 if `-O' is specified, and 0 if neither is specified.
SIZE is non-zero if `-Os' is specified and zero otherwise. */
void
void
optimization_options
(
level
,
size
)
optimization_options
(
level
,
size
)
int
level
;
int
level
ATTRIBUTE_UNUSED
;
int
size
ATTRIBUTE_UNUSED
;
int
size
ATTRIBUTE_UNUSED
;
{
{
#ifdef HAVE_decrement_and_branch_on_count
#ifdef HAVE_decrement_and_branch_on_count
...
@@ -183,7 +213,9 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
...
@@ -183,7 +213,9 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
};
};
/* Match exactly zero. */
/* Return true if OP a (const_int 0) operand.
OP is the current operation.
MODE is the current operation mode. */
int
int
const0_operand
(
op
,
mode
)
const0_operand
(
op
,
mode
)
...
@@ -193,7 +225,9 @@ const0_operand (op, mode)
...
@@ -193,7 +225,9 @@ const0_operand (op, mode)
return
op
==
CONST0_RTX
(
mode
);
return
op
==
CONST0_RTX
(
mode
);
}
}
/* Match exactly one. */
/* Return true if OP a (const_int 1) operand.
OP is the current operation.
MODE is the current operation mode. */
int
int
const1_operand
(
op
,
mode
)
const1_operand
(
op
,
mode
)
...
@@ -202,12 +236,12 @@ const1_operand (op, mode)
...
@@ -202,12 +236,12 @@ const1_operand (op, mode)
{
{
return
op
==
CONST1_RTX
(
mode
);
return
op
==
CONST1_RTX
(
mode
);
}
}
/* Return
1
if OP needs base and index register. */
/* Return
true
if OP needs base and index register. */
static
int
static
int
base_n_index_p
(
rtx
op
)
base_n_index_p
(
op
)
register
rtx
op
;
{
{
if
((
GET_CODE
(
op
)
==
PLUS
)
&&
if
((
GET_CODE
(
op
)
==
PLUS
)
&&
(
GET_CODE
(
XEXP
(
op
,
0
))
==
PLUS
||
(
GET_CODE
(
XEXP
(
op
,
0
))
==
PLUS
||
...
@@ -217,7 +251,8 @@ base_n_index_p (rtx op)
...
@@ -217,7 +251,8 @@ base_n_index_p (rtx op)
return
0
;
return
0
;
}
}
/* Check mode and mode of op, set it to mode of op, if VOIDmode. */
/* Return true if the mode of operand OP matches MODE.
If MODE is set to VOIDmode, set it to the mode of OP. */
static
int
static
int
check_mode
(
op
,
mode
)
check_mode
(
op
,
mode
)
...
@@ -234,8 +269,7 @@ check_mode (op, mode)
...
@@ -234,8 +269,7 @@ check_mode (op, mode)
return
1
;
return
1
;
}
}
/* Return true if OP a valid operand for the LARL instruction.
/* Return 1 if OP a valid operand for the LARL instruction.
OP is the current operation.
OP is the current operation.
MODE is the current operation mode. */
MODE is the current operation mode. */
...
@@ -244,9 +278,6 @@ larl_operand (op, mode)
...
@@ -244,9 +278,6 @@ larl_operand (op, mode)
register
rtx
op
;
register
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
mode
;
{
{
rtx
sym
;
register
enum
rtx_code
code
=
GET_CODE
(
op
);
if
(
!
check_mode
(
op
,
&
mode
))
if
(
!
check_mode
(
op
,
&
mode
))
return
0
;
return
0
;
...
@@ -291,7 +322,7 @@ larl_operand (op, mode)
...
@@ -291,7 +322,7 @@ larl_operand (op, mode)
return
0
;
return
0
;
}
}
/* Return
1
if OP is a valid FP-Register.
/* Return
true
if OP is a valid FP-Register.
OP is the current operation.
OP is the current operation.
MODE is the current operation mode. */
MODE is the current operation mode. */
...
@@ -309,7 +340,9 @@ fp_operand (op, mode)
...
@@ -309,7 +340,9 @@ fp_operand (op, mode)
return
0
;
return
0
;
}
}
/* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction. */
/* Return true if OP is a valid S operand for an RS, SI or SS type instruction.
OP is the current operation.
MODE is the current operation mode. */
int
int
s_operand
(
op
,
mode
)
s_operand
(
op
,
mode
)
...
@@ -330,7 +363,9 @@ s_operand (op, mode)
...
@@ -330,7 +363,9 @@ s_operand (op, mode)
}
}
/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
instruction. */
instruction.
OP is the current operation.
MODE is the current operation mode. */
int
int
r_or_s_operand
(
op
,
mode
)
r_or_s_operand
(
op
,
mode
)
...
@@ -351,8 +386,10 @@ r_or_s_operand (op, mode)
...
@@ -351,8 +386,10 @@ r_or_s_operand (op, mode)
return
register_operand
(
op
,
mode
);
return
register_operand
(
op
,
mode
);
}
}
/* Return 1 if OP is a valid R or S or immediate operand for
/* Return true if OP is a valid R or S or immediate operand for
RS, SI or SS type instruction. */
RS, SI or SS type instruction.
OP is the current operation.
MODE is the current operation mode. */
int
int
r_or_s_or_im8_operand
(
op
,
mode
)
r_or_s_or_im8_operand
(
op
,
mode
)
...
@@ -373,8 +410,10 @@ r_or_s_or_im8_operand (op, mode)
...
@@ -373,8 +410,10 @@ r_or_s_or_im8_operand (op, mode)
return
register_operand
(
op
,
mode
)
||
immediate_operand
(
op
,
mode
);
return
register_operand
(
op
,
mode
)
||
immediate_operand
(
op
,
mode
);
}
}
/* Return 1 if OP is a valid R or X or 16 bit immediate operand for
/* Return true if OP is a valid R or X or 16 bit immediate operand for
RX, RR or RI type instruction. */
RX, RR or RI type instruction.
OP is the current operation.
MODE is the current operation mode. */
int
int
r_or_x_or_im16_operand
(
op
,
mode
)
r_or_x_or_im16_operand
(
op
,
mode
)
...
@@ -390,8 +429,9 @@ r_or_x_or_im16_operand (op, mode)
...
@@ -390,8 +429,9 @@ r_or_x_or_im16_operand (op, mode)
return
register_operand
(
op
,
mode
)
||
memory_operand
(
op
,
mode
);
return
register_operand
(
op
,
mode
)
||
memory_operand
(
op
,
mode
);
}
}
/* Return 1 if OP is a valid R or 8 bit immediate operand for
/* Return true if OP is a valid R or 8 bit immediate operand.
!!!!!!! type instruction. */
OP is the current operation.
MODE is the current operation mode. */
int
int
r_or_im8_operand
(
op
,
mode
)
r_or_im8_operand
(
op
,
mode
)
...
@@ -407,14 +447,16 @@ r_or_im8_operand (op, mode)
...
@@ -407,14 +447,16 @@ r_or_im8_operand (op, mode)
return
register_operand
(
op
,
mode
)
||
memory_operand
(
op
,
mode
);
return
register_operand
(
op
,
mode
)
||
memory_operand
(
op
,
mode
);
}
}
/* Return
1
if OP is a valid operand for the 'test under mask'
/* Return
true
if OP is a valid operand for the 'test under mask'
instruction with 16 bit immediate.
instruction with 16 bit immediate.
The value should only have set bits in one halfword. */
The value should only have set bits in one halfword.
OP is the current operation.
MODE is the current operation mode. */
int
int
tmxx_operand
(
op
,
mode
)
tmxx_operand
(
op
,
mode
)
register
rtx
op
;
register
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
mode
ATTRIBUTE_UNUSED
;
{
{
rtx
con
;
rtx
con
;
if
(
GET_CODE
(
op
)
==
CONST_INT
)
if
(
GET_CODE
(
op
)
==
CONST_INT
)
...
@@ -431,7 +473,7 @@ tmxx_operand (op, mode)
...
@@ -431,7 +473,7 @@ tmxx_operand (op, mode)
c
=
(
unsigned
HOST_WIDEST_INT
)
INTVAL
(
con
);
c
=
(
unsigned
HOST_WIDEST_INT
)
INTVAL
(
con
);
return
((
c
&
0xffff
)
?
((
c
&
0xffffffffffff0000ULL
)
==
0
)
:
return
((
c
&
0xffff
)
?
((
c
&
0xffffffffffff0000ULL
)
==
0
)
:
(
c
&
0xffff0000
)
?
((
c
&
0xffffffff0000ffffULL
)
==
0
)
:
(
c
&
0xffff0000
U
)
?
((
c
&
0xffffffff0000ffffULL
)
==
0
)
:
(
c
&
0xffff00000000ULL
)
?
((
c
&
0xffff0000ffffffffULL
)
==
0
)
:
(
c
&
0xffff00000000ULL
)
?
((
c
&
0xffff0000ffffffffULL
)
==
0
)
:
(
c
&
0xffff000000000000ULL
)
?
((
c
&
0xffffffffffffULL
)
==
0
)
:
1
);
(
c
&
0xffff000000000000ULL
)
?
((
c
&
0xffffffffffffULL
)
==
0
)
:
1
);
...
@@ -440,15 +482,14 @@ tmxx_operand (op, mode)
...
@@ -440,15 +482,14 @@ tmxx_operand (op, mode)
return
0
;
return
0
;
}
}
/* Return true if OP is a valid operand for the BRAS instruction.
/* Return 1 if valid operand for BRAS
OP is the current operation.
OP is the current operation.
MODE is the current operation mode. */
MODE is the current operation mode. */
int
int
bras_sym_operand
(
op
,
mode
)
bras_sym_operand
(
op
,
mode
)
register
rtx
op
;
register
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
mode
ATTRIBUTE_UNUSED
;
{
{
register
enum
rtx_code
code
=
GET_CODE
(
op
);
register
enum
rtx_code
code
=
GET_CODE
(
op
);
...
@@ -465,8 +506,10 @@ bras_sym_operand (op, mode)
...
@@ -465,8 +506,10 @@ bras_sym_operand (op, mode)
}
}
/* Return 1 if OP is a load multiple operation. It is known to be a
/* Return true if OP is a load multiple operation. It is known to be a
PARALLEL and the first section will be tested. */
PARALLEL and the first section will be tested.
OP is the current operation.
MODE is the current operation mode. */
int
int
load_multiple_operation
(
op
,
mode
)
load_multiple_operation
(
op
,
mode
)
...
@@ -509,7 +552,10 @@ load_multiple_operation (op, mode)
...
@@ -509,7 +552,10 @@ load_multiple_operation (op, mode)
return
1
;
return
1
;
}
}
/* Similar, but tests for store multiple. */
/* Return true if OP is a store multiple operation. It is known to be a
PARALLEL and the first section will be tested.
OP is the current operation.
MODE is the current operation mode. */
int
int
store_multiple_operation
(
op
,
mode
)
store_multiple_operation
(
op
,
mode
)
...
@@ -551,13 +597,13 @@ store_multiple_operation (op, mode)
...
@@ -551,13 +597,13 @@ store_multiple_operation (op, mode)
}
}
/* Return
s 1
if OP contains a symbol reference */
/* Return
true
if OP contains a symbol reference */
int
int
symbolic_reference_mentioned_p
(
op
)
symbolic_reference_mentioned_p
(
op
)
rtx
op
;
rtx
op
;
{
{
register
char
*
fmt
;
register
c
onst
c
har
*
fmt
;
register
int
i
;
register
int
i
;
if
(
GET_CODE
(
op
)
==
SYMBOL_REF
||
GET_CODE
(
op
)
==
LABEL_REF
)
if
(
GET_CODE
(
op
)
==
SYMBOL_REF
||
GET_CODE
(
op
)
==
LABEL_REF
)
...
@@ -583,6 +629,10 @@ symbolic_reference_mentioned_p (op)
...
@@ -583,6 +629,10 @@ symbolic_reference_mentioned_p (op)
}
}
/* Return true if OP is a legitimate general operand when
generating PIC code. It is given that flag_pic is on
and that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
int
int
legitimate_pic_operand_p
(
op
)
legitimate_pic_operand_p
(
op
)
register
rtx
op
;
register
rtx
op
;
...
@@ -601,6 +651,9 @@ legitimate_pic_operand_p (op)
...
@@ -601,6 +651,9 @@ legitimate_pic_operand_p (op)
return
0
;
return
0
;
}
}
/* Returns true if the constant value OP is a legitimate general operand.
It is given that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
int
int
legitimate_constant_p
(
op
)
legitimate_constant_p
(
op
)
register
rtx
op
;
register
rtx
op
;
...
@@ -632,22 +685,16 @@ legitimate_constant_p (op)
...
@@ -632,22 +685,16 @@ legitimate_constant_p (op)
}
}
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
/* Decompose a RTL expression ADDR for a memory address into
that is a valid memory address for an instruction.
its components, returned in OUT. The boolean STRICT
The MODE argument is the machine mode for the MEM expression
specifies whether strict register checking applies.
that wants to use this address.
Returns 0 if ADDR is not a valid memory address, nonzero
otherwise. If OUT is NULL, don't return the components,
On S/390, legitimate addresses are:
but check for validity only.
base l reg,(base)
displacement l reg,disp
base + displacement l reg,disp(base)
index + base l reg,(base,index),reg
(index + base) + displacement l reg,disp(base,index)
It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should
convert common non-canonical forms to canonical form so that they will
be recognized. */
Note: Only addresses in canonical form are recognized.
LEGITIMIZE_ADDRESS should convert non-canonical forms to the
canonical form so that they will be recognized. */
static
int
static
int
s390_decompose_address
(
addr
,
out
,
strict
)
s390_decompose_address
(
addr
,
out
,
strict
)
...
@@ -766,7 +813,7 @@ s390_decompose_address (addr, out, strict)
...
@@ -766,7 +813,7 @@ s390_decompose_address (addr, out, strict)
/* In some cases, we can accept an additional
/* In some cases, we can accept an additional
small constant offset. Split these off here. */
small constant offset. Split these off here. */
int
offset
=
0
;
unsigned
int
offset
=
0
;
if
(
GET_CODE
(
disp
)
==
CONST
if
(
GET_CODE
(
disp
)
==
CONST
&&
GET_CODE
(
XEXP
(
disp
,
0
))
==
PLUS
&&
GET_CODE
(
XEXP
(
disp
,
0
))
==
PLUS
...
@@ -821,9 +868,12 @@ s390_decompose_address (addr, out, strict)
...
@@ -821,9 +868,12 @@ s390_decompose_address (addr, out, strict)
return
TRUE
;
return
TRUE
;
}
}
/* Return nonzero if ADDR is a valid memory address.
STRICT specifies whether strict register checking applies. */
int
int
legitimate_address_p
(
mode
,
addr
,
strict
)
legitimate_address_p
(
mode
,
addr
,
strict
)
enum
machine_mode
mode
;
enum
machine_mode
mode
ATTRIBUTE_UNUSED
;
register
rtx
addr
;
register
rtx
addr
;
int
strict
;
int
strict
;
{
{
...
@@ -956,7 +1006,7 @@ legitimize_pic_address (orig, reg)
...
@@ -956,7 +1006,7 @@ legitimize_pic_address (orig, reg)
if
(
GET_CODE
(
addr
)
==
UNSPEC
)
if
(
GET_CODE
(
addr
)
==
UNSPEC
)
{
{
if
(
XVECLEN
(
addr
,
0
)
!=
1
)
if
(
XVECLEN
(
addr
,
0
)
!=
1
)
abort
();
abort
();
switch
(
XINT
(
addr
,
1
))
switch
(
XINT
(
addr
,
1
))
{
{
/* If someone moved an @GOT or lt-relative UNSPEC
/* If someone moved an @GOT or lt-relative UNSPEC
...
@@ -1002,7 +1052,7 @@ legitimize_pic_address (orig, reg)
...
@@ -1002,7 +1052,7 @@ legitimize_pic_address (orig, reg)
}
}
}
}
else
if
(
GET_CODE
(
addr
)
!=
PLUS
)
else
if
(
GET_CODE
(
addr
)
!=
PLUS
)
abort
();
abort
();
}
}
if
(
GET_CODE
(
addr
)
==
PLUS
)
if
(
GET_CODE
(
addr
)
==
PLUS
)
{
{
...
@@ -1076,9 +1126,9 @@ legitimize_pic_address (orig, reg)
...
@@ -1076,9 +1126,9 @@ legitimize_pic_address (orig, reg)
&&
GET_CODE
(
op1
)
==
CONST_INT
)
&&
GET_CODE
(
op1
)
==
CONST_INT
)
{
{
if
(
XVECLEN
(
op0
,
0
)
!=
1
)
if
(
XVECLEN
(
op0
,
0
)
!=
1
)
abort
();
abort
();
if
(
XINT
(
op0
,
1
)
!=
100
)
if
(
XINT
(
op0
,
1
)
!=
100
)
abort
();
abort
();
new
=
force_const_mem
(
SImode
,
orig
);
new
=
force_const_mem
(
SImode
,
orig
);
}
}
...
@@ -1125,18 +1175,13 @@ emit_pic_move (operands, mode)
...
@@ -1125,18 +1175,13 @@ emit_pic_move (operands, mode)
operands
[
1
]
=
legitimize_pic_address
(
operands
[
1
],
temp
);
operands
[
1
]
=
legitimize_pic_address
(
operands
[
1
],
temp
);
}
}
/* Try machine-dependent ways of modifying an illegitimate address
/* Try machine-dependent ways of modifying an illegitimate address
X
to be legitimate. If we find one, return the new, valid address.
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c.
OLDX is the address as it was before break_out_memory_refs was called.
OLDX is the address as it was before break_out_memory_refs was called.
In some cases it is useful to look at this to decide what needs to be done.
In some cases it is useful to look at this to decide what needs to be done.
MODE and WIN are passed so that this macro can use
MODE is the mode of the operand pointed to by X.
GO_IF_LEGITIMATE_ADDRESS.
It is always safe for this macro to do nothing. It exists to recognize
opportunities to optimize the output.
When -fpic is used, special handling is needed for symbolic references.
When -fpic is used, special handling is needed for symbolic references.
See comments by legitimize_pic_address for details. */
See comments by legitimize_pic_address for details. */
...
@@ -1145,7 +1190,7 @@ rtx
...
@@ -1145,7 +1190,7 @@ rtx
legitimize_address
(
x
,
oldx
,
mode
)
legitimize_address
(
x
,
oldx
,
mode
)
register
rtx
x
;
register
rtx
x
;
register
rtx
oldx
ATTRIBUTE_UNUSED
;
register
rtx
oldx
ATTRIBUTE_UNUSED
;
enum
machine_mode
mode
;
enum
machine_mode
mode
ATTRIBUTE_UNUSED
;
{
{
if
(
flag_pic
&&
SYMBOLIC_CONST
(
x
))
if
(
flag_pic
&&
SYMBOLIC_CONST
(
x
))
return
legitimize_pic_address
(
x
,
0
);
return
legitimize_pic_address
(
x
,
0
);
...
@@ -1154,10 +1199,13 @@ legitimize_address (x, oldx, mode)
...
@@ -1154,10 +1199,13 @@ legitimize_address (x, oldx, mode)
}
}
/* Output branch conditions. */
/* Output branch condition code of CODE in assembler
syntax to stdio stream FILE. */
static
void
static
void
output_branch_condition
(
FILE
*
file
,
rtx
code
)
output_branch_condition
(
file
,
code
)
FILE
*
file
;
rtx
code
;
{
{
switch
(
GET_CODE
(
code
))
switch
(
GET_CODE
(
code
))
{
{
...
@@ -1188,8 +1236,13 @@ output_branch_condition (FILE *file, rtx code)
...
@@ -1188,8 +1236,13 @@ output_branch_condition (FILE *file, rtx code)
}
}
}
}
/* Output the inverse of the branch condition code of CODE
in assembler syntax to stdio stream FILE. */
static
void
static
void
output_inverse_branch_condition
(
FILE
*
file
,
rtx
code
)
output_inverse_branch_condition
(
file
,
code
)
FILE
*
file
;
rtx
code
;
{
{
switch
(
GET_CODE
(
code
))
switch
(
GET_CODE
(
code
))
{
{
...
@@ -1220,10 +1273,13 @@ output_inverse_branch_condition (FILE *file, rtx code)
...
@@ -1220,10 +1273,13 @@ output_inverse_branch_condition (FILE *file, rtx code)
}
}
}
}
/* Output a symbolic constant. */
/* Output symbolic constant X in assembler syntax to
stdio stream FILE. */
void
void
s390_output_symbolic_const
(
FILE
*
file
,
rtx
x
)
s390_output_symbolic_const
(
file
,
x
)
FILE
*
file
;
rtx
x
;
{
{
switch
(
GET_CODE
(
x
))
switch
(
GET_CODE
(
x
))
{
{
...
@@ -1303,10 +1359,13 @@ s390_output_symbolic_const (FILE *file, rtx x)
...
@@ -1303,10 +1359,13 @@ s390_output_symbolic_const (FILE *file, rtx x)
}
}
}
}
/* Output an address operand. */
/* Output address operand ADDR in assembler syntax to
stdio stream FILE. */
void
void
print_operand_address
(
FILE
*
file
,
rtx
addr
)
print_operand_address
(
file
,
addr
)
FILE
*
file
;
rtx
addr
;
{
{
struct
s390_address
ad
;
struct
s390_address
ad
;
...
@@ -1325,10 +1384,28 @@ print_operand_address (FILE *file, rtx addr)
...
@@ -1325,10 +1384,28 @@ print_operand_address (FILE *file, rtx addr)
fprintf
(
file
,
"(%s)"
,
reg_names
[
REGNO
(
ad
.
base
)]);
fprintf
(
file
,
"(%s)"
,
reg_names
[
REGNO
(
ad
.
base
)]);
}
}
/* Output an operand. */
/* Output operand X in assembler syntax to stdio stream FILE.
CODE specified the format flag. The following format flags
are recognized:
'C': print opcode suffix for branch condition.
'D': print opcode suffix for inverse branch condition.
'Y': print current constant pool address (pc-relative).
'y': print current constant pool address (absolute).
'O': print only the displacement of a memory reference.
'R': print only the base register of a memory reference.
'N': print the second word of a DImode operand.
'M': print the second word of a TImode operand.
'b': print integer X as if it's a unsigned byte.
'x': print integer X as if it's a unsigned word.
'h': print integer X as if it's a signed word. */
void
void
print_operand
(
FILE
*
file
,
rtx
x
,
char
code
)
print_operand
(
file
,
x
,
code
)
FILE
*
file
;
rtx
x
;
int
code
;
{
{
switch
(
code
)
switch
(
code
)
{
{
...
@@ -1355,7 +1432,7 @@ print_operand (FILE *file, rtx x, char code)
...
@@ -1355,7 +1432,7 @@ print_operand (FILE *file, rtx x, char code)
if
(
GET_CODE
(
x
)
!=
MEM
if
(
GET_CODE
(
x
)
!=
MEM
||
!
s390_decompose_address
(
XEXP
(
x
,
0
),
&
ad
,
TRUE
)
||
!
s390_decompose_address
(
XEXP
(
x
,
0
),
&
ad
,
TRUE
)
||
ad
.
indx
)
||
ad
.
indx
)
abort
();
abort
();
if
(
ad
.
disp
)
if
(
ad
.
disp
)
s390_output_symbolic_const
(
file
,
ad
.
disp
);
s390_output_symbolic_const
(
file
,
ad
.
disp
);
...
@@ -1371,7 +1448,7 @@ print_operand (FILE *file, rtx x, char code)
...
@@ -1371,7 +1448,7 @@ print_operand (FILE *file, rtx x, char code)
if
(
GET_CODE
(
x
)
!=
MEM
if
(
GET_CODE
(
x
)
!=
MEM
||
!
s390_decompose_address
(
XEXP
(
x
,
0
),
&
ad
,
TRUE
)
||
!
s390_decompose_address
(
XEXP
(
x
,
0
),
&
ad
,
TRUE
)
||
ad
.
indx
)
||
ad
.
indx
)
abort
();
abort
();
if
(
ad
.
base
)
if
(
ad
.
base
)
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
ad
.
base
)]);
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
ad
.
base
)]);
...
@@ -1386,7 +1463,7 @@ print_operand (FILE *file, rtx x, char code)
...
@@ -1386,7 +1463,7 @@ print_operand (FILE *file, rtx x, char code)
else
if
(
GET_CODE
(
x
)
==
MEM
)
else
if
(
GET_CODE
(
x
)
==
MEM
)
x
=
change_address
(
x
,
VOIDmode
,
plus_constant
(
XEXP
(
x
,
0
),
4
));
x
=
change_address
(
x
,
VOIDmode
,
plus_constant
(
XEXP
(
x
,
0
),
4
));
else
else
abort
();
abort
();
break
;
break
;
case
'M'
:
case
'M'
:
...
@@ -1395,7 +1472,7 @@ print_operand (FILE *file, rtx x, char code)
...
@@ -1395,7 +1472,7 @@ print_operand (FILE *file, rtx x, char code)
else
if
(
GET_CODE
(
x
)
==
MEM
)
else
if
(
GET_CODE
(
x
)
==
MEM
)
x
=
change_address
(
x
,
VOIDmode
,
plus_constant
(
XEXP
(
x
,
0
),
8
));
x
=
change_address
(
x
,
VOIDmode
,
plus_constant
(
XEXP
(
x
,
0
),
8
));
else
else
abort
();
abort
();
break
;
break
;
}
}
...
@@ -1437,11 +1514,13 @@ print_operand (FILE *file, rtx x, char code)
...
@@ -1437,11 +1514,13 @@ print_operand (FILE *file, rtx x, char code)
#define DEBUG_SCHED 0
#define DEBUG_SCHED 0
/*
True, if register regno is used for forming a memory address in
/*
Returns true if register REGNO is used for forming
a
expression x
. */
a
memory address in expression X
. */
static
int
static
int
reg_used_in_mem_p
(
int
regno
,
rtx
x
)
reg_used_in_mem_p
(
regno
,
x
)
int
regno
;
rtx
x
;
{
{
enum
rtx_code
code
=
GET_CODE
(
x
);
enum
rtx_code
code
=
GET_CODE
(
x
);
int
i
,
j
;
int
i
,
j
;
...
@@ -1469,11 +1548,13 @@ reg_used_in_mem_p (int regno, rtx x)
...
@@ -1469,11 +1548,13 @@ reg_used_in_mem_p (int regno, rtx x)
return
0
;
return
0
;
}
}
/* Returns true
, if expression dep_rtx
sets a address register
/* Returns true
if expression DEP_RTX
sets a address register
used by instruction
insn
to address memory. */
used by instruction
INSN
to address memory. */
static
int
static
int
addr_generation_dependency_p
(
rtx
dep_rtx
,
rtx
insn
)
addr_generation_dependency_p
(
dep_rtx
,
insn
)
rtx
dep_rtx
;
rtx
insn
;
{
{
rtx
target
;
rtx
target
;
...
@@ -1496,16 +1577,23 @@ addr_generation_dependency_p (rtx dep_rtx, rtx insn)
...
@@ -1496,16 +1577,23 @@ addr_generation_dependency_p (rtx dep_rtx, rtx insn)
}
}
/* Data dependencies are all handled without delay. But if an register
/* Return the modified cost of the dependency of instruction INSN
is changed for a memory access, at least 4 cycle need to be put
on instruction DEP_INSN through the link LINK. COST is the
between the set of the register and the use. Because of that,
default cost of that dependency.
the delays specified in the .md file needs to check and adjust
to the right cost. */
Data dependencies are all handled without delay. However, if a
register is modified and subsequently used as base or index
register of a memory reference, at least 4 cycles need to pass
between setting and using the register to avoid pipeline stalls. */
int
int
s390_adjust_cost
(
rtx
insn
,
rtx
link
,
rtx
dep_insn
,
int
cost
)
s390_adjust_cost
(
insn
,
link
,
dep_insn
,
cost
)
rtx
insn
;
rtx
link
;
rtx
dep_insn
;
int
cost
;
{
{
rtx
dep_rtx
,
dest
,
x
;
rtx
dep_rtx
;
int
i
;
int
i
;
/* If the dependence is an anti-dependence, there is no cost. For an
/* If the dependence is an anti-dependence, there is no cost. For an
...
@@ -1575,20 +1663,30 @@ s390_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost )
...
@@ -1575,20 +1663,30 @@ s390_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost )
- in this case, a branch from one chunk to other chunk needs
- in this case, a branch from one chunk to other chunk needs
a reload of base register at the code label branched to. */
a reload of base register at the code label branched to. */
/* Index of constant pool chunk that is currently being processed.
Set to -1 before function output has started. */
rtx
s390_pool_start_insn
=
NULL_RTX
;
/* Count of actual pool in function (-1 -> before function). */
int
s390_pool_count
=
-
1
;
int
s390_pool_count
=
-
1
;
/* First insn using the constant pool chunk that is currently being
processed. */
rtx
s390_pool_start_insn
=
NULL_RTX
;
/* UID of last insn using the constant pool chunk that is currently
being processed. */
static
int
pool_stop_uid
;
static
int
pool_stop_uid
;
/* Called from the ASM_OUTPUT_POOL_PROLOGUE macro to
prepare for printing a literal pool chunk to stdio stream FILE.
FNAME and FNDECL specify the name and type of the current function.
SIZE is the size in bytes of the current literal pool. */
void
void
s390_asm_output_pool_prologue
(
FILE
*
file
,
char
*
fname
,
tree
fndecl
,
int
size
)
s390_asm_output_pool_prologue
(
file
,
fname
,
fndecl
,
size
)
FILE
*
file
;
const
char
*
fname
ATTRIBUTE_UNUSED
;
tree
fndecl
;
int
size
ATTRIBUTE_UNUSED
;
{
{
if
(
s390_pool_count
>
0
)
{
if
(
s390_pool_count
>
0
)
{
...
@@ -1600,7 +1698,7 @@ s390_asm_output_pool_prologue (FILE *file, char *fname, tree fndecl, int size)
...
@@ -1600,7 +1698,7 @@ s390_asm_output_pool_prologue (FILE *file, char *fname, tree fndecl, int size)
fprintf
(
file
,
"
\t
larl
\t
%s,.LT%X_%X
\n
"
,
fprintf
(
file
,
"
\t
larl
\t
%s,.LT%X_%X
\n
"
,
reg_names
[
BASE_REGISTER
],
reg_names
[
BASE_REGISTER
],
s390_function_count
,
s390_pool_count
);
s390_function_count
,
s390_pool_count
);
readonly_data_section
();
readonly_data_section
();
ASM_OUTPUT_ALIGN
(
file
,
floor_log2
(
3
));
ASM_OUTPUT_ALIGN
(
file
,
floor_log2
(
3
));
fprintf
(
file
,
".LT%X_%X:
\t
# Pool %d
\n
"
,
fprintf
(
file
,
".LT%X_%X:
\t
# Pool %d
\n
"
,
s390_function_count
,
s390_pool_count
,
s390_pool_count
);
s390_function_count
,
s390_pool_count
,
s390_pool_count
);
...
@@ -1614,12 +1712,15 @@ s390_asm_output_pool_prologue (FILE *file, char *fname, tree fndecl, int size)
...
@@ -1614,12 +1712,15 @@ s390_asm_output_pool_prologue (FILE *file, char *fname, tree fndecl, int size)
function_section
(
fndecl
);
function_section
(
fndecl
);
}
}
/*
Check if other addr is in different chunk than my addr,
/*
Return true if OTHER_ADDR is in different chunk than MY_ADDR.
return symbol_ref to other pool in that case. */
LTORG points to a list of all literal pools inserted
into the current function. */
static
int
static
int
other_chunk
(
int
*
ltorg
,
int
my_addr
,
int
other_addr
)
other_chunk
(
ltorg
,
my_addr
,
other_addr
)
int
*
ltorg
;
int
my_addr
;
int
other_addr
;
{
{
int
ad
,
i
=
0
,
j
=
0
;
int
ad
,
i
=
0
,
j
=
0
;
...
@@ -1639,10 +1740,13 @@ other_chunk (int *ltorg, int my_addr, int other_addr)
...
@@ -1639,10 +1740,13 @@ other_chunk (int *ltorg, int my_addr, int other_addr)
return
1
;
return
1
;
}
}
/* Check, if other label is to far away to branch relative. */
/* Return true if OTHER_ADDR is too far away from MY_ADDR
to use a relative branch instruction. */
static
int
static
int
far_away
(
int
my_addr
,
int
other_addr
)
far_away
(
my_addr
,
other_addr
)
int
my_addr
;
int
other_addr
;
{
{
/* In 64 bit mode we can jump +- 4GB. */
/* In 64 bit mode we can jump +- 4GB. */
if
(
TARGET_64BIT
)
if
(
TARGET_64BIT
)
...
@@ -1652,10 +1756,18 @@ far_away (int my_addr, int other_addr)
...
@@ -1652,10 +1756,18 @@ far_away (int my_addr, int other_addr)
return
0
;
return
0
;
}
}
/* Go through all insns in the current function (starting
at INSN), replacing branch insn if necessary. A branch
needs to be modified if either the distance to the
target is too far to use a relative branch, or if the
target uses a different literal pool than the origin.
LTORG_UIDS points to a list of all literal pool insns
that have been inserted. */
static
rtx
static
rtx
check_and_change_labels
(
rtx
insn
,
int
*
ltorg_uids
)
check_and_change_labels
(
insn
,
ltorg_uids
)
rtx
insn
;
int
*
ltorg_uids
;
{
{
rtx
temp_reg
=
gen_rtx_REG
(
Pmode
,
RETURN_REGNUM
);
rtx
temp_reg
=
gen_rtx_REG
(
Pmode
,
RETURN_REGNUM
);
rtx
target
,
jump
;
rtx
target
,
jump
;
...
@@ -1792,13 +1904,18 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
...
@@ -1792,13 +1904,18 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
return
insn
;
return
insn
;
}
}
static
int
chunk_max
=
0
;
/* Called from s390_function_prologue to make final adjustments
before outputting code. CHUNKIFY specifies whether we need
to use multiple literal pools (because the total size of the
literals exceeds 4K). */
void
static
void
s390_final_chunkify
(
int
chunkify
)
s390_final_chunkify
(
chunkify
)
int
chunkify
;
{
{
rtx
insn
,
ninsn
,
tmp
;
rtx
insn
,
ninsn
,
tmp
;
int
addr
,
naddr
,
uids
;
int
addr
,
naddr
=
0
,
uids
;
int
chunk_max
=
0
;
const
char
*
asms
;
const
char
*
asms
;
...
@@ -1850,7 +1967,7 @@ s390_final_chunkify (int chunkify)
...
@@ -1850,7 +1967,7 @@ s390_final_chunkify (int chunkify)
fprintf
(
stderr
,
"s390 multiple literalpool support:"
fprintf
(
stderr
,
"s390 multiple literalpool support:"
"
\n
No code label between this insn %X %X"
,
"
\n
No code label between this insn %X %X"
,
naddr
,
INSN_ADDRESSES
(
INSN_UID
(
tmp
)));
naddr
,
INSN_ADDRESSES
(
INSN_UID
(
tmp
)));
abort
();
abort
();
}
}
}
}
if
(
tmp
==
NULL
)
if
(
tmp
==
NULL
)
...
@@ -1905,12 +2022,11 @@ s390_final_chunkify (int chunkify)
...
@@ -1905,12 +2022,11 @@ s390_final_chunkify (int chunkify)
pool_stop_uid
=
ltorg_uids
[
0
];
pool_stop_uid
=
ltorg_uids
[
0
];
}
}
/* Return 1 if next literal pool is reached (check for ltorg insn)
/* Return true if INSN is a 'ltorg' insn. */
maybe should use unspec insn. */
int
int
s390_stop_dump_lit_p
(
rtx
insn
)
s390_stop_dump_lit_p
(
insn
)
rtx
insn
;
{
{
rtx
body
=
PATTERN
(
insn
);
rtx
body
=
PATTERN
(
insn
);
if
(
GET_CODE
(
body
)
==
PARALLEL
if
(
GET_CODE
(
body
)
==
PARALLEL
...
@@ -1926,8 +2042,13 @@ s390_stop_dump_lit_p (rtx insn)
...
@@ -1926,8 +2042,13 @@ s390_stop_dump_lit_p (rtx insn)
return
0
;
return
0
;
}
}
/* Output literal pool chunk to be used for insns
between insn ACT_INSN and the insn with UID STOP. */
void
void
s390_dump_literal_pool
(
rtx
act_insn
,
rtx
stop
)
s390_dump_literal_pool
(
act_insn
,
stop
)
rtx
act_insn
;
rtx
stop
;
{
{
s390_pool_start_insn
=
act_insn
;
s390_pool_start_insn
=
act_insn
;
pool_stop_uid
=
INTVAL
(
stop
);
pool_stop_uid
=
INTVAL
(
stop
);
...
@@ -1942,16 +2063,20 @@ extern char *dwarf2out_cfi_label PARAMS ((void));
...
@@ -1942,16 +2063,20 @@ extern char *dwarf2out_cfi_label PARAMS ((void));
#endif
#endif
/* Flag set in prologue, used in epilog to know
/* Flag set in prologue, used in epilog to know
if stack is allocated or not. */
if stack is allocated or not. */
static
int
leaf_function_flag
;
static
int
leaf_function_flag
;
rtx
s390_got_label
;
/* Symbol references needed by the profile code;
set up by the function prologue routine if necessary. */
rtx
s390_profile
[
10
];
rtx
s390_profile
[
10
];
/* Number of elements of current constant pool. */
int
s390_nr_constants
;
int
s390_nr_constants
;
/* Return
s 1
if floating point registers need to be saved. */
/* Return
true
if floating point registers need to be saved. */
static
int
save_fprs_p
()
static
int
save_fprs_p
()
{
{
int
i
;
int
i
;
if
(
!
TARGET_64BIT
)
if
(
!
TARGET_64BIT
)
...
@@ -1964,8 +2089,8 @@ static int save_fprs_p()
...
@@ -1964,8 +2089,8 @@ static int save_fprs_p()
return
0
;
return
0
;
}
}
/*
Current function is a leaf function, without automatics,
/*
Return true if urrent function is a leaf function,
alloca or vararg stuff. */
without automatics,
alloca or vararg stuff. */
static
int
static
int
cur_is_leaf_function
()
cur_is_leaf_function
()
...
@@ -1980,10 +2105,11 @@ cur_is_leaf_function ()
...
@@ -1980,10 +2105,11 @@ cur_is_leaf_function ()
return
0
;
return
0
;
}
}
/*
Calculate
offset between argument pointer and frame pointer
/*
Return
offset between argument pointer and frame pointer
initialy after prologue. */
initial
l
y after prologue. */
int
s390_arg_frame_offset
()
int
s390_arg_frame_offset
()
{
{
int
lsize
=
get_frame_size
()
+
current_function_outgoing_args_size
int
lsize
=
get_frame_size
()
+
current_function_outgoing_args_size
+
save_fprs_p
()
*
64
;
+
save_fprs_p
()
*
64
;
...
@@ -1994,9 +2120,15 @@ int s390_arg_frame_offset ()
...
@@ -1994,9 +2120,15 @@ int s390_arg_frame_offset ()
return
2
*
STACK_POINTER_OFFSET
+
lsize
;
return
2
*
STACK_POINTER_OFFSET
+
lsize
;
}
}
/* Save Floating point register on current stack. */
/* Output code to stdio stream FILE to save floating point
registers on current stack, at offset OFFSET to the frame
pointer register FP. */
static
int
save_fprs
(
FILE
*
file
,
long
offset
,
int
fp
)
static
int
save_fprs
(
file
,
offset
,
fp
)
FILE
*
file
;
long
offset
;
int
fp
;
{
{
int
i
;
int
i
;
...
@@ -2007,22 +2139,30 @@ static int save_fprs(FILE *file, long offset, int fp)
...
@@ -2007,22 +2139,30 @@ static int save_fprs(FILE *file, long offset, int fp)
{
{
if
(
regs_ever_live
[
i
]
==
1
)
if
(
regs_ever_live
[
i
]
==
1
)
{
{
fprintf
(
file
,
"
\t
std
\t
%s,%d(%s)
\n
"
,
reg_names
[
i
],
fprintf
(
file
,
"
\t
std
\t
%s,%
l
d(%s)
\n
"
,
reg_names
[
i
],
(
i
-
24
)
*
8
+
offset
,
reg_names
[
fp
]);
(
i
-
24
)
*
8
+
offset
,
reg_names
[
fp
]);
}
}
}
}
return
1
;
}
}
/* Restore Floating point register on current stack. */
/* Output code to stdio stream FILE to restore floating point
registers from current stack, at offset OFFSET to the frame
pointer register FP. */
static
int
restore_fprs
(
FILE
*
file
,
long
offset
,
int
fp
)
static
int
restore_fprs
(
file
,
offset
,
fp
)
FILE
*
file
;
long
offset
;
int
fp
;
{
{
int
i
;
int
i
;
if
(
!
TARGET_64BIT
)
if
(
!
TARGET_64BIT
)
return
0
;
return
0
;
if
(
!
save_fprs_p
())
if
(
!
save_fprs_p
())
return
0
;
return
0
;
if
(
offset
<
0
)
if
(
offset
<
0
)
...
@@ -2038,16 +2178,19 @@ static int restore_fprs(FILE *file, long offset, int fp)
...
@@ -2038,16 +2178,19 @@ static int restore_fprs(FILE *file, long offset, int fp)
{
{
if
(
regs_ever_live
[
i
]
==
1
)
if
(
regs_ever_live
[
i
]
==
1
)
{
{
fprintf
(
file
,
"
\t
ld
\t
%s,%d(%s)
\n
"
,
reg_names
[
i
],
fprintf
(
file
,
"
\t
ld
\t
%s,%
l
d(%s)
\n
"
,
reg_names
[
i
],
(
i
-
24
)
*
8
+
offset
,
reg_names
[
fp
]);
(
i
-
24
)
*
8
+
offset
,
reg_names
[
fp
]);
}
}
}
}
return
1
;
}
}
/* Output
constant pool in function prologue (31 bit) or in readonly section
. */
/* Output
main constant pool to stdio stream FILE
. */
static
int
static
void
s390_output_constant_pool
(
FILE
*
file
)
s390_output_constant_pool
(
file
)
FILE
*
file
;
{
{
/* Output constant pool. */
/* Output constant pool. */
if
(
s390_nr_constants
||
regs_ever_live
[
BASE_REGISTER
])
if
(
s390_nr_constants
||
regs_ever_live
[
BASE_REGISTER
])
...
@@ -2057,7 +2200,7 @@ s390_output_constant_pool(FILE* file)
...
@@ -2057,7 +2200,7 @@ s390_output_constant_pool(FILE* file)
{
{
fprintf
(
file
,
"
\t
larl
\t
%s,.LT%X_%X
\n
"
,
reg_names
[
BASE_REGISTER
],
fprintf
(
file
,
"
\t
larl
\t
%s,.LT%X_%X
\n
"
,
reg_names
[
BASE_REGISTER
],
s390_function_count
,
s390_pool_count
);
s390_function_count
,
s390_pool_count
);
readonly_data_section
();
readonly_data_section
();
ASM_OUTPUT_ALIGN
(
file
,
floor_log2
(
3
));
ASM_OUTPUT_ALIGN
(
file
,
floor_log2
(
3
));
}
}
else
else
...
@@ -2070,17 +2213,20 @@ s390_output_constant_pool(FILE* file)
...
@@ -2070,17 +2213,20 @@ s390_output_constant_pool(FILE* file)
fprintf
(
file
,
".LTN%X_%X:
\n
"
,
s390_function_count
,
fprintf
(
file
,
".LTN%X_%X:
\n
"
,
s390_function_count
,
s390_pool_count
);
s390_pool_count
);
if
(
TARGET_64BIT
)
if
(
TARGET_64BIT
)
function_section
(
current_function_decl
);
function_section
(
current_function_decl
);
regs_ever_live
[
BASE_REGISTER
]
=
1
;
regs_ever_live
[
BASE_REGISTER
]
=
1
;
}
}
}
}
/* Add constant CTX to the constant pool at a late time
/* This function generates the assembly code for function entry. */
(after the initial pass to count the number of constants
was already done). Returns the resulting constant
pool reference. */
static
rtx
static
rtx
s390_force_const_mem_late
(
rtx
cst
)
s390_force_const_mem_late
(
cst
)
rtx
cst
;
{
{
cst
=
force_const_mem
(
Pmode
,
cst
);
cst
=
force_const_mem
(
Pmode
,
cst
);
...
@@ -2092,8 +2238,17 @@ s390_force_const_mem_late (rtx cst)
...
@@ -2092,8 +2238,17 @@ s390_force_const_mem_late (rtx cst)
return
cst
;
return
cst
;
}
}
/* Add a reference to the symbol NAME to the constant pool.
FUNC specifies whether NAME refers to a function, while
GLOBAL specifies whether NAME is a global symbol. Depending
on these flags, the appopriate PLT or GOT references are
generated. Returns the constant pool reference. */
static
rtx
static
rtx
s390_force_const_mem_symbol
(
char
*
name
,
int
func
,
int
global
)
s390_force_const_mem_symbol
(
name
,
func
,
global
)
const
char
*
name
;
int
func
;
int
global
;
{
{
rtx
symbol
;
rtx
symbol
;
...
@@ -2121,15 +2276,19 @@ s390_force_const_mem_symbol (char *name, int func, int global)
...
@@ -2121,15 +2276,19 @@ s390_force_const_mem_symbol (char *name, int func, int global)
return
s390_force_const_mem_late
(
symbol
);
return
s390_force_const_mem_late
(
symbol
);
}
}
/* This function generates the assembly code for function entry. */
/* Output the function prologue assembly code to the
stdio stream FILE. The local frame size is passed
in LSIZE. */
void
void
s390_function_prologue
(
FILE
*
file
,
HOST_WIDE_INT
lsize
)
s390_function_prologue
(
file
,
lsize
)
FILE
*
file
;
HOST_WIDE_INT
lsize
;
{
{
extern
int
profile_label_no
;
extern
int
profile_label_no
;
int
i
,
j
;
int
i
,
j
;
long
frame_size
;
long
frame_size
;
rtx
stack_label
=
0
,
got_label
=
0
,
tmp
;
rtx
stack_label
=
0
,
got_label
=
0
;
char
*
l
;
char
*
l
;
char
b64
[
2
]
=
" "
;
char
b64
[
2
]
=
" "
;
b64
[
0
]
=
TARGET_64BIT
?
'g'
:
'\0'
;
b64
[
0
]
=
TARGET_64BIT
?
'g'
:
'\0'
;
...
@@ -2335,14 +2494,13 @@ s390_function_prologue (FILE *file, HOST_WIDE_INT lsize)
...
@@ -2335,14 +2494,13 @@ s390_function_prologue (FILE *file, HOST_WIDE_INT lsize)
}
}
if
(
save_fprs_p
()
&&
frame_size
>
4095
)
if
(
save_fprs_p
()
&&
frame_size
>
4095
)
{
{
int
fp
=
1
;
int
fp
=
1
;
int
offset
=
0
;
fprintf
(
file
,
"
\t
lgr
\t
%s,%s
\n
"
,
reg_names
[
fp
],
fprintf
(
file
,
"
\t
lgr
\t
%s,%s
\n
"
,
reg_names
[
fp
],
reg_names
[
STACK_POINTER_REGNUM
]);
reg_names
[
STACK_POINTER_REGNUM
]);
fprintf
(
file
,
"
\t
aghi
\t
%s,-64
\n
"
,
reg_names
[
fp
]);
fprintf
(
file
,
"
\t
aghi
\t
%s,-64
\n
"
,
reg_names
[
fp
]);
save_fprs
(
file
,
0
,
fp
);
save_fprs
(
file
,
0
,
fp
);
}
}
/* Decrement stack. */
/* Decrement stack. */
...
@@ -2370,7 +2528,7 @@ s390_function_prologue (FILE *file, HOST_WIDE_INT lsize)
...
@@ -2370,7 +2528,7 @@ s390_function_prologue (FILE *file, HOST_WIDE_INT lsize)
}
}
else
else
{
{
fprintf
(
file
,
"
\t
a%shi
\t
%s,-%d
\n
"
,
b64
,
fprintf
(
file
,
"
\t
a%shi
\t
%s,-%
l
d
\n
"
,
b64
,
reg_names
[
STACK_POINTER_REGNUM
],
frame_size
);
reg_names
[
STACK_POINTER_REGNUM
],
frame_size
);
}
}
#ifdef INCOMING_RETURN_ADDR_RTX
#ifdef INCOMING_RETURN_ADDR_RTX
...
@@ -2432,10 +2590,14 @@ s390_function_prologue (FILE *file, HOST_WIDE_INT lsize)
...
@@ -2432,10 +2590,14 @@ s390_function_prologue (FILE *file, HOST_WIDE_INT lsize)
return
;
return
;
}
}
/* This function generates the assembly code for function exit. */
/* Output the function epilogue assembly code to the
stdio stream FILE. The local frame size is passed
in LSIZE. */
void
void
s390_function_epilogue
(
FILE
*
file
,
HOST_WIDE_INT
lsize
)
s390_function_epilogue
(
file
,
lsize
)
FILE
*
file
;
HOST_WIDE_INT
lsize
;
{
{
/* Register is call clobbered and not used for eh or return. */
/* Register is call clobbered and not used for eh or return. */
#define FREE_REG 4
#define FREE_REG 4
...
@@ -2532,21 +2694,15 @@ s390_function_epilogue (FILE *file, HOST_WIDE_INT lsize)
...
@@ -2532,21 +2694,15 @@ s390_function_epilogue (FILE *file, HOST_WIDE_INT lsize)
return
;
return
;
}
}
/* For structs of odd size the address is passed as reference.
Complex number are also passes on the stack.
Note: We don't use mode, since a struct with the following format
is BLKmode, but has size 4.
struct
{
char a;
char b[3]
}.
The ABI states, that this value has to be passed in register. */
/* Return the size in bytes of a function argument of
type TYPE and/or mode MODE. At least one of TYPE or
MODE must be specified. */
static
int
static
int
s390_function_arg_size
(
enum
machine_mode
mode
,
tree
type
)
s390_function_arg_size
(
mode
,
type
)
enum
machine_mode
mode
;
tree
type
;
{
{
if
(
type
)
if
(
type
)
return
int_size_in_bytes
(
type
);
return
int_size_in_bytes
(
type
);
...
@@ -2556,11 +2712,19 @@ s390_function_arg_size (enum machine_mode mode, tree type)
...
@@ -2556,11 +2712,19 @@ s390_function_arg_size (enum machine_mode mode, tree type)
return
GET_MODE_SIZE
(
mode
);
return
GET_MODE_SIZE
(
mode
);
/* If we have neither type nor mode, abort */
/* If we have neither type nor mode, abort */
fatal_error
(
"no type info available for BLKmode
\n
"
);
abort
(
);
}
}
/* Return 1 if a function argument of type TYPE and mode MODE
is to be passed by reference. The ABI specifies that only
structures of size 1, 2, 4, or 8 bytes are passed by value,
all other structures (and complex numbers) are passed by
reference. */
int
int
s390_function_arg_pass_by_reference
(
enum
machine_mode
mode
,
tree
type
)
s390_function_arg_pass_by_reference
(
mode
,
type
)
enum
machine_mode
mode
;
tree
type
;
{
{
int
size
=
s390_function_arg_size
(
mode
,
type
);
int
size
=
s390_function_arg_size
(
mode
,
type
);
...
@@ -2579,11 +2743,16 @@ s390_function_arg_pass_by_reference (enum machine_mode mode, tree type)
...
@@ -2579,11 +2743,16 @@ s390_function_arg_pass_by_reference (enum machine_mode mode, tree type)
/* Update the data in CUM to advance over an argument of mode MODE and
/* Update the data in CUM to advance over an argument of mode MODE and
data type TYPE. (TYPE is null for libcalls where that information
data type TYPE. (TYPE is null for libcalls where that information
may not be available.). */
may not be available.). The boolean NAMED specifies whether the
argument is a named argument (as opposed to an unnamed argument
matching an ellipsis). */
void
void
s390_function_arg_advance
(
CUMULATIVE_ARGS
*
cum
,
s390_function_arg_advance
(
cum
,
mode
,
type
,
named
)
enum
machine_mode
mode
,
tree
type
,
int
named
)
CUMULATIVE_ARGS
*
cum
;
enum
machine_mode
mode
;
tree
type
;
int
named
ATTRIBUTE_UNUSED
;
{
{
if
(
!
TARGET_SOFT_FLOAT
&&
(
mode
==
DFmode
||
mode
==
SFmode
))
if
(
!
TARGET_SOFT_FLOAT
&&
(
mode
==
DFmode
||
mode
==
SFmode
))
{
{
...
@@ -2600,17 +2769,31 @@ s390_function_arg_advance (CUMULATIVE_ARGS * cum,
...
@@ -2600,17 +2769,31 @@ s390_function_arg_advance (CUMULATIVE_ARGS * cum,
}
}
}
}
/* Define where to put the arguments to a function.
Value is zero to push the argument on the stack,
/* Define where to put the arguments to a function. Value is zero to push
or a hard register in which to store the argument.
the argument on the stack, or a hard register in which to store the
argument. Gprs 2-6 and Fprs 0 and 2 are used as arguments.
MODE is the argument's machine mode.
All integral values go into register, until all are used up, the rest
TYPE is the data type of the argument (as a tree).
goes onto stack. The same is valid for floating-point values. */
This is null for libcalls where that information may
not be available.
CUM is a variable of type CUMULATIVE_ARGS which gives info about
the preceding args and about the function being called.
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis).
On S/390, we use general purpose registers 2 through 6 to
pass integer, pointer, and certain structure arguments, and
floating point registers 0 and 2 (0, 2, 4, and 6 on 64-bit)
to pass floating point arguments. All remaining arguments
are pushed to the stack. */
rtx
rtx
s390_function_arg
(
CUMULATIVE_ARGS
*
cum
,
s390_function_arg
(
cum
,
mode
,
type
,
named
)
enum
machine_mode
mode
,
tree
type
,
int
named
)
CUMULATIVE_ARGS
*
cum
;
enum
machine_mode
mode
;
tree
type
;
int
named
ATTRIBUTE_UNUSED
;
{
{
if
(
s390_function_arg_pass_by_reference
(
mode
,
type
))
if
(
s390_function_arg_pass_by_reference
(
mode
,
type
))
return
0
;
return
0
;
...
@@ -2635,14 +2818,27 @@ s390_function_arg (CUMULATIVE_ARGS * cum,
...
@@ -2635,14 +2818,27 @@ s390_function_arg (CUMULATIVE_ARGS * cum,
}
}
/* Builtin va_list stuff
/* Create and return the va_list datatype.
va_list is a structure of four elements:
__gpr: number of named args passed in general purpose register
On S/390, va_list is an array type equivalent to
__gpr: number of named args passed in floating purpose register
__overflow_arg_area: address of area, where arguments are passed
typedef struct __va_list_tag
if they do not fit in gprs 2 to 6 and fpr 0 and 2
{
__reg_save_area: address, where register passed args are saved
long __gpr;
in prologue. */
long __fpr;
void *__overflow_arg_area;
void *__reg_save_area;
} va_list[1];
where __gpr and __fpr hold the number of general purpose
or floating point arguments used up to now, respectively,
__overflow_arg_area points to the stack location of the
next argument passed on the stack, and __reg_save_area
always points to the start of the register area in the
call frame of the current function. The function prologue
saves all registers used for argument passing into this
area if the function uses variable arguments. */
tree
tree
s390_build_va_list
()
s390_build_va_list
()
...
@@ -2681,17 +2877,25 @@ s390_build_va_list ()
...
@@ -2681,17 +2877,25 @@ s390_build_va_list ()
return
build_array_type
(
record
,
build_index_type
(
size_zero_node
));
return
build_array_type
(
record
,
build_index_type
(
size_zero_node
));
}
}
/* Builtin va_start
/* Implement va_start by filling the va_list structure VALIST.
The va_list struct is set with the values.
STDARG_P is true if implementing __builtin_stdarg_va_start,
gpr: compile time known got out of current_function_args_info
false if implementing __builtin_varargs_va_start. NEXTARG
fpr: compile time known got out of current_function_args_info
points to the first anonymous stack argument.
overflow_arg_area: address passed with register 7 (incoming args register)
(setup in prologue)
The following global variables are used to initalize
reg_save_area: address of save area where first 5 gprs and 2 fprs sare
the va_list structure:
saved (saved in prologue). */
current_function_args_info:
holds number of gprs and fprs used for named arguments.
current_function_arg_offset_rtx:
holds the offset of the first anonymous stack argument
(relative to the virtual arg pointer). */
void
void
s390_va_start
(
int
stdarg_p
,
tree
valist
,
rtx
nextarg
)
s390_va_start
(
stdarg_p
,
valist
,
nextarg
)
int
stdarg_p
;
tree
valist
;
rtx
nextarg
ATTRIBUTE_UNUSED
;
{
{
HOST_WIDE_INT
n_gpr
,
n_fpr
;
HOST_WIDE_INT
n_gpr
,
n_fpr
;
int
off
;
int
off
;
...
@@ -2748,10 +2952,11 @@ s390_va_start (int stdarg_p, tree valist, rtx nextarg)
...
@@ -2748,10 +2952,11 @@ s390_va_start (int stdarg_p, tree valist, rtx nextarg)
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
}
}
/* Implement va_arg by updating the va_list structure
/* Builtin va_arg.
VALIST as required to retrieve an argument of type
TYPE, and returning that argument.
Works like following
:
Generates code equivalent to
:
if (integral value) {
if (integral value) {
if (size <= 4 && args.gpr < 5 ||
if (size <= 4 && args.gpr < 5 ||
...
@@ -2771,9 +2976,10 @@ s390_va_start (int stdarg_p, tree valist, rtx nextarg)
...
@@ -2771,9 +2976,10 @@ s390_va_start (int stdarg_p, tree valist, rtx nextarg)
ret = **args.overflow_arg_area++;
ret = **args.overflow_arg_area++;
} */
} */
rtx
rtx
s390_va_arg
(
tree
valist
,
tree
type
)
s390_va_arg
(
valist
,
type
)
tree
valist
;
tree
type
;
{
{
tree
f_gpr
,
f_fpr
,
f_ovf
,
f_sav
;
tree
f_gpr
,
f_fpr
,
f_ovf
,
f_sav
;
tree
gpr
,
fpr
,
ovf
,
sav
,
reg
,
t
,
u
;
tree
gpr
,
fpr
,
ovf
,
sav
,
reg
,
t
,
u
;
...
@@ -2932,13 +3138,16 @@ s390_va_arg (tree valist, tree type)
...
@@ -2932,13 +3138,16 @@ s390_va_arg (tree valist, tree type)
return
addr_rtx
;
return
addr_rtx
;
}
}
/* Implementation of Trampoline
Gpr 1 is used as base register and for the jump
/* Output assembly code for the trampoline template to
to the nested function.
stdio stream FILE.
Gpr 0 is static chain. */
On S/390, we use gpr 1 internally in the trampoline code;
gpr 0 is used to hold the static chain. */
void
void
s390_trampoline_template
(
FILE
*
file
)
s390_trampoline_template
(
file
)
FILE
*
file
;
{
{
if
(
TARGET_64BIT
)
if
(
TARGET_64BIT
)
{
{
...
@@ -2960,6 +3169,10 @@ s390_trampoline_template (FILE * file)
...
@@ -2960,6 +3169,10 @@ s390_trampoline_template (FILE * file)
}
}
}
}
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
CXT is an RTX for the static chain value for the function. */
void
void
s390_initialize_trampoline
(
addr
,
fnaddr
,
cxt
)
s390_initialize_trampoline
(
addr
,
fnaddr
,
cxt
)
rtx
addr
;
rtx
addr
;
...
@@ -2969,9 +3182,9 @@ s390_initialize_trampoline (addr, fnaddr, cxt)
...
@@ -2969,9 +3182,9 @@ s390_initialize_trampoline (addr, fnaddr, cxt)
emit_move_insn
(
gen_rtx
emit_move_insn
(
gen_rtx
(
MEM
,
Pmode
,
(
MEM
,
Pmode
,
memory_address
(
Pmode
,
memory_address
(
Pmode
,
plus_constant
(
addr
,(
TARGET_64BIT
?
20
:
12
)
))),
cxt
);
plus_constant
(
addr
,
(
TARGET_64BIT
?
20
:
12
)
))),
cxt
);
emit_move_insn
(
gen_rtx
emit_move_insn
(
gen_rtx
(
MEM
,
Pmode
,
(
MEM
,
Pmode
,
memory_address
(
Pmode
,
memory_address
(
Pmode
,
plus_constant
(
addr
,(
TARGET_64BIT
?
28
:
16
)
))),
fnaddr
);
plus_constant
(
addr
,
(
TARGET_64BIT
?
28
:
16
)
))),
fnaddr
);
}
}
gcc/config/s390/s390.h
View file @
994fe660
...
@@ -48,22 +48,22 @@ extern int target_flags;
...
@@ -48,22 +48,22 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
#define TARGET_SWITCHES \
{ { "hard-float", 1,N_("Use hardware fp")}, \
{ { "hard-float", 1,
N_("Use hardware fp")}, \
{ "soft-float", -1,N_("Don't use hardware fp")}, \
{ "soft-float", -1,
N_("Don't use hardware fp")}, \
{ "backchain", 2,N_("Set backchain")}, \
{ "backchain", 2,
N_("Set backchain")}, \
{ "no-backchain", -2,N_("Don't set backchain (faster, but debug harder")}, \
{ "no-backchain", -2,
N_("Don't set backchain (faster, but debug harder")}, \
{ "small-exec", 4,N_("Use bras for execucable < 64k")}, \
{ "small-exec", 4,
N_("Use bras for execucable < 64k")}, \
{ "no-small-exec",-4,N_("Don't use bras")}, \
{ "no-small-exec",-4,
N_("Don't use bras")}, \
{ "debug", 8,N_("Additional debug prints")}, \
{ "debug", 8,
N_("Additional debug prints")}, \
{ "no-debug", -8,N_("Don't print additional debug prints")}, \
{ "no-debug", -8,
N_("Don't print additional debug prints")}, \
{ "64", 16,N_("64 bit mode")}, \
{ "64", 16,
N_("64 bit mode")}, \
{ "31", -16,N_("31 bit mode")}, \
{ "31", -16,
N_("31 bit mode")}, \
{ "mvcle", 32,N_("mvcle use")}, \
{ "mvcle", 32,
N_("mvcle use")}, \
{ "no-mvcle", -32,N_("mvc&ex")}, \
{ "no-mvcle", -32,
N_("mvc&ex")}, \
{ "", TARGET_DEFAULT, 0 } }
{ "", TARGET_DEFAULT, 0 } }
/* Define this to change the optimizations performed by default. */
/* Define this to change the optimizations performed by default. */
#define OPTIMIZATION_OPTIONS(LEVEL,
SIZE) optimization_options(LEVEL,
SIZE)
#define OPTIMIZATION_OPTIONS(LEVEL,
SIZE) optimization_options(LEVEL,
SIZE)
/* The current function count for create unique internal labels. */
/* The current function count for create unique internal labels. */
...
@@ -213,7 +213,7 @@ if (INTEGRAL_MODE_P (MODE) && \
...
@@ -213,7 +213,7 @@ if (INTEGRAL_MODE_P (MODE) && \
/* Standard register usage. */
/* Standard register usage. */
#define INT_REGNO_P(N) ( (N) >= 0 && (N) < 16 )
#define INT_REGNO_P(N) ( (
int)(
N) >= 0 && (N) < 16 )
#ifdef IEEE_FLOAT
#ifdef IEEE_FLOAT
#define FLOAT_REGNO_P(N) ( (N) >= 16 && (N) < 32 )
#define FLOAT_REGNO_P(N) ( (N) >= 16 && (N) < 32 )
#else
#else
...
@@ -682,14 +682,14 @@ CUMULATIVE_ARGS;
...
@@ -682,14 +682,14 @@ CUMULATIVE_ARGS;
may not be available.) */
may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
s390_function_arg_advance(&CUM, MODE, TYPE, NAMED)
s390_function_arg_advance
(&CUM, MODE, TYPE, NAMED)
/* Define where to put the arguments to a function. Value is zero to push
/* Define where to put the arguments to a function. Value is zero to push
the argument on the stack, or a hard register in which to store the
the argument on the stack, or a hard register in which to store the
argument. */
argument. */
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
s390_function_arg(&CUM, MODE, TYPE, NAMED)
s390_function_arg
(&CUM, MODE, TYPE, NAMED)
/* Define where to expect the arguments of a function. Value is zero, if
/* Define where to expect the arguments of a function. Value is zero, if
the argument is on the stack, or a hard register in which the argument
the argument is on the stack, or a hard register in which the argument
...
@@ -808,7 +808,7 @@ CUMULATIVE_ARGS;
...
@@ -808,7 +808,7 @@ CUMULATIVE_ARGS;
#define FUNCTION_PROFILER(FILE, LABELNO) \
#define FUNCTION_PROFILER(FILE, LABELNO) \
do { \
do { \
extern rtx s390_profile[]; \
extern rtx s390_profile[]; \
extern
s390_pool_count;
\
extern
int s390_pool_count;
\
rtx tmp; \
rtx tmp; \
static char label[128]; \
static char label[128]; \
fprintf (FILE, "# function profiler \n"); \
fprintf (FILE, "# function profiler \n"); \
...
@@ -1101,7 +1101,7 @@ do \
...
@@ -1101,7 +1101,7 @@ do \
{ \
{ \
rtx tmp[1]; \
rtx tmp[1]; \
fprintf (FILE, "# block profiler %d block %d \n", \
fprintf (FILE, "# block profiler %d block %d \n", \
profile_block_flag,BLOCKNO); \
profile_block_flag,
BLOCKNO); \
output_asm_insn ("ipm 14", tmp); \
output_asm_insn ("ipm 14", tmp); \
output_asm_insn ("aghi 15,-224", tmp); \
output_asm_insn ("aghi 15,-224", tmp); \
output_asm_insn ("stmg 14,5,160(15)", tmp); \
output_asm_insn ("stmg 14,5,160(15)", tmp); \
...
@@ -1325,7 +1325,7 @@ do { \
...
@@ -1325,7 +1325,7 @@ do { \
((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
#define REGNO_OK_FOR_FP_P(REGNO) \
#define REGNO_OK_FOR_FP_P(REGNO) \
FLOAT_REGNO_P(REGNO)
FLOAT_REGNO_P
(REGNO)
/* Now macros that check whether X is a register and also,
/* Now macros that check whether X is a register and also,
strictly, whether it is in a specified class. */
strictly, whether it is in a specified class. */
...
@@ -1531,7 +1531,7 @@ do { \
...
@@ -1531,7 +1531,7 @@ do { \
After generation of rtl, the compiler makes no further distinction
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
between pointers and any other objects of this machine mode. */
#define Pmode (
TARGET_64BIT ? DImode : SImode
)
#define Pmode (
(enum machine_mode) (TARGET_64BIT ? DImode : SImode)
)
/* A function address in a call instruction is a byte address (for
/* A function address in a call instruction is a byte address (for
indexing purposes) so give the MEM rtx a byte's mode. */
indexing purposes) so give the MEM rtx a byte's mode. */
...
@@ -1689,7 +1689,7 @@ do { \
...
@@ -1689,7 +1689,7 @@ do { \
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. */
return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP,
X,Y)
\
#define SELECT_CC_MODE(OP,
X, Y)
\
( (OP) == EQ || (OP) == NE ? CCZmode \
( (OP) == EQ || (OP) == NE ? CCZmode \
: (OP) == LE || (OP) == LT || \
: (OP) == LE || (OP) == LT || \
(OP) == GE || (OP) == GT ? CCSmode \
(OP) == GE || (OP) == GT ? CCSmode \
...
@@ -1703,8 +1703,6 @@ do { \
...
@@ -1703,8 +1703,6 @@ do { \
since it hasn't been defined! */
since it hasn't been defined! */
extern
struct
rtx_def
*
s390_compare_op0
,
*
s390_compare_op1
;
extern
struct
rtx_def
*
s390_compare_op0
,
*
s390_compare_op1
;
extern
int
s390_match_ccmode
PARAMS
((
struct
rtx_def
*
,
int
));
/* How to refer to registers in assembler output. This sequence is
/* How to refer to registers in assembler output. This sequence is
...
@@ -1809,7 +1807,7 @@ extern int s390_nr_constants;
...
@@ -1809,7 +1807,7 @@ extern int s390_nr_constants;
/* Mark entries referenced by other entries */
\
/* Mark entries referenced by other entries */
\
for (pool = first_pool; pool; pool = pool->next) \
for (pool = first_pool; pool; pool = pool->next) \
if (pool->mark) \
if (pool->mark) \
mark_constants(pool->constant); \
mark_constants
(pool->constant); \
\
\
s390_asm_output_pool_prologue (FILE, FUNNAME, fndecl, size); \
s390_asm_output_pool_prologue (FILE, FUNNAME, fndecl, size); \
}
}
...
...
gcc/config/s390/s390.md
View file @
994fe660
...
@@ -796,6 +796,9 @@
...
@@ -796,6 +796,9 @@
case 4: /* m <- m */
case 4: /* m <- m */
return \"mvc\\t%O0(16,%R0),%1\";
return \"mvc\\t%O0(16,%R0),%1\";
default:
abort();
}
}
}"
}"
[
(set_attr "op_type" "NN,NN,RS,RS,SS")
[
(set_attr "op_type" "NN,NN,RS,RS,SS")
...
@@ -873,6 +876,9 @@
...
@@ -873,6 +876,9 @@
case 4: /* m <- m */
case 4: /* m <- m */
return \"mvc\\t%O0(8,%R0),%1\";
return \"mvc\\t%O0(8,%R0),%1\";
default:
abort();
}
}
}"
}"
[
(set_attr "op_type" "NN,NN,RS,RS,SS")
[
(set_attr "op_type" "NN,NN,RS,RS,SS")
...
@@ -1085,6 +1091,9 @@
...
@@ -1085,6 +1091,9 @@
case 6: /* m <- m */
case 6: /* m <- m */
return \"mvc\\t%O0(8,%R0),%1\";
return \"mvc\\t%O0(8,%R0),%1\";
default:
abort();
}
}
}"
}"
[
(set_attr "op_type" "RR,RX,RX,RS,RS,NN,SS")
[
(set_attr "op_type" "RR,RX,RX,RS,RS,NN,SS")
...
@@ -1132,6 +1141,9 @@
...
@@ -1132,6 +1141,9 @@
case 3: /* m <- m */
case 3: /* m <- m */
return \"mvc\\t%O0(8,%R0),%1\";
return \"mvc\\t%O0(8,%R0),%1\";
default:
abort();
}
}
}"
}"
[
(set_attr "op_type" "NN,RS,RS,SS")
[
(set_attr "op_type" "NN,RS,RS,SS")
...
@@ -2442,7 +2454,7 @@
...
@@ -2442,7 +2454,7 @@
operands
[
1
]
= force_reg (DFmode,operands
[
1
]
);
operands
[
1
]
= force_reg (DFmode,operands
[
1
]
);
emit_insn (gen_cmpdf (operands
[
1
]
, force_const_mem (DFmode,
emit_insn (gen_cmpdf (operands
[
1
]
, force_const_mem (DFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x80000000, DFmode))));
CONST_DOUBLE_FROM_REAL_VALUE (0x80000000
ULL
, DFmode))));
emit_jump_insn (gen_blt (label1));
emit_jump_insn (gen_blt (label1));
emit_insn (gen_subdf3 (temp, operands
[
1
]
, force_const_mem (DFmode,
emit_insn (gen_subdf3 (temp, operands
[
1
]
, force_const_mem (DFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
...
@@ -2583,7 +2595,7 @@
...
@@ -2583,7 +2595,7 @@
operands
[
1
]
= force_reg (SFmode, operands
[
1
]
);
operands
[
1
]
= force_reg (SFmode, operands
[
1
]
);
emit_insn (gen_cmpsf (operands
[
1
]
, force_const_mem (SFmode,
emit_insn (gen_cmpsf (operands
[
1
]
, force_const_mem (SFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x80000000, SFmode))));
CONST_DOUBLE_FROM_REAL_VALUE (0x80000000
ULL
, SFmode))));
emit_jump_insn (gen_blt (label1));
emit_jump_insn (gen_blt (label1));
emit_insn (gen_subsf3 (temp, operands
[
1
]
, force_const_mem (SFmode,
emit_insn (gen_subsf3 (temp, operands
[
1
]
, force_const_mem (SFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
...
@@ -2669,7 +2681,7 @@
...
@@ -2669,7 +2681,7 @@
rtx temp = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
rtx temp = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
rtx two31 = force_const_mem (DFmode,
rtx two31 = force_const_mem (DFmode,
gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
0x80000000
, 0x4E000000
));
0x80000000
U, 0x4E000000U
));
emit_insn (gen_floatsidf2_ibm (operands[0], operands[1], two31, temp));
emit_insn (gen_floatsidf2_ibm (operands[0], operands[1], two31, temp));
DONE;
DONE;
...
...
gcc/config/s390/t-linux
View file @
994fe660
# The crtbegin and crtend must not depend on a small GOT
# The crtbegin and crtend must not depend on a small GOT
CRTSTUFF_T_CFLAGS = -O2 -fPIC
CRTSTUFF_T_CFLAGS = -O2 -fPIC
linux.o: $(srcdir)/config/s390/linux.c $(CONFIG_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/s390/linux.c
# Compile libgcc2.a with pic.
# Compile libgcc2.a with pic.
TARGET_LIBGCC2_CFLAGS = -fPIC -include $(srcdir)/config/s390/fixdfdi.h
TARGET_LIBGCC2_CFLAGS = -fPIC -include $(srcdir)/config/s390/fixdfdi.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