Commit 54b695e7 by Aldy Hernandez Committed by Aldy Hernandez

rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register on e500v2.

	* config/rs6000/rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register
	on e500v2.
	(CANNOT_CHANGE_MODE_CLASS): Restrict DI mode changes on e500v2.
	(PREDICATE_CODES): Add rs6k_nonimmediate_operand.

	* config/rs6000/rs6000.c (invalid_e500_subreg): New.
	(rs6k_nonimmediate_operand): New.
	(rs6000_legitimate_offset_address_p): Handle DI modes on e500v2
	correctly.
	(legitimate_lo_sum_address_p): Same.
	(rs6000_legitimize_address): Same.
	(rs6000_legitimize_reload_address): Same.
	(rs6000_legitimate_address): Same.
	(spe_build_register_parallel): Pass DF and DC modes in a DI
	register.

	* config/rs6000/rs6000.md ("*movsi_internal1"): Change predicate
	to rs6k_nonimmediate_operand.

	* config/rs6000/spe.md ("*frob_df_di"): New.
	("*frob_di_df"): New.
	("*frob_di_df_2"): New.
	("*mov_sidf_e500_subreg0"): New.
	("*mov_sidf_e500_subreg4"): New.
	("*movdf_e500_double"): Change predicate to
	rs6k_nonimmediate_operand.

From-SVN: r93665
parent fd3395a5
2005-01-14 Aldy Hernandez <aldyh@redhat.com>
* config/rs6000/rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register
on e500v2.
(CANNOT_CHANGE_MODE_CLASS): Restrict DI mode changes on e500v2.
(PREDICATE_CODES): Add rs6k_nonimmediate_operand.
* config/rs6000/rs6000.c (invalid_e500_subreg): New.
(rs6k_nonimmediate_operand): New.
(rs6000_legitimate_offset_address_p): Handle DI modes on e500v2
correctly.
(legitimate_lo_sum_address_p): Same.
(rs6000_legitimize_address): Same.
(rs6000_legitimize_reload_address): Same.
(rs6000_legitimate_address): Same.
(spe_build_register_parallel): Pass DF and DC modes in a DI
register.
* config/rs6000/rs6000.md ("*movsi_internal1"): Change predicate
to rs6k_nonimmediate_operand.
* config/rs6000/spe.md ("*frob_df_di"): New.
("*frob_di_df"): New.
("*frob_di_df_2"): New.
("*mov_sidf_e500_subreg0"): New.
("*mov_sidf_e500_subreg4"): New.
("*movdf_e500_double"): Change predicate to
rs6k_nonimmediate_operand.
2005-01-14 Aldy Hernandez <aldyh@redhat.com>
* postreload.c (move2add_note_store): Only call
trunc_int_for_mode on scalar integers.
......
......@@ -710,6 +710,7 @@ static rtx spe_expand_builtin (tree, rtx, bool *);
static rtx spe_expand_stv_builtin (enum insn_code, tree);
static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
static bool invalid_e500_subreg (rtx, enum machine_mode);
static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
static rs6000_stack_t *rs6000_stack_info (void);
static void debug_stack_info (rs6000_stack_t *);
......@@ -3035,6 +3036,39 @@ input_operand (rtx op, enum machine_mode mode)
return 0;
}
/* Return TRUE if OP is an invalid SUBREG operation on the e500. */
static bool
invalid_e500_subreg (rtx op, enum machine_mode mode)
{
/* Reject (subreg:SI (reg:DF)). */
if (GET_CODE (op) == SUBREG
&& mode == SImode
&& REG_P (SUBREG_REG (op))
&& GET_MODE (SUBREG_REG (op)) == DFmode)
return true;
/* Reject (subreg:DF (reg:DI)). */
if (GET_CODE (op) == SUBREG
&& mode == DFmode
&& REG_P (SUBREG_REG (op))
&& GET_MODE (SUBREG_REG (op)) == DImode)
return true;
return false;
}
/* Just like nonimmediate_operand, but return 0 for invalid SUBREG's
on the e500. */
int
rs6k_nonimmediate_operand (rtx op, enum machine_mode mode)
{
if (TARGET_E500_DOUBLE
&& GET_CODE (op) == SUBREG
&& invalid_e500_subreg (op, mode))
return 0;
return nonimmediate_operand (op, mode);
}
/* Darwin, AIX increases natural record alignment to doubleword if the first
field is an FP double while the FP fields remain word aligned. */
......@@ -3248,6 +3282,14 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
return SPE_CONST_OFFSET_OK (offset);
case DImode:
/* On e500v2, we may have:
(subreg:DF (mem:DI (plus (reg) (const_int))) 0).
Which gets addressed with evldd instructions. */
if (TARGET_E500_DOUBLE)
return SPE_CONST_OFFSET_OK (offset);
if (mode == DFmode || !TARGET_POWERPC64)
extra = 4;
else if (offset & 3)
......@@ -3326,7 +3368,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
return false;
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
return false;
if (TARGET_E500_DOUBLE && mode == DFmode)
/* Restrict addressing for DI because of our SUBREG hackery. */
if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
return false;
x = XEXP (x, 1);
......@@ -3403,7 +3446,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& GET_MODE_NUNITS (mode) == 1
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
|| ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
|| (((mode != DImode && mode != DFmode) || TARGET_E500_DOUBLE)
&& mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& mode != TImode)
{
......@@ -3423,8 +3467,11 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return reg;
}
else if (SPE_VECTOR_MODE (mode)
|| (TARGET_E500_DOUBLE && mode == DFmode))
|| (TARGET_E500_DOUBLE && (mode == DFmode
|| mode == DImode)))
{
if (mode == DImode)
return NULL_RTX;
/* We accept [reg + reg] and [reg + OFFSET]. */
if (GET_CODE (x) == PLUS)
......@@ -3834,7 +3881,8 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& !SPE_VECTOR_MODE (mode)
&& !(TARGET_E500_DOUBLE && mode == DFmode)
&& !(TARGET_E500_DOUBLE && (mode == DFmode
|| mode == DImode))
&& !ALTIVEC_VECTOR_MODE (mode))
{
HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
......@@ -3942,7 +3990,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
&& !ALTIVEC_VECTOR_MODE (mode)
&& !SPE_VECTOR_MODE (mode)
&& !(TARGET_E500_DOUBLE && mode == DFmode)
/* Restrict addressing for DI because of our SUBREG hackery. */
&& !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
......@@ -5084,31 +5133,23 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
static rtx
spe_build_register_parallel (enum machine_mode mode, int gregno)
{
rtx r1, r2, r3, r4;
enum machine_mode inner = SImode;
rtx r1, r3;
if (mode == DFmode)
{
r1 = gen_rtx_REG (inner, gregno);
r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx);
r2 = gen_rtx_REG (inner, gregno + 1);
r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (4));
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
r1 = gen_rtx_REG (DImode, gregno);
r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
}
else if (mode == DCmode)
{
r1 = gen_rtx_REG (inner, gregno);
r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx);
r2 = gen_rtx_REG (inner, gregno + 1);
r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (4));
r3 = gen_rtx_REG (inner, gregno + 2);
r3 = gen_rtx_EXPR_LIST (SImode, r3, GEN_INT (8));
r4 = gen_rtx_REG (inner, gregno + 3);
r4 = gen_rtx_EXPR_LIST (SImode, r4, GEN_INT (12));
return gen_rtx_PARALLEL (mode, gen_rtvec (4, r1, r2, r3, r4));
r1 = gen_rtx_REG (DImode, gregno);
r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
r3 = gen_rtx_REG (DImode, gregno + 2);
r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8));
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3));
}
abort ();
abort();
return NULL_RTX;
}
......
......@@ -1429,6 +1429,8 @@ enum reg_class
#define CLASS_MAX_NREGS(CLASS, MODE) \
(((CLASS) == FLOAT_REGS) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
: (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS && (MODE) == DFmode) \
? 1 \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
......@@ -1442,6 +1444,8 @@ enum reg_class
? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
: (TARGET_E500_DOUBLE && (((TO) == DFmode) + ((FROM) == DFmode)) == 1) \
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
: (TARGET_E500_DOUBLE && (((TO) == DImode) + ((FROM) == DImode)) == 1) \
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
: (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
: 0)
......@@ -2588,6 +2592,7 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
{"current_file_function_operand", {SYMBOL_REF}}, \
{"input_operand", {SUBREG, MEM, REG, CONST_INT, \
CONST_DOUBLE, SYMBOL_REF}}, \
{"rs6k_nonimmediate_operand", {SUBREG, MEM, REG}}, \
{"load_multiple_operation", {PARALLEL}}, \
{"store_multiple_operation", {PARALLEL}}, \
{"lmw_operation", {PARALLEL}}, \
......
......@@ -7709,7 +7709,7 @@
(set_attr "length" "4")])
(define_insn "*movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
[(set (match_operand:SI 0 "rs6k_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
(match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))]
"gpc_reg_operand (operands[0], SImode)
|| gpc_reg_operand (operands[1], SImode)"
......
......@@ -2192,8 +2192,45 @@
(set_attr "length" "4")])
;; Double-precision floating point instructions.
;; FIXME: Add o=r option.
(define_insn "*frob_df_di"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r")
(subreg:DF (match_operand:DI 1 "input_operand" "r,m") 0))]
"TARGET_E500_DOUBLE"
"@
evmergelo %0,%H1,%L1
evldd%X1 %0,%y1")
(define_insn "*frob_di_df"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r")
(subreg:DI (match_operand:DF 1 "input_operand" "r") 0))]
"TARGET_E500_DOUBLE" /*one of these can be an mr */
"evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1"
[(set_attr "length" "8")])
(define_insn "*frob_di_df_2"
[(set (subreg:DF (match_operand:DI 0 "register_operand" "=&r") 0)
(match_operand:DF 1 "register_operand" "r"))]
"TARGET_E500_DOUBLE"
"evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1"
[(set_attr "length" "8")])
(define_insn "*mov_sidf_e500_subreg0"
[(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 0)
(match_operand:SI 1 "register_operand" "r"))]
"TARGET_E500_DOUBLE"
"evmergelo %0,%1,%0")
(define_insn "*mov_sidf_e500_subreg4"
[(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 4)
(match_operand:SI 1 "register_operand" "r"))]
"TARGET_E500_DOUBLE"
"mr %0,%1")
;; FIXME: Allow r=CONST0.
(define_insn "*movdf_e500_double"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
[(set (match_operand:DF 0 "rs6k_nonimmediate_operand" "=r,r,m")
(match_operand:DF 1 "input_operand" "r,m,r"))]
"TARGET_HARD_FLOAT && TARGET_E500_DOUBLE
&& (gpc_reg_operand (operands[0], DFmode)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment