h8300.c: Include obstack.h.
authorJeff Law <law@gcc.gnu.org>
Wed, 8 May 1996 02:36:19 +0000 (20:36 -0600)
committerJeff Law <law@gcc.gnu.org>
Wed, 8 May 1996 02:36:19 +0000 (20:36 -0600)
        * h8300/h8300.c: Include obstack.h.
        (bit_memory_operand): New function.
        (print_operand): Append ":16" to a memory reference to
        the tiny data area.
        (h8300_tiny_data_p): New function.
        (h8300_valid_machine_decl_attribute): Accept "tiny_data".  Fix
        typo.
        (h8300_encode_label): New function.
        (h8300_adjust_insn_length): References to the tiny data section
        are two bytes shorter than normal accesses on the H8/300H.
        * h8300/h8300.h (OK_FOR_U): Fix thinko.
        (ENCODE_SECTION_INFO): Encode info for tiny data variables.
        (STRIP_NAME_ENCODING): Define.
        * h8300/h8300.md (movqi insn): Fix length for a constant load.
        (movstrictqi): Likewise.
        (movhi, movstricthi): Likewise.
        (memory btst patterns): Add register to the constraints to keep
        reload happy.

From-SVN: r11955

gcc/config/h8300/h8300.c
gcc/config/h8300/h8300.h
gcc/config/h8300/h8300.md

index 21748e9799f9a955539f38e8e4792391b922e305..f086cafaaecbb6f6a7d9919b50f0b6ea42602a35 100644 (file)
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA.  */
 #include "recog.h"
 #include "expr.h"
 #include "tree.h"
+#include "obstack.h"
 
 /* Forward declarations.  */
 void print_operand_address ();
@@ -615,6 +616,15 @@ bit_operand (op, mode)
     }
 }
 
+int
+bit_memory_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return (GET_CODE (op) == MEM
+         && EXTRA_CONSTRAINT (op, 'U'));
+}
+
 /* Recognize valid operators for bit test.  */
 
 int
@@ -1193,6 +1203,9 @@ print_operand (file, x, code)
              && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
              && SYMBOL_REF_FLAG (XEXP (x, 0)))
            fprintf (file, ":8");
+         if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+             && TINY_DATA_NAME_P (XSTR (XEXP (x, 0), 0)))
+           fprintf (file, ":16");
          break;
 
        case CONST_INT:
@@ -2188,7 +2201,7 @@ h8300_funcvec_function_p (func)
   return a != NULL_TREE;
 }
 
-/* Return nonzero if DECL is a variable that's in the tiny
+/* Return nonzero if DECL is a variable that's in the eight bit
    data area.  */
 
 int
@@ -2204,6 +2217,22 @@ h8300_eightbit_data_p (decl)
   return a != NULL_TREE;
 }
 
+/* Return nonzero if DECL is a variable that's in the tiny
+   data area.  */
+
+int
+h8300_tiny_data_p (decl)
+     tree decl;
+{
+  tree a;
+
+  if (TREE_CODE (decl) != VAR_DECL)
+    return 0;
+
+  a = lookup_attribute ("tiny_data", DECL_MACHINE_ATTRIBUTES (decl));
+  return a != NULL_TREE;
+}
+
 /* Return nonzero if ATTR is a valid attribute for DECL.
    ATTRIBUTES are any existing attributes and ARGS are the arguments
    supplied with ATTR.
@@ -2214,7 +2243,13 @@ h8300_eightbit_data_p (decl)
    interrupt handler.
 
    function_vector: This function should be called through the
-   function vector.  */
+   function vector.
+
+   eightbit_data: This variable lives in the 8-bit data area and can
+   be referenced with 8-bit absolute memory addresses.
+
+   tiny_data: This variable lives in the tiny data area and can be
+   referenced with 16-bit absolute memory references.  */
 
 int
 h8300_valid_machine_decl_attribute (decl, attributes, attr, args)
@@ -2238,13 +2273,41 @@ h8300_valid_machine_decl_attribute (decl, attributes, attr, args)
          warning ("Only initialized variables can be placed into the 8-bit area.");
          return 0;
        }
-      DECL_SECTION_NAME (decl) = build_string (8, ".eight");
+      DECL_SECTION_NAME (decl) = build_string (7, ".eight");
+      return 1;
+    }
+
+  if (is_attribute_p ("tiny_data", attr)
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+    {
+      if (DECL_INITIAL (decl) == NULL_TREE)
+       {
+         warning ("Only initialized variables can be placed into the 8-bit area.");
+         return 0;
+       }
+      DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
       return 1;
     }
       
   return 0;
 }
 
+extern struct obstack *saveable_obstack;
+
+h8300_encode_label (decl)
+     tree decl;
+{
+  char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+  int len = strlen (str);
+  char *newstr;
+
+  newstr = obstack_alloc (saveable_obstack, len + 2);
+
+  strcpy (newstr + 1, str);
+  *newstr = '*';
+  XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
+}
+
 char *
 output_simode_bld (bild, log2, operands)
      int bild;
@@ -2316,6 +2379,13 @@ h8300_adjust_insn_length (insn, length)
          && INTVAL (XEXP (addr, 1)) > -32768
          && INTVAL (XEXP (addr, 1)) < 32767)
        return -4;
+
+      /* On the H8/300H, abs:16 is two bytes shorter than the
+        more general abs:24.  */
+      if (TARGET_H8300H
+         && GET_CODE (addr) == SYMBOL_REF
+         && TINY_DATA_NAME_P (XSTR (addr, 0)))
+       return -2;
     }
 
   /* Loading some constants needs adjustment.  */
index 069797f7fe191d841d2867c7e7152a964d253d2c..3020fbe57fc91b19cb42501b80a0b90c283d90f8 100644 (file)
@@ -150,7 +150,7 @@ do {                                \
 /* Define this if most significant word of a multiword number is lowest
    numbered.  
    This is true on an H8/300 (actually we can make it up, but we choose to
-   be consistent.  */ 
+   be consistent).  */ 
 #define WORDS_BIG_ENDIAN 1
 
 /* Number of bits in an addressable storage unit */
@@ -784,8 +784,7 @@ struct rtx_def *function_arg();
 
 /* Extra constraints - 'U' if for an operand valid for a bset
    destination; i.e. a register, register indirect, or the
-   eightbit memory region (a SYMBOL_REF with the SYMBOL_REF_FLAG
-   set.  */
+   eightbit memory region (a SYMBOL_REF with an SYMBOL_REF_FLAG set).  */
 #define OK_FOR_U(OP) \
   ((GET_CODE (OP) == REG && REG_OK_FOR_BASE_P (OP)) \
    || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
@@ -795,7 +794,7 @@ struct rtx_def *function_arg();
    || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST \
        && GET_CODE (XEXP (XEXP (OP, 0), 0)) == PLUS \
        && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 0)) == SYMBOL_REF \
-       && SYMBOL_REF_FLAG (XEXP (XEXP (XEXP (OP, 0), 0), 0)) \
+       && SYMBOL_REF_FLAG (XEXP (XEXP (OP, 0), 0)) \
        && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 1)) == CONST_INT))
  
 #define EXTRA_CONSTRAINT(OP, C) \
@@ -1106,16 +1105,28 @@ readonly_data()                                                 \
     }                                          \
 }                                               
 
+#define TINY_DATA_NAME_P(NAME) (*(NAME) == '*')
+
 /* If we are referencing a function that is supposed to be called
    through the function vector, the SYMBOL_REF_FLAG in the rtl
    so the call patterns can generate the correct code.  */
 #define ENCODE_SECTION_INFO(DECL)  \
-  if ((TREE_CODE (DECL) == FUNCTION_DECL \
+  if (TREE_CODE (DECL) == FUNCTION_DECL \
        && h8300_funcvec_function_p (DECL)) \
-      || ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \
-         && TREE_CODE (DECL) == VAR_DECL \
-         && h8300_eightbit_data_p (DECL))) \
-    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
+  else if ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \
+      && TREE_CODE (DECL) == VAR_DECL \
+      && h8300_eightbit_data_p (DECL)) \
+    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
+  else if ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \
+      && TREE_CODE (DECL) == VAR_DECL \
+      && h8300_tiny_data_p (DECL)) \
+    h8300_encode_label (DECL);
+
+/* Store the user-specified part of SYMBOL_NAME in VAR.
+   This is sort of inverse to ENCODE_SECTION_INFO.  */
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+  (VAR) = (SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*' || (SYMBOL_NAME)[0] == '@');
 
 /* How to refer to registers in assembler output.
    This sequence is indexed by compiler's hard-register-number (see above).  */
index 059a91fe2a82dd8cc52bcd8e574e19a59b689f21..f714b84317d756357768aa62957a4197fa08a9b1 100644 (file)
    (set_attr "cc" "set")])
 
 (define_insn ""
-  [(set (match_operand:QI 0 "general_operand_dst" "=r,r,<,r,o")
-       (match_operand:QI 1 "general_operand_src" "I,r>,r,io,r"))]
+  [(set (match_operand:QI 0 "general_operand_dst" "=r,r,<,r,r,o")
+       (match_operand:QI 1 "general_operand_src" "I,r>,r,i,o,r"))]
   "register_operand (operands[0],QImode)
    || register_operand (operands[1], QImode)"
   "@
    mov.b       %R1,%X0
    mov.b       %X1,%R0
    mov.b       %R1,%X0
+   mov.b       %R1,%X0
    mov.b       %X1,%R0"
   [(set_attr_alternative "length"
-     [(const_int 2) (const_int 2) (const_int 2)
+     [(const_int 2) (const_int 2) (const_int 2) (const_int 2)
       (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
       (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
-   (set_attr "cc" "set_zn_c0,set,set,set,set")])
+   (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
 
 (define_expand "movqi"
   [(set (match_operand:QI 0 "general_operand_dst" "")
 }")
 
 (define_insn "movstrictqi"
-  [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "=r,r,r"))
-                        (match_operand:QI 1 "general_operand_src" "I,r,io"))]
+  [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "=r,r,r,r"))
+                        (match_operand:QI 1 "general_operand_src" "I,r,i,o"))]
   ""
   "@
    sub.b       %X0,%X0
    mov.b       %X1,%X0
+   mov.b       %R1,%X0
    mov.b       %R1,%X0"
   [(set_attr_alternative "length"
-     [(const_int 2) (const_int 2)
+     [(const_int 2) (const_int 2) (const_int 2)
       (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
-   (set_attr "cc" "set_zn_c0,set,set")])
+   (set_attr "cc" "set_zn_c0,set,set,set")])
    
 ;; movhi
 
    (set_attr "cc" "set")])
 
 (define_insn ""
-  [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,o")
-       (match_operand:HI 1 "general_operand_src" "I,r>,r,io,r"))]
+  [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,o")
+       (match_operand:HI 1 "general_operand_src" "I,r>,r,i,o,r"))]
   "register_operand (operands[0],HImode)
    || register_operand (operands[1], HImode)"
   "@
    mov.w       %T1,%T0
    mov.w       %T1,%T0
    mov.w       %T1,%T0
+   mov.w       %T1,%T0
    mov.w       %T1,%T0"
   [(set_attr_alternative "length"
-     [(const_int 2) (const_int 2) (const_int 2)
+     [(const_int 2) (const_int 2) (const_int 2) (const_int 4)
       (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
       (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
-   (set_attr "cc" "set_zn_c0,set,set,set,set")])
+   (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
 
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand_dst" "")
 }")
 
 (define_insn "movstricthi"
-  [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r"))
-                        (match_operand:HI 1 "general_operand_src" "I,r,io"))]
+  [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,r"))
+                        (match_operand:HI 1 "general_operand_src" "I,r,i,o"))]
   ""
   "@
    sub.w       %T0,%T0
    mov.w       %T1,%T0
+   mov.w       %T1,%T0
    mov.w       %T1,%T0"
   [(set_attr_alternative "length"
-     [(const_int 2) (const_int 2)
+     [(const_int 2) (const_int 2) (const_int 4)
       (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
-   (set_attr "cc" "set_zn_c0,set,set")])
+   (set_attr "cc" "set_zn_c0,set,set,set")])
 
 ;; movsi
 
 ;; ----------------------------------------------------------------------
 
 (define_insn ""
-  [(set (cc0) (zero_extract:QI (match_operand:QI 0 "memory_operand" "U")
+  [(set (cc0) (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "rU")
                               (const_int 1)
                               (match_operand:QI 1 "const_int_operand" "n")))]
   ""
    (set_attr "cc" "set_zn_c0")])
 
 (define_insn ""
-  [(set (cc0) (zero_extract:HI (match_operand:QI 0 "memory_operand" "U")
+  [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "rU")
                               (const_int 1)
                               (match_operand:QI 1 "const_int_operand" "n")))]
   ""
    (set_attr "cc" "set_zn_c0")])
 
 (define_insn ""
-  [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "U")
+  [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_memory_operand" "rU")
                               (const_int 1)
                               (match_operand:QI 1 "const_int_operand" "n")))]
   ""