From 4d6c607f2e7c6a0a443e33356eaf2bcd5ff8eb17 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Fri, 11 Apr 1997 20:48:54 +0000 Subject: [PATCH] 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 --- gcc/config/m32r/m32r.c | 28 +++++++++++++++++ gcc/config/m32r/m32r.h | 2 +- gcc/config/m32r/m32r.md | 68 +++++++++++++++++++++++++++++++++++------ 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index b915553fa9e..9a36ec82dfc 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 805de455985..e199ff9923b 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 5d11a7bea4b..814d41ddfc0 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" -- 2.30.2