+2018-11-28 Jeff Law <law@redhat.com>
+
+ * config/h8300/constraints.md: Add "C" constraint for call insns.
+ * config/h8300/h8300.md (call, call_value): Turn into a define_expand
+ and define_insn pair. Move invalid call targets into a register in
+ the expander and fix constraints in the matching pattern.
+ * config/h8300/predicates.md (call_expander_operand): Renamed from
+ call_insn_operand. Reject things we shouldn't be trying to handle.
+ (call_insn_operand): New predicate for use by the call/call_value
+ insns.
+ (small_call_insn_operand): Update appropriately.
+
2018-11-28 Sam Tebbs <sam.tebbs@arm.com>
* config/aarch64/aarch64.c (aarch64_process_target_attr): Replace
- calls to strtok with strtok_r.
+ calls to strtok with strtok_r.
2018-11-28 Richard Biener <rguenther@suse.de>
;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
-(define_insn "call"
- [(call (match_operand:QI 0 "call_insn_operand" "or")
- (match_operand:HI 1 "general_operand" "g"))]
+(define_expand "call"
+ [(call (match_operand:QI 0 "call_expander_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ {
+ if (!register_operand (XEXP (operands[0], 0), Pmode)
+ && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
+ XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
+ })
+
+(define_insn "call_insn"
+ [(call (mem:QI (match_operand 0 "call_insn_operand" "Cr"))
+ (match_operand:HI 1 "general_operand" "g"))]
""
{
- if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
- && (SYMBOL_REF_FLAGS (XEXP (operands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
- return "jsr\\t@%0:8";
+ rtx xoperands[1];
+ xoperands[0] = gen_rtx_MEM (QImode, operands[0]);
+ gcc_assert (GET_MODE (operands[0]) == Pmode);
+ if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF
+ && (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+ output_asm_insn ("jsr\\t@%0:8", xoperands);
else
- return "jsr\\t%0";
+ output_asm_insn ("jsr\\t%0", xoperands);
+ return "";
}
[(set_attr "type" "call")
(set (attr "length")
;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
-(define_insn "call_value"
+(define_expand "call_value"
+ [(set (match_operand 0 "" "")
+ (call (match_operand:QI 1 "call_expander_operand" "")
+ (match_operand:HI 2 "general_operand" "")))]
+ ""
+ {
+ if (!register_operand (XEXP (operands[1], 0), Pmode)
+ && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
+ XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+ })
+
+(define_insn "call_value_insn"
[(set (match_operand 0 "" "=r")
- (call (match_operand:QI 1 "call_insn_operand" "or")
- (match_operand:HI 2 "general_operand" "g")))]
+ (call (mem:QI (match_operand 1 "call_insn_operand" "Cr"))
+ (match_operand:HI 2 "general_operand" "g")))]
""
{
- if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
- && (SYMBOL_REF_FLAGS (XEXP (operands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
- return "jsr\\t@%1:8";
+ rtx xoperands[2];
+ gcc_assert (GET_MODE (operands[1]) == Pmode);
+ xoperands[0] = operands[0];
+ xoperands[1] = gen_rtx_MEM (QImode, operands[1]);
+ if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF
+ && (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+ output_asm_insn ("jsr\\t@%1:8", xoperands);
else
- return "jsr\\t%1";
+ output_asm_insn ("jsr\\t%1", xoperands);
+ return "";
}
[(set_attr "type" "call")
(set (attr "length")
;; Return true if OP is a valid call operand.
-(define_predicate "call_insn_operand"
+(define_predicate "call_expander_operand"
(match_code "mem")
{
if (GET_CODE (op) == MEM)
rtx inside = XEXP (op, 0);
if (register_operand (inside, Pmode))
return 1;
- if (CONSTANT_ADDRESS_P (inside))
+ if (SYMBOL_REF_P (inside))
return 1;
}
return 0;
})
+(define_predicate "call_insn_operand"
+ (match_code "reg,symbol_ref")
+{
+ if (register_operand (op, Pmode))
+ return 1;
+ if (SYMBOL_REF_P (op))
+ return 1;
+ return 0;
+})
+
;; Return true if OP is a valid call operand, and OP represents an
;; operand for a small call (4 bytes instead of 6 bytes).
(define_predicate "small_call_insn_operand"
- (match_code "mem")
+ (match_code "reg,symbol_ref")
{
- if (GET_CODE (op) == MEM)
- {
- rtx inside = XEXP (op, 0);
+ /* Register indirect is a small call. */
+ if (register_operand (op, Pmode))
+ return 1;
- /* Register indirect is a small call. */
- if (register_operand (inside, Pmode))
- return 1;
+ /* A call through the function vector is a small call too. */
+ if (GET_CODE (op) == SYMBOL_REF
+ && (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+ return 1;
- /* A call through the function vector is a small call too. */
- if (GET_CODE (inside) == SYMBOL_REF
- && (SYMBOL_REF_FLAGS (inside) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
- return 1;
- }
/* Otherwise it's a large call. */
return 0;
})