re PR target/65192 ([avr-tiny] ICE in tiny_valid_direct_memory_access_range)
authorGeorg-Johann Lay <avr@gjlay.de>
Thu, 26 Feb 2015 19:43:54 +0000 (19:43 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Thu, 26 Feb 2015 19:43:54 +0000 (19:43 +0000)
PR target/65192
* config/avr/avr-protos.h (tiny_valid_direct_memory_access_range):
Remove.
* config/avr/avr.c: Same.
(avr_legitimate_address_p) <AVR_TINY, CONSTANT_ADDRESS_P>:
Refuse any constant address not in 0..0xbf.
* config/avr/avr.md (*mov<mode>, *movsf): Remove
tiny_valid_direct_memory_access_range from insn conditions.
(mov<mode>): Don't special-case expansion of avrtiny addresses.

From-SVN: r221029

gcc/ChangeLog
gcc/config/avr/avr-protos.h
gcc/config/avr/avr.c
gcc/config/avr/avr.md

index 4e8f5478b46540a957043f073cf9592e16134945..40499826dc32ca02493bd0ac7349b3aa294fdb91 100644 (file)
@@ -1,3 +1,15 @@
+2015-02-26  Georg-Johann Lay  <avr@gjlay.de>
+
+       PR target/65192
+       * config/avr/avr-protos.h (tiny_valid_direct_memory_access_range):
+       Remove.
+       * config/avr/avr.c: Same.
+       (avr_legitimate_address_p) <AVR_TINY, CONSTANT_ADDRESS_P>:
+       Refuse any constant address not in 0..0xbf.
+       * config/avr/avr.md (*mov<mode>, *movsf): Remove
+       tiny_valid_direct_memory_access_range from insn conditions.
+       (mov<mode>): Don't special-case expansion of avrtiny addresses.
+
 2015-02-26  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/61142
index 40f1486e1bfae6f1d100c8531d9e670fea368ee3..b5de42709e593f0b58e1cfbd27b8d580e0f0814a 100644 (file)
@@ -46,7 +46,6 @@ extern void avr_init_cumulative_args (CUMULATIVE_ARGS*, tree, rtx, tree);
 
 #ifdef RTX_CODE
 extern int avr_hard_regno_call_part_clobbered (unsigned, machine_mode);
-extern bool tiny_valid_direct_memory_access_range(rtx, machine_mode);
 extern const char *output_movqi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movhi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movsisf (rtx_insn *insn, rtx operands[], int *l);
index 7d0a13d79f057bccada1f11f94aec2d63140030c..07d7bafd54a5683c4bc727c0d36d7a9f00ae7832 100644 (file)
@@ -1823,6 +1823,16 @@ avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
       break;
     }
 
+  if (AVR_TINY
+      && CONSTANT_ADDRESS_P (x))
+    {
+      /* avrtiny's load / store instructions only cover addresses 0..0xbf:
+         IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf.  */
+
+      ok = (CONST_INT_P (x)
+            && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)));
+    }
+
   if (avr_log.legitimate_address_p)
     {
       avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
@@ -3210,37 +3220,6 @@ avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
 }
 
 
-/* AVRTC-579
-   If OP is a symbol or a constant expression with value > 0xbf
-   return FALSE, otherwise TRUE.
-   This check is used to avoid LDS / STS instruction with invalid memory
-   access range (valid range 0x40..0xbf).  For I/O operand range 0x0..0x3f,
-   IN / OUT instruction will be generated.  */
-
-bool
-tiny_valid_direct_memory_access_range (rtx op, machine_mode mode)
-{
-  rtx x;
-
-  if (!AVR_TINY)
-    return true;
-
-  x = XEXP (op,0);
-
-  if (MEM_P (op) && x && GET_CODE (x) == SYMBOL_REF)
-    {
-      return false;
-    }
-
-  if (MEM_P (op) && x && (CONSTANT_ADDRESS_P (x))
-      && !(IN_RANGE (INTVAL (x), 0, 0xC0 - GET_MODE_SIZE (mode))))
-    {
-      return false;
-    }
-
-  return true;
-}
-
 const char*
 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
 {
index d6d930c74b68c31c0d165bf474f4e654f8cd9aa6..1b39ddbd158d13d3e831e1b1b527877aa2e9c4d3 100644 (file)
         emit_insn (gen_load<mode>_libgcc (dest, src));
         DONE;
       }
-
-    // AVRTC-579
-    // If the source operand expression is out of range for LDS instruction
-    // copy source operand expression to register.
-    // For tiny core, LDS instruction's memory access range limited to 0x40..0xbf.
-
-    if (!tiny_valid_direct_memory_access_range (src, <MODE>mode))
-      {
-        rtx srcx = XEXP (src, 0);
-        operands[1] = src = replace_equiv_address (src, copy_to_mode_reg (GET_MODE (srcx), srcx));
-        emit_move_insn (dest, src);
-        DONE;
-      }
-
-    // AVRTC-579
-    // If the destination operand expression is out of range for STS instruction
-    // copy destination operand expression to register.
-    // For tiny core, STS instruction's memory access range limited to 0x40..0xbf.
-
-    if (!tiny_valid_direct_memory_access_range (dest, <MODE>mode))
-      {
-        rtx destx = XEXP (dest, 0);
-        operands[0] = dest = replace_equiv_address (dest, copy_to_mode_reg (GET_MODE (destx), destx));
-        emit_move_insn (dest, src);
-        DONE;
-      }
   })
 
 ;;========================================================================
 (define_insn "mov<mode>_insn"
   [(set (match_operand:ALL1 0 "nonimmediate_operand" "=r    ,d    ,Qm   ,r ,q,r,*r")
         (match_operand:ALL1 1 "nox_general_operand"   "r Y00,n Ynn,r Y00,Qm,r,q,i"))]
-  "(register_operand (operands[0], <MODE>mode)
-    || reg_or_0_operand (operands[1], <MODE>mode))
-   /* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
-      though access range is checked during define_expand, it is required
-      here to avoid merging RTXes during combine pass.  */
-   && tiny_valid_direct_memory_access_range (operands[0], QImode)
-   && tiny_valid_direct_memory_access_range (operands[1], QImode)"
+  "register_operand (operands[0], <MODE>mode)
+    || reg_or_0_operand (operands[1], <MODE>mode)"
   {
     return output_movqi (insn, operands, NULL);
   }
 (define_insn "*mov<mode>"
   [(set (match_operand:ALL2 0 "nonimmediate_operand" "=r,r  ,r,m    ,d,*r,q,r")
         (match_operand:ALL2 1 "nox_general_operand"   "r,Y00,m,r Y00,i,i ,r,q"))]
-  "(register_operand (operands[0], <MODE>mode)
-    || reg_or_0_operand (operands[1], <MODE>mode))
-   /* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
-      though access range is checked during define_expand, it is required
-      here to avoid merging RTXes during combine pass.  */
-   && tiny_valid_direct_memory_access_range (operands[0], HImode)
-   && tiny_valid_direct_memory_access_range (operands[1], HImode)"
+  "register_operand (operands[0], <MODE>mode)
+   || reg_or_0_operand (operands[1], <MODE>mode)"
   {
     return output_movhi (insn, operands, NULL);
   }
 (define_insn "*mov<mode>"
   [(set (match_operand:ALL4 0 "nonimmediate_operand" "=r,r  ,r ,Qm   ,!d,r")
         (match_operand:ALL4 1 "nox_general_operand"   "r,Y00,Qm,r Y00,i ,i"))]
-  "(register_operand (operands[0], <MODE>mode)
-    || reg_or_0_operand (operands[1], <MODE>mode))
-   /* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
-      though access range is checked during define_expand, it is required
-      here to avoid merging RTXes during combine pass.  */
-   && tiny_valid_direct_memory_access_range (operands[0], SImode)
-   && tiny_valid_direct_memory_access_range (operands[1], SImode)"
+  "register_operand (operands[0], <MODE>mode)
+   || reg_or_0_operand (operands[1], <MODE>mode)"
   {
     return output_movsisf (insn, operands, NULL);
   }
 (define_insn "*movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
         (match_operand:SF 1 "nox_general_operand"   "r,G,Qm,rG,F ,F"))]
-  "(register_operand (operands[0], SFmode)
-    || reg_or_0_operand (operands[1], SFmode))
-   /* Skip if operands are out of lds/sts memory access range(0x40..0xbf)
-      though access range is checked during define_expand, it is required
-      here to avoid merging rtls during combine pass.  */
-   && tiny_valid_direct_memory_access_range (operands[0], SFmode)
-   && tiny_valid_direct_memory_access_range (operands[1], SFmode)"
+  "register_operand (operands[0], SFmode)
+   || reg_or_0_operand (operands[1], SFmode)"
   {
     return output_movsisf (insn, operands, NULL);
   }