OSDN Git Service

* m32r/m32r.h (UPPER16_P): Fix calculation.
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Apr 1997 20:48:54 +0000 (20:48 +0000)
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Apr 1997 20:48:54 +0000 (20:48 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@13857 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/m32r/m32r.c
gcc/config/m32r/m32r.h
gcc/config/m32r/m32r.md

index b915553..9a36ec8 100644 (file)
@@ -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;
index 805de45..e199ff9 100644 (file)
@@ -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)
index 5d11a7b..814d41d 100644 (file)
   ""
   "
 {
-  /* 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;
   "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
   ""
   "@
    and %0,%2
-   and3 %0,%1,%#%2"
+   and3 %0,%1,%#%2 ; %X2"
   [(set_attr "type" "binary")])
 
 (define_insn "iorsi3"
   ""
   "@
    or %0,%2
-   or3 %0,%1,%#%2"
+   or3 %0,%1,%#%2 ; %X2"
   [(set_attr "type" "binary")])
 
 (define_insn "xorsi3"
   ""
   "@
    xor %0,%2
-   xor3 %0,%1,%#%2"
+   xor3 %0,%1,%#%2 ; %X2"
   [(set_attr "type" "binary")])
 
 (define_insn "negsi2"