diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 21748e9799f..f086cafaaec 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -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. */ diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index 069797f7fe1..3020fbe57fc 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -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). */ diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 059a91fe2a8..f714b84317d 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -116,8 +116,8 @@ (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)" "@ @@ -125,12 +125,13 @@ 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" "") @@ -147,17 +148,18 @@ }") (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 @@ -178,8 +180,8 @@ (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)" "@ @@ -187,12 +189,13 @@ 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" "") @@ -209,17 +212,18 @@ }") (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 @@ -453,7 +457,7 @@ ;; ---------------------------------------------------------------------- (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")))] "" @@ -462,7 +466,7 @@ (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")))] "" @@ -471,7 +475,7 @@ (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")))] ""