;; Predicate definitions for Xilinx MicroBlaze ;; Copyright (C) 2009-2022 Free Software Foundation, Inc. ;; ;; Contributed by Michael Eager eager@eagercon.com. ;; ;; This file is part of GCC. ;; ;; GCC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; GCC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GCC; see the file COPYING3. If not see ;; http://www.gnu.org/licenses/.

;; Return whether OP can be used as an operands in arithmetic. (define_predicate “arith_operand” (ior (match_code “const_int,const_double”) (match_operand 0 “register_operand”)))

(define_predicate “arith_operand32” (ior (match_operand 0 “register_operand”) (and (match_code “const_int,const_double”) (match_test “LARGE_INT (op)”))))

(define_predicate “arith_plus_operand” (match_operand 0 “general_operand”) { switch (GET_CODE (op)) { default: return 0; case CONST_INT: case REG: return 1; case SYMBOL_REF: case LABEL_REF: if (flag_pic || microblaze_tls_referenced_p(op)) return 0; return 1; case CONST: { rtx const0; const0 = XEXP (op, 0);

      switch (GET_CODE(const0))
        {
          default:
            return 0;
          case UNSPEC :
            return 1;

          case PLUS :
            {
              rtx p0, p1;
              p0 = XEXP (const0, 0);
              p1 = XEXP (const0, 1);

              if ((GET_CODE(p0) == SYMBOL_REF
                   || GET_CODE (p0) == LABEL_REF)
                  && GET_CODE(p1) == CONST_INT)
                {
                  return arith_plus_operand (p0, GET_MODE(p0));
                }
            }
        }
    }
}

return 0; })

(define_predicate “const_0_operand” (and (match_code “const_int,const_double”) (match_test “op == CONST0_RTX (GET_MODE (op))”)))

;; Return whether OP is a register or the constant 0. (define_predicate “reg_or_0_operand” (ior (match_operand 0 “const_0_operand”) (match_operand 0 “register_operand”)))

(define_predicate “reg_or_mem_operand” (ior (match_operand 0 “memory_operand”) (match_operand 0 “register_operand”)))

;; Return if the operand is either the PC or a label_ref.
(define_special_predicate “pc_or_label_operand”
(ior (match_code “pc,label_ref”) (and (match_code “symbol_ref”) (match_test “!(strcmp ((XSTR (op, 0)), "_stack_overflow_exit"))”))))

;; Test for valid call operand (define_predicate “call_insn_operand” (match_test “CALL_INSN_OP (op)”))

(define_predicate “call_insn_simple_operand” (and (match_test “CALL_INSN_OP (op)”) (match_test “GET_CODE (op) == REG || GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST_INT”)))

;; Return if OPERAND is valid as a source operand for a move instruction. (define_predicate “move_src_operand” (and ( not ( and (match_code “plus”) (not (match_test “(GET_CODE (XEXP (op, 0)) == REG) ^ (GET_CODE (XEXP (op,1)) == REG)”)) ) ) (match_operand 0 “general_operand”)) { if (microblaze_tls_referenced_p(op) || (flag_pic && (symbol_mentioned_p(op) || label_mentioned_p(op)))) return false;

return true; })

;; Test for valid PIC call operand (define_predicate “call_insn_plt_operand” (match_test “PLT_ADDR_P (op)”))

;; Return if the code of this rtx pattern is a comparison. (define_predicate “cmp_op” (match_code “gt,ge,gtu,geu,lt,le,ltu,leu”))