aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Evans <dje@gnu.org>1997-04-11 20:48:54 +0000
committerDoug Evans <dje@gnu.org>1997-04-11 20:48:54 +0000
commit4d6c607f2e7c6a0a443e33356eaf2bcd5ff8eb17 (patch)
treec2dc6e74d32b0b6f530c64aec40a5d1856311e10
parent4e007b6eea06c7668e340e7bafc1cb94054b23e6 (diff)
downloadgcc-4d6c607f2e7c6a0a443e33356eaf2bcd5ff8eb17.zip
gcc-4d6c607f2e7c6a0a443e33356eaf2bcd5ff8eb17.tar.gz
gcc-4d6c607f2e7c6a0a443e33356eaf2bcd5ff8eb17.tar.bz2
m32r.h (UPPER16_P): Fix calculation.
* m32r/m32r.h (UPPER16_P): Fix calculation. * m32r/m32r.c (two_insn_const_operand): New function. (m32r_print_operand): Handle 'X'. * m32r/m32r.md (movsi): Tweak. (*movsi_insn): Output hex value of constants too. (movsi define_split): Add. (andsi3,orsi3,xorsi3): Output hex value of constants too. From-SVN: r13857
-rw-r--r--gcc/config/m32r/m32r.c28
-rw-r--r--gcc/config/m32r/m32r.h2
-rw-r--r--gcc/config/m32r/m32r.md68
3 files changed, 87 insertions, 11 deletions
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index b915553..9a36ec8 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -707,6 +707,22 @@ reg_or_cmp_int16_operand (op, mode)
return CMP_INT16_P (INTVAL (op));
}
+/* Return true if OP is a const_int requiring two instructions to load. */
+
+int
+two_insn_const_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ if (INT16_P (INTVAL (op))
+ || UINT24_P (INTVAL (op))
+ || UPPER16_P (INTVAL (op)))
+ return 0;
+ return 1;
+}
+
/* Return true if OP is an acceptable argument for a single word
move source. */
@@ -1667,6 +1683,18 @@ m32r_print_operand (file, x, code)
output_operand_lossage ("invalid operand to %N code");
return;
+ case 'X' :
+ /* Print a const_int in hex. Used in comments. */
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file,
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+ "0x%x",
+#else
+ "0x%lx",
+#endif
+ INTVAL (x));
+ return;
+
case '#' :
fputs (IMMEDIATE_PREFIX, file);
return;
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index 805de45..e199ff9 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -593,7 +593,7 @@ extern enum reg_class m32r_regno_reg_class[];
#define INT16_P(X) ((unsigned) ((X) + 0x8000) < 0x10000)
#define CMP_INT16_P(X) ((unsigned) ((X) - 1 + 0x8000) < 0x10000)
#define UINT16_P(X) ((unsigned) (X) < 0x10000)
-#define UPPER16_P(X) (((X) & 0xffff0000) == 0)
+#define UPPER16_P(X) (((X) & ~0xffff0000) == 0)
#define UINT24_P(X) ((unsigned) (X) < 0x1000000)
#define INT32_P(X) ((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
&& (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md
index 5d11a7b..814d41d 100644
--- a/gcc/config/m32r/m32r.md
+++ b/gcc/config/m32r/m32r.md
@@ -168,19 +168,21 @@
""
"
{
- /* Everything except mem = const or mem = mem can be done easily.
- If medium or large code model, symbols have to be loaded with seth/add3.
- Objects in the small data area are handled too. */
+ /* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
+ /* Small Data Area reference? */
if (small_data_operand (operands[1], SImode))
{
emit_insn (gen_movsi_sda (operands[0], operands[1]));
DONE;
}
- else if (addr32_operand (operands[1], SImode))
+
+ /* If medium or large code model, symbols have to be loaded with
+ seth/add3. */
+ if (addr32_operand (operands[1], SImode))
{
emit_insn (gen_movsi_addr32 (operands[0], operands[1]));
DONE;
@@ -194,15 +196,61 @@
"register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
"@
mv %0,%1
- ldi %0,%#%1
- ldi %0,%#%1
- ld24 %0,%#%1
+ ldi %0,%#%1 ; %X1
+ ldi %0,%#%1 ; %X1
+ ld24 %0,%#%1 ; %X1
seth %0,%#%T1
seth %0,%#%T1\;or3 %0,%0,%#%B1
ld %0,%1
st %1,%0"
[(set_attr "type" "move,move,move4,move4,move4,multi,load,store")])
+; Try to use a four byte / two byte pair for constants not loadable with
+; ldi, ld24, seth.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "two_insn_const_operand" ""))]
+ ""
+ [(set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))]
+ "
+{
+ unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
+ unsigned HOST_WIDE_INT tmp;
+ int shift;
+
+ /* In all cases we will emit two instructions. However we try to
+ use 2 byte instructions whereever possible. We can assume the
+ constant isn't loadable with any of ldi, ld24, or seth. */
+
+ /* See if we can load a 24 bit unsigned value and invert it. */
+ if (UINT24_P (~ val))
+ {
+ emit_insn (gen_movsi (operands[0], GEN_INT (~ val)));
+ emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
+ DONE;
+ }
+
+ /* See if we can load a 24 bit unsigned value and shift it into place.
+ 0x01fffffe is just beyond ld24's range. */
+ for (shift = 1, tmp = 0x01fffffe;
+ shift < 8;
+ ++shift, tmp <<= 1)
+ {
+ if ((val & ~tmp) == 0)
+ {
+ emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift)));
+ emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift)));
+ DONE;
+ }
+ }
+
+ /* Can't use any two byte insn, fall back to seth/or3. */
+ operands[2] = GEN_INT ((val) & 0xffff0000);
+ operands[3] = GEN_INT ((val) & 0xffff);
+}")
+
;; Small data area support.
;; The address of _SDA_BASE_ is loaded into a register and all objects in
;; the small data area are indexed off that. This is done for each reference
@@ -769,7 +817,7 @@
""
"@
and %0,%2
- and3 %0,%1,%#%2"
+ and3 %0,%1,%#%2 ; %X2"
[(set_attr "type" "binary")])
(define_insn "iorsi3"
@@ -779,7 +827,7 @@
""
"@
or %0,%2
- or3 %0,%1,%#%2"
+ or3 %0,%1,%#%2 ; %X2"
[(set_attr "type" "binary")])
(define_insn "xorsi3"
@@ -789,7 +837,7 @@
""
"@
xor %0,%2
- xor3 %0,%1,%#%2"
+ xor3 %0,%1,%#%2 ; %X2"
[(set_attr "type" "binary")])
(define_insn "negsi2"