;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
;;
;; micromips.md Machine Description for the microMIPS instruction set
;; 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
;; .
(define_insn "*store_word_multiple"
[(match_parallel 0 ""
[(set (match_operand:SI 1 "memory_operand")
(match_operand:SI 2 "register_operand"))])]
"TARGET_MICROMIPS
&& umips_save_restore_pattern_p (true, operands[0])"
{ return umips_output_save_restore (true, operands[0]); }
[(set_attr "type" "multimem")
(set_attr "mode" "SI")
(set_attr "can_delay" "no")])
(define_insn "*load_word_multiple"
[(match_parallel 0 ""
[(set (match_operand:SI 1 "register_operand")
(match_operand:SI 2 "memory_operand"))])]
"TARGET_MICROMIPS
&& umips_save_restore_pattern_p (false, operands[0])"
{ return umips_output_save_restore (false, operands[0]); }
[(set_attr "type" "multimem")
(set_attr "mode" "SI")
(set_attr "can_delay" "no")])
;; For LWP.
(define_peephole2
[(set (match_operand:SI 0 "d_operand" "")
(match_operand:SI 1 "non_volatile_mem_operand" ""))
(set (match_operand:SI 2 "d_operand" "")
(match_operand:SI 3 "non_volatile_mem_operand" ""))]
"TARGET_MICROMIPS
&& umips_load_store_pair_p (true, operands)"
[(parallel [(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))])])
;; The behavior of the LWP insn is undefined if placed in a delay slot.
(define_insn "*lwp"
[(parallel [(set (match_operand:SI 0 "d_operand")
(match_operand:SI 1 "non_volatile_mem_operand"))
(set (match_operand:SI 2 "d_operand")
(match_operand:SI 3 "non_volatile_mem_operand"))])]
"TARGET_MICROMIPS
&& umips_load_store_pair_p (true, operands)"
{
umips_output_load_store_pair (true, operands);
return "";
}
[(set_attr "type" "load")
(set_attr "mode" "SI")
(set_attr "can_delay" "no")])
;; For SWP.
(define_peephole2
[(set (match_operand:SI 0 "non_volatile_mem_operand" "")
(match_operand:SI 1 "d_operand" ""))
(set (match_operand:SI 2 "non_volatile_mem_operand" "")
(match_operand:SI 3 "d_operand" ""))]
"TARGET_MICROMIPS
&& umips_load_store_pair_p (false, operands)"
[(parallel [(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))])])
;; The behavior of the SWP insn is undefined if placed in a delay slot.
(define_insn "*swp"
[(set (match_operand:SI 0 "non_volatile_mem_operand")
(match_operand:SI 1 "d_operand"))
(set (match_operand:SI 2 "non_volatile_mem_operand")
(match_operand:SI 3 "d_operand"))]
"TARGET_MICROMIPS
&& umips_load_store_pair_p (false, operands)"
{
umips_output_load_store_pair (false, operands);
return "";
}
[(set_attr "type" "store")
(set_attr "mode" "SI")
(set_attr "can_delay" "no")])
;; For JRADDIUSP.
(define_insn "jraddiusp"
[(return)
(use (reg:SI 31))
(set (reg:SI 29)
(plus:SI (reg:SI 29)
(match_operand 0 "uw5_operand")))]
"TARGET_MICROMIPS"
"jraddiusp\t%0"
[(set_attr "type" "trap")
(set_attr "can_delay" "no")
(set_attr "mode" "SI")])
;; For MOVEP.
(define_peephole2
[(set (match_operand:MOVEP1 0 "register_operand" "")
(match_operand:MOVEP1 1 "movep_src_operand" ""))
(set (match_operand:MOVEP2 2 "register_operand" "")
(match_operand:MOVEP2 3 "movep_src_operand" ""))]
"TARGET_MICROMIPS
&& umips_movep_target_p (operands[0], operands[2])"
[(parallel [(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))])])
;; The behavior of the MOVEP insn is undefined if placed in a delay slot.
(define_insn "*movep"
[(set (match_operand:MOVEP1 0 "register_operand")
(match_operand:MOVEP1 1 "movep_src_operand"))
(set (match_operand:MOVEP2 2 "register_operand")
(match_operand:MOVEP2 3 "movep_src_operand"))]
"TARGET_MICROMIPS
&& umips_movep_target_p (operands[0], operands[2])"
{
if (REGNO (operands[0]) < REGNO (operands[2]))
return "movep\t%0,%2,%z1,%z3";
else
return "movep\t%2,%0,%z3,%z1";
}
[(set_attr "type" "move")
(set_attr "mode" "")
(set_attr "can_delay" "no")])