constraints.md: Add "C" constraint for call insns.
authorJeff Law <law@gcc.gnu.org>
Wed, 28 Nov 2018 17:26:03 +0000 (10:26 -0700)
committerJeff Law <law@gcc.gnu.org>
Wed, 28 Nov 2018 17:26:03 +0000 (10:26 -0700)
* 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.

From-SVN: r266571

gcc/ChangeLog
gcc/config/h8300/constraints.md
gcc/config/h8300/h8300.md
gcc/config/h8300/predicates.md

index 2e4af6f97f7d80d9dd3377e276bedc9a6064612f..6456facbacbfbf162d2d99b4ca328d568eb71658 100644 (file)
@@ -1,7 +1,19 @@
+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>
 
index 9d0ac42fdaab420846260e702f95ee92f219f8f8..4175c832ef39eeb1a6c9214136c15f957bcc27a9 100644 (file)
   (and (match_code "const_int")
        (match_test "!h8300_shift_needs_scratch_p (ival, QImode)")))
 
+(define_constraint "C"
+  "@internal"
+  (match_code "symbol_ref"))
+
 (define_constraint "S"
   "@internal"
   (and (match_code "const_int")
index 70f96c7481f2811c9116a9c64e5c79e5c9b762c6..0686f25d71de857dc46a426de6463850f29382fd 100644 (file)
 
 ;; ??? 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")
index 698cdee1ddf10349256a218aa176acd9842d1c22..217189ad1f5e504f250f1d0c371ceafe494175ad 100644 (file)
 
 ;; 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;
 })