;; Machine description for RISC-V Zc extension.
;; Copyright (C) 2023-2025 Free Software Foundation, Inc.
;; Contributed by Fei Gao (gaofei@eswincomputing.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/>.

(define_insn "@gpr_multi_pop_up_to_ra_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_ra_operand" "I")))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s0_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s0_operand" "I")))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s1_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s1_operand" "I")))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s1}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s2_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s2_operand" "I")))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s2}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s3_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s3_operand" "I")))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s3}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s4_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s4_operand" "I")))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s4}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s5_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s5_operand" "I")))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s5}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s6_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s6_operand" "I")))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s6}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s7_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s7_operand" "I")))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                      (const_int <slot8_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s7}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s8_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s8_operand" "I")))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s8}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s9_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s9_operand" "I")))
   (set (reg:X S9_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                      (const_int <slot8_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s9}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_pop_up_to_s11_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s11_operand" "I")))
   (set (reg:X S11_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S10_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S9_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                      (const_int <slot8_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot11_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot12_offset>))))]
  "TARGET_ZCMP"
  "cm.pop	{ra, s0-s11}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_ra_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_ra_operand" "I")))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s0_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s0_operand" "I")))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s1_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s1_operand" "I")))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s1}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s2_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s2_operand" "I")))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s2}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s3_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s3_operand" "I")))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s3}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s4_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s4_operand" "I")))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s4}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s5_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s5_operand" "I")))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s5}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s6_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s6_operand" "I")))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s6}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s7_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s7_operand" "I")))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s7}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s8_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s8_operand" "I")))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s8}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s9_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s9_operand" "I")))
   (set (reg:X S9_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s9}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popret_up_to_s11_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s11_operand" "I")))
   (set (reg:X S11_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S10_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S9_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                      (const_int <slot8_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot11_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot12_offset>))))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popret	{ra, s0-s11}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_ra_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_ra_operand" "I")))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s0_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s0_operand" "I")))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s1_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s1_operand" "I")))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s1}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s2_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s2_operand" "I")))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s2}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s3_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s3_operand" "I")))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s3}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s4_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s4_operand" "I")))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s4}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s5_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s5_operand" "I")))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s5}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s6_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s6_operand" "I")))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s6}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s7_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s7_operand" "I")))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s7}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s8_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s8_operand" "I")))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s8}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s9_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s9_operand" "I")))
   (set (reg:X S9_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s9}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_popretz_up_to_s11_<mode>"
  [(set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_pop_up_to_s11_operand" "I")))
   (set (reg:X S11_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>))))
   (set (reg:X S10_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>))))
   (set (reg:X S9_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>))))
   (set (reg:X S8_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>))))
   (set (reg:X S7_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>))))
   (set (reg:X S6_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>))))
   (set (reg:X S5_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>))))
   (set (reg:X S4_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>))))
   (set (reg:X S3_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                      (const_int <slot8_offset>))))
   (set (reg:X S2_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>))))
   (set (reg:X S1_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>))))
   (set (reg:X S0_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot11_offset>))))
   (set (reg:X RETURN_ADDR_REGNUM)
        (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot12_offset>))))
   (set (reg:X A0_REGNUM)
        (const_int 0))
   (use (reg:X A0_REGNUM))
   (return)
   (use (reg:SI RETURN_ADDR_REGNUM))]
  "TARGET_ZCMP"
  "cm.popretz	{ra, s0-s11}, %0"
[(set_attr "type" "load")])

(define_insn "@gpr_multi_push_up_to_ra_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_ra_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s0_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s0_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s1_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s1_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s1}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s2_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s2_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s2}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s3_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s3_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s3}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s4_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s4_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s4}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s5_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S5_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s5_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s5}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s6_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S6_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S5_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s6_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s6}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s7_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S7_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S6_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S5_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                      (const_int <slot8_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s7_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s7}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s8_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S8_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S7_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S6_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S5_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s8_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s8}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s9_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S9_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S8_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S7_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S6_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S5_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s9_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s9}, %0"
[(set_attr "type" "store")])

(define_insn "@gpr_multi_push_up_to_s11_<mode>"
  [(set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot0_offset>)))
        (reg:X S11_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot1_offset>)))
        (reg:X S10_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot2_offset>)))
        (reg:X S9_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot3_offset>)))
        (reg:X S8_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot4_offset>)))
        (reg:X S7_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot5_offset>)))
        (reg:X S6_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot6_offset>)))
        (reg:X S5_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot7_offset>)))
        (reg:X S4_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot8_offset>)))
        (reg:X S3_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot9_offset>)))
        (reg:X S2_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot10_offset>)))
        (reg:X S1_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot11_offset>)))
        (reg:X S0_REGNUM))
   (set (mem:X (plus:X (reg:X SP_REGNUM)
                       (const_int <slot12_offset>)))
        (reg:X RETURN_ADDR_REGNUM))
   (set (reg:X SP_REGNUM)
        (plus:X (reg:X SP_REGNUM)
                 (match_operand 0 "stack_push_up_to_s11_operand" "I")))]
  "TARGET_ZCMP"
  "cm.push	{ra, s0-s11}, %0"
[(set_attr "type" "store")])

;; ZCMP mv
(define_insn "*mva01s<X:mode>"
  [(set (match_operand:X 0 "a0a1_reg_operand" "=r")
        (match_operand:X 1 "zcmp_mv_sreg_operand" "r"))
   (set (match_operand:X 2 "a0a1_reg_operand" "=r")
        (match_operand:X 3 "zcmp_mv_sreg_operand" "r"))]
  "TARGET_ZCMP
   && (REGNO (operands[2]) != REGNO (operands[0]))"
  { return (REGNO (operands[0]) == A0_REGNUM) ? "cm.mva01s\t%1,%3" : "cm.mva01s\t%3,%1"; }
  [(set_attr "mode" "<X:MODE>")
   (set_attr "type" "mvpair")])

(define_insn "*mvsa01<X:mode>"
  [(set (match_operand:X 0 "zcmp_mv_sreg_operand" "=r")
        (match_operand:X 1 "a0a1_reg_operand" "r"))
   (set (match_operand:X 2 "zcmp_mv_sreg_operand" "=r")
        (match_operand:X 3 "a0a1_reg_operand" "r"))]
  "TARGET_ZCMP
   && (REGNO (operands[0]) != REGNO (operands[2]))
   && (REGNO (operands[1]) != REGNO (operands[3]))"
  { return (REGNO (operands[1]) == A0_REGNUM) ? "cm.mvsa01\t%0,%2" : "cm.mvsa01\t%2,%0"; }
  [(set_attr "mode" "<X:MODE>")
   (set_attr "type" "mvpair")])
