PR target/35013, 27192
authorAndy Hutchinson <hutchinsonandy@gcc.gnu.org>
Thu, 24 Dec 2009 19:53:57 +0000 (19:53 +0000)
committerAndy Hutchinson <hutchinsonandy@gcc.gnu.org>
Thu, 24 Dec 2009 19:53:57 +0000 (19:53 +0000)
2009-12-24  Andy Hutchinson  <hutchinsonandy@gcc.gnu.org>

PR target/35013, 27192
* config/avr/avr.c (print_operand_address): Print correct program
memory address.
Add warning for large device offset addresses.
(avr_assemble_integer): Ditto.
(print_operand): Add warnings for incorrect addressing.
(out_movqi_r_mr): Tag assembler with new address codes.
(out_movhi_r_mr): Ditto.
(out_movsi_r_mr): Ditto.
(out_movqi_mr_r): Ditto.
(out_movhi_mr_r): Ditto.
(out_movsi_mr_r): Ditto.
* config/avr/predicates.md (text_segment_operand): New predicate.
* config/avr/avr.md (jump): Tag assembler with new address codes.
(call_insn): Ditto.
(call_value_insn): Ditto.
(*tablejump_lib): Ditto.
(*cbi): Ditto.
(*sbi): Ditto.
(indirect_jump): New define_expand.
(jcindirect_jump): New pattern for constant expression jump.
(njcindirect_jump): Renamed old indirect_jump.

From-SVN: r155459

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/config/avr/avr.md
gcc/config/avr/predicates.md

index f8b5fcebdcd120e6caae54069cba67cf34c76929..786021818a6d434d92135fdcbaf655f84547ffe3 100644 (file)
@@ -1,3 +1,28 @@
+2009-12-24  Andy Hutchinson  <hutchinsonandy@gcc.gnu.org>
+
+       PR target/35013, 27192
+       * config/avr/avr.c (print_operand_address): Print correct program
+       memory address.
+       Add warning for large device offset addresses.
+       (avr_assemble_integer): Ditto.
+       (print_operand): Add warnings for incorrect addressing.
+       (out_movqi_r_mr): Tag assembler with new address codes.
+       (out_movhi_r_mr): Ditto.
+       (out_movsi_r_mr): Ditto.
+       (out_movqi_mr_r): Ditto.
+       (out_movhi_mr_r): Ditto.
+       (out_movsi_mr_r): Ditto.
+       * config/avr/predicates.md (text_segment_operand): New predicate.
+       * config/avr/avr.md (jump): Tag assembler with new address codes.
+       (call_insn): Ditto.
+       (call_value_insn): Ditto.
+       (*tablejump_lib): Ditto.
+       (*cbi): Ditto.
+       (*sbi): Ditto.
+       (indirect_jump): New define_expand.
+       (jcindirect_jump): New pattern for constant expression jump.
+       (njcindirect_jump): Renamed old indirect_jump.
+
 2009-12-24  Steven Bosscher  <steven@gcc.gnu.org>
 
        * store-motion.c (build_store_vectors): Clear regs_set_in_block at
index b1713a89c20621caa7232babac308202931d3ff0..eff2179b93d62b233d74fb0c37d3e973105bfe13 100644 (file)
@@ -1176,12 +1176,33 @@ print_operand_address (FILE *file, rtx addr)
 
     default:
       if (CONSTANT_ADDRESS_P (addr)
-         && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
-             || GET_CODE (addr) == LABEL_REF))
+         && text_segment_operand (addr, VOIDmode))
        {
-         fprintf (file, "gs(");
-         output_addr_const (file,addr);
-         fprintf (file ,")");
+         rtx x = XEXP (addr,0);
+         if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
+           {
+             /* Assembler gs() will implant word address. Make offset 
+                a byte offset inside gs() for assembler. This is 
+                needed because the more logical (constant+gs(sym)) is not 
+                accepted by gas. For 128K and lower devices this is ok. For
+                large devices it will create a Trampoline to offset from symbol 
+                which may not be what the user really wanted.  */
+             fprintf (file, "gs(");
+             output_addr_const (file, XEXP (x,0));
+             fprintf (file,"+" HOST_WIDE_INT_PRINT_DEC ")", 2 * INTVAL (XEXP (x,1)));
+             if (AVR_3_BYTE_PC)
+               if (warning ( 0, "Pointer offset from symbol maybe incorrect."))
+                 {
+                   output_addr_const (stderr, addr);
+                   fprintf(stderr,"\n");
+                 }
+           }
+         else
+           {
+             fprintf (file, "gs(");
+             output_addr_const (file, addr);
+             fprintf (file, ")");
+           }
        }
       else
        output_addr_const (file, addr);
@@ -1221,12 +1242,18 @@ print_operand (FILE *file, rtx x, int code)
   else if (GET_CODE (x) == MEM)
     {
       rtx addr = XEXP (x,0);
-
-      if (CONSTANT_P (addr) && abcd)
+      if (code == 'm')
        {
-         fputc ('(', file);
-         output_address (addr);
-         fprintf (file, ")+%d", abcd);
+          if (!CONSTANT_P (addr))
+           fatal_insn ("bad address, not a constant):", addr);
+         /* Assembler template with m-code is data - not progmem section */
+         if (text_segment_operand (addr, VOIDmode))
+           if (warning ( 0, "accessing data memory with program memory address"))
+             {
+               output_addr_const (stderr, addr);
+               fprintf(stderr,"\n");
+             }
+         output_addr_const (file, addr);
        }
       else if (code == 'o')
        {
@@ -1257,6 +1284,18 @@ print_operand (FILE *file, rtx x, int code)
       else
        print_operand_address (file, addr);
     }
+  else if (code == 'x')
+    {
+      /* Constant progmem address - like used in jmp or call */
+      if (0 == text_segment_operand (x, VOIDmode))
+           if (warning ( 0, "accessing program  memory with data memory address"))
+         {
+           output_addr_const (stderr, x);
+           fprintf(stderr,"\n");
+         }
+      /* Use normal symbol for direct address no linker trampoline needed */
+      output_addr_const (file, x);
+    }
   else if (GET_CODE (x) == CONST_DOUBLE)
     {
       long val;
@@ -1874,10 +1913,10 @@ out_movqi_r_mr (rtx insn, rtx op[], int *l)
       if (optimize > 0 && io_address_operand (x, QImode))
        {
          *l = 1;
-         return AS2 (in,%0,%1-0x20);
+         return AS2 (in,%0,%m1-0x20);
        }
       *l = 2;
-      return AS2 (lds,%0,%1);
+      return AS2 (lds,%0,%m1);
     }
   /* memory access by reg+disp */
   else if (GET_CODE (x) == PLUS
@@ -2062,12 +2101,12 @@ out_movhi_r_mr (rtx insn, rtx op[], int *l)
       if (optimize > 0 && io_address_operand (base, HImode))
        {
          *l = 2;
-         return (AS2 (in,%A0,%A1-0x20) CR_TAB
-                 AS2 (in,%B0,%B1-0x20));
+         return (AS2 (in,%A0,%m1-0x20) CR_TAB
+                 AS2 (in,%B0,%m1+1-0x20));
        }
       *l = 4;
-      return (AS2 (lds,%A0,%A1) CR_TAB
-             AS2 (lds,%B0,%B1));
+      return (AS2 (lds,%A0,%m1) CR_TAB
+             AS2 (lds,%B0,%m1+1));
     }
   
   fatal_insn ("unknown move insn:",insn);
@@ -2226,10 +2265,10 @@ out_movsi_r_mr (rtx insn, rtx op[], int *l)
                  AS2 (ld,%C0,%1) CR_TAB
                  AS2 (ld,%D0,%1));
   else if (CONSTANT_ADDRESS_P (base))
-      return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
-                   AS2 (lds,%B0,%B1) CR_TAB
-                   AS2 (lds,%C0,%C1) CR_TAB
-                   AS2 (lds,%D0,%D1));
+      return *l=8, (AS2 (lds,%A0,%m1) CR_TAB
+                   AS2 (lds,%B0,%m1+1) CR_TAB
+                   AS2 (lds,%C0,%m1+2) CR_TAB
+                   AS2 (lds,%D0,%m1+3));
     
   fatal_insn ("unknown move insn:",insn);
   return "";
@@ -2249,10 +2288,10 @@ out_movsi_mr_r (rtx insn, rtx op[], int *l)
     l = &tmp;
   
   if (CONSTANT_ADDRESS_P (base))
-    return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
-                AS2 (sts,%B0,%B1) CR_TAB
-                AS2 (sts,%C0,%C1) CR_TAB
-                AS2 (sts,%D0,%D1));
+    return *l=8,(AS2 (sts,%m0,%A1) CR_TAB
+                AS2 (sts,%m0+1,%B1) CR_TAB
+                AS2 (sts,%m0+2,%C1) CR_TAB
+                AS2 (sts,%m0+3,%D1));
   if (reg_base > 0)                 /* (r) */
     {
       if (reg_base == REG_X)                /* (R26) */
@@ -2562,10 +2601,10 @@ out_movqi_mr_r (rtx insn, rtx op[], int *l)
       if (optimize > 0 && io_address_operand (x, QImode))
        {
          *l = 1;
-         return AS2 (out,%0-0x20,%1);
+         return AS2 (out,%m0-0x20,%1);
        }
       *l = 2;
-      return AS2 (sts,%0,%1);
+      return AS2 (sts,%m0,%1);
     }
   /* memory access by reg+disp */
   else if (GET_CODE (x) == PLUS        
@@ -2641,11 +2680,11 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
       if (optimize > 0 && io_address_operand (base, HImode))
        {
          *l = 2;
-         return (AS2 (out,%B0-0x20,%B1) CR_TAB
-                 AS2 (out,%A0-0x20,%A1));
+         return (AS2 (out,%m0+1-0x20,%B1) CR_TAB
+                 AS2 (out,%m0-0x20,%A1));
        }
-      return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
-                     AS2 (sts,%A0,%A1));
+      return *l = 4, (AS2 (sts,%m0+1,%B1) CR_TAB
+                     AS2 (sts,%m0,%A1));
     }
   if (reg_base > 0)
     {
@@ -4502,8 +4541,7 @@ static bool
 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
 {
   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
-      && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
-         || GET_CODE (x) == LABEL_REF))
+      && text_segment_operand (x, VOIDmode) )
     {
       fputs ("\t.word\tgs(", asm_out_file);
       output_addr_const (asm_out_file, x);
@@ -5944,13 +5982,13 @@ avr_out_sbxx_branch (rtx insn, rtx operands[])
       if (INTVAL (operands[1]) < 0x40)
        {
          if (comp == EQ)
-           output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
+           output_asm_insn (AS2 (sbis,%m1-0x20,%2), operands);
          else
-           output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
+           output_asm_insn (AS2 (sbic,%m1-0x20,%2), operands);
        }
       else
        {
-         output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
+         output_asm_insn (AS2 (in,__tmp_reg__,%m1-0x20), operands);
          if (comp == EQ)
            output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
          else
@@ -5979,9 +6017,9 @@ avr_out_sbxx_branch (rtx insn, rtx operands[])
 
   if (long_jump)
     return (AS1 (rjmp,.+4) CR_TAB
-           AS1 (jmp,%3));
+           AS1 (jmp,%x3));
   if (!reverse)
-    return AS1 (rjmp,%3);
+    return AS1 (rjmp,%x3);
   return "";
 }
 
index 1271fa4f44bd914689c0bdd9b02c89160ab1bd6c..f0e59eb6ef4651f60e9b95b8692a98ae1bca997e 100644 (file)
 ;;  D  Add 3.
 ;;  j  Branch condition.
 ;;  k  Reverse branch condition.
+;;..m..Constant Direct Data memory address.
 ;;  o  Displacement for (mem (plus (reg) (const_int))) operands.
 ;;  p  POST_INC or PRE_DEC address as a pointer (X, Y, Z)
 ;;  r  POST_INC or PRE_DEC address as a register (r26, r28, r30)
+;;..x..Constant Direct Program memory address.
 ;;  ~  Output 'r' if not AVR_HAVE_JMP_CALL.
 ;;  !  Output 'e' if AVR_HAVE_EIJMP_EICALL.
 
   ""
   "*{
   if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1)
-    return AS1 (jmp,%0);
-  return AS1 (rjmp,%0);
+    return AS1 (jmp,%x0);
+  return AS1 (rjmp,%x0);
 }"
   [(set (attr "length")
        (if_then_else (match_operand 0 "symbol_ref_operand" "") 
                \"%!icall\");
     }
   else if (which_alternative==2)
-    return AS1(%~call,%c0);
+    return AS1(%~call,%x0);
   return (AS2 (ldi,r30,lo8(%0)) CR_TAB
           AS2 (ldi,r31,hi8(%0)) CR_TAB
           \"%!icall\");
                \"%!icall\");
     }
   else if (which_alternative==2)
-    return AS1(%~call,%c1);
+    return AS1(%~call,%x1);
   return (AS2 (ldi, r30, lo8(%1)) CR_TAB
           AS2 (ldi, r31, hi8(%1)) CR_TAB
           \"%!icall\");
    (set_attr "length" "1")])
 
 ; indirect jump
-(define_insn "indirect_jump"
+
+(define_expand "indirect_jump"
+  [(set (pc) (match_operand:HI 0 "nonmemory_operand" ""))]
+  ""
+  " if ((!AVR_HAVE_JMP_CALL) && !register_operand(operand0, HImode))
+    {
+      operands[0] = copy_to_mode_reg(HImode, operand0);
+    }"
+)
+
+; indirect jump
+(define_insn "*jcindirect_jump"
+  [(set (pc) (match_operand:HI 0 "immediate_operand" "i"))]
+  ""
+  "@
+       %~jmp %x0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "none")])
+
+;;
+(define_insn "*njcindirect_jump"
   [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))]
   "!AVR_HAVE_EIJMP_EICALL"
   "@
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
   "AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES"
-  "jmp __tablejump2__"
+  "%~jmp __tablejump2__"
   [(set_attr "length" "2")
    (set_attr "cc" "clobber")])
 
   "(optimize > 0)"
 {
   operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
-  return AS2 (cbi,%0-0x20,%2);
+  return AS2 (cbi,%m0-0x20,%2);
 }
   [(set_attr "length" "1")
    (set_attr "cc" "none")])
   "(optimize > 0)"
 {
   operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
-  return AS2 (sbi,%0-0x20,%2);
+  return AS2 (sbi,%m0-0x20,%2);
 }
   [(set_attr "length" "1")
    (set_attr "cc" "none")])
index 2aa3e88c79dfb37ddda9a8795617e10b83b326cc..9a3473bf88f549114ca8269bb551872e02eaee33 100755 (executable)
 (define_predicate "symbol_ref_operand"
   (match_code "symbol_ref"))
 
+;; Return true if OP is a text segment reference.
+;; This is needed for program memory address expressions.
+(define_predicate "text_segment_operand"
+  (match_code "code_label,label_ref,symbol_ref,plus,const")
+{
+  switch (GET_CODE (op))
+    {
+    case CODE_LABEL:
+      return true;
+    case LABEL_REF :
+      return true;
+    case SYMBOL_REF :
+      return SYMBOL_REF_FUNCTION_P (op);
+    case PLUS :
+      /* Assume canonical format of symbol + constant.
+        Fall through.  */
+    case CONST :
+      return text_segment_operand (XEXP (op, 0), VOIDmode);
+    default :
+      return false;
+    }
+})
+
 ;; Return true if OP is a constant that contains only one 1 in its
 ;; binary representation.
 (define_predicate "single_one_operand"