* 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
#include "recog.h"
#include "expr.h"
#include "tree.h"
+#include "obstack.h"
/* Forward declarations. */
void print_operand_address ();
}
}
+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
&& 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:
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
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.
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)
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;
&& 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. */
/* 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 */
/* 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 \
|| (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) \
} \
}
+#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). */
(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")))]
""