summaryrefslogtreecommitdiff
path: root/gcc/config/picochip/picochip.c
diff options
context:
space:
mode:
authorhariharans <hariharans@138bc75d-0d04-0410-961f-82ee72b054a4>2010-04-30 09:40:21 +0000
committerhariharans <hariharans@138bc75d-0d04-0410-961f-82ee72b054a4>2010-04-30 09:40:21 +0000
commit1b7aefdbfa2539b169c00647ac09f0fab39af677 (patch)
tree4d431d1801fd8cfcc9e1bf12e77b84f78e83e81a /gcc/config/picochip/picochip.c
parentb7e3aeb1d14c179214a5509ae0b031dd725c377d (diff)
downloadgcc-1b7aefdbfa2539b169c00647ac09f0fab39af677.tar.gz
* config/picochip/picochip.c (picochip_legitimize_address): Define.
Use this function to do machine-specific conversion. (picochip_legitimize_reload_address): Likewise. (picochip_legitimate_address_p): Check valid base register only if strict. (picochip_check_conditional_copy): Check for modw only if opnd is register. * config/picochip/picochip.h (LEGITIMIZE_RELOAD_ADDRESS): Use this to call the function in c. * config/picochip/picochip-protos.h (picochip_legitimize_reload_address): Define. * config/picochip/picochip.md (supported_compare1): Define. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158927 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/picochip/picochip.c')
-rw-r--r--gcc/config/picochip/picochip.c159
1 files changed, 154 insertions, 5 deletions
diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c
index 03df3fbc2ce..0d6db586b38 100644
--- a/gcc/config/picochip/picochip.c
+++ b/gcc/config/picochip/picochip.c
@@ -96,6 +96,10 @@ bool picochip_rtx_costs (rtx x, int code, int outer_code, int* total, bool speed
bool picochip_return_in_memory(const_tree type,
const_tree fntype ATTRIBUTE_UNUSED);
bool picochip_legitimate_address_p (enum machine_mode, rtx, bool);
+rtx picochip_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode);
+int picochip_legitimize_reload_address (rtx *x, enum machine_mode mode,
+ int opnum, int type, int ind_levels);
rtx picochip_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED);
rtx picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
@@ -279,6 +283,9 @@ static char picochip_get_vliw_alu_id (void);
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P picochip_legitimate_address_p
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS picochip_legitimize_address
+
/* Loading and storing QImode values to and from memory
usually requires a scratch register. */
#undef TARGET_SECONDARY_RELOAD
@@ -1268,9 +1275,13 @@ picochip_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
rtx base = XEXP (x, 0);
rtx offset = XEXP (x, 1);
+ if (strict && !REGNO_OK_FOR_BASE_P (REGNO(base)))
+ {
+ valid = 0;
+ break;
+ }
valid = (REG == GET_CODE (base) &&
- REGNO_OK_FOR_BASE_P (REGNO(base)) &&
picochip_legitimate_address_register (base, strict) &&
CONST_INT == GET_CODE (offset) &&
picochip_const_ok_for_base (mode, REGNO (base),
@@ -1311,6 +1322,144 @@ picochip_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
}
+/* For all memory operations, picochip allows a uconst4 offset value. It
+ is hence beneficial to turn an
+ addr = <reg + long_const>
+ ld/st addr
+
+ into
+
+ X = reg + long_const & FFF0
+ diff = long_const - (long_const & FFF0)
+ ld/st <X + diff>
+
+ X can be reused in subsequent memory operations.
+ */
+rtx
+picochip_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ if (!optimize)
+ return x;
+
+ unsigned mask_val;
+ // Depending on mode, the offsets allowed are either 16/32/64.
+ switch (mode)
+ {
+ case QImode:
+ mask_val = 0xFFF0;
+ break;
+ case HImode:
+ mask_val = 0xFFE0;
+ break;
+ case SImode:
+ mask_val = 0xFFC0;
+ break;
+ default:
+ return x;
+ }
+
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ int offset = INTVAL (XEXP (x, 1));
+ // Ignore cases with negative offsets.
+ if (offset < 0)
+ return x;
+ int high_val = offset & mask_val;
+ int low_val = offset - high_val;
+ if (high_val != 0)
+ {
+ rtx temp_reg = force_reg (Pmode, gen_rtx_PLUS (Pmode, XEXP (x, 0), GEN_INT(high_val)));
+ x = gen_rtx_PLUS (Pmode, temp_reg, GEN_INT(low_val));
+ return x;
+ }
+ }
+ return x;
+}
+
+/* For all memory operations, picochip allows a uconst4 offset value. It
+ is hence beneficial to turn an
+ addr = <reg + long_const>
+ ld/st addr
+
+ into
+
+ X = reg + long_const & FFF0
+ diff = long_const - (long_const & FFF0)
+ ld/st <X + diff>
+
+ X can be reused in subsequent memory operations.
+ */
+int
+picochip_legitimize_reload_address (rtx *x,
+ enum machine_mode mode,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED)
+{
+ if (picochip_symbol_offset(*x))
+ {
+ *x = gen_rtx_CONST(mode, *x);
+ return 0;
+ }
+ if (!optimize)
+ return 0;
+
+ /* We should recognise addresses that we created.*/
+ if (GET_CODE (*x) == PLUS
+ && GET_CODE (XEXP (*x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (*x, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (*x, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (*x, 1)) == CONST_INT)
+ {
+ push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (*x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ return 1;
+ }
+
+ unsigned mask_val;
+ // Depending on mode, the offsets allowed are either 16/32/64.
+ switch (mode)
+ {
+ case QImode:
+ mask_val = 0xFFF0;
+ break;
+ case HImode:
+ mask_val = 0xFFE0;
+ break;
+ case SImode:
+ mask_val = 0xFFC0;
+ break;
+ default:
+ return 0;
+ }
+
+ if (GET_CODE (*x) == PLUS
+ && GET_CODE (XEXP (*x, 0)) == REG
+ && GET_CODE (XEXP (*x, 1)) == CONST_INT)
+ {
+ int offset = INTVAL (XEXP (*x, 1));
+ // Ignore cases with negative offsets.
+ if (offset < 0)
+ return 0;
+ int high_val = offset & mask_val;
+ int low_val = offset - high_val;
+ if (high_val != 0)
+ {
+ rtx temp_reg = gen_rtx_PLUS (Pmode, XEXP (*x, 0), GEN_INT(high_val));
+ *x = gen_rtx_PLUS (Pmode, temp_reg, GEN_INT(low_val));
+ push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (*x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* Detect an rtx which matches (plus (symbol_ref) (const_int)). */
int
picochip_symbol_offset (rtx operand)
@@ -4395,11 +4544,11 @@ picochip_check_conditional_copy (rtx * operands)
handled using logical operations (e.g., SIreg != 0 when low ||
high). Need to find test cases to provoke this though (fixunssfdi
in libgcc does, but is complicated). */
- if (GET_MODE (branch_op_0) != HImode ||
- !(register_operand (branch_op_0, GET_MODE (branch_op_0))))
+ if (register_operand(branch_op_0, GET_MODE(branch_op_0)) &&
+ GET_MODE(branch_op_0) != HImode)
return 0;
- if (GET_MODE (branch_op_1) != HImode ||
- !(picochip_comparison_operand (branch_op_1, GET_MODE (branch_op_1))))
+ if (register_operand(branch_op_1, GET_MODE(branch_op_1)) &&
+ GET_MODE(branch_op_1) != HImode)
return 0;
return 1;