aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/lm32/lm32.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/lm32/lm32.md')
-rw-r--r--gcc-4.9/gcc/config/lm32/lm32.md1015
1 files changed, 1015 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/config/lm32/lm32.md b/gcc-4.9/gcc/config/lm32/lm32.md
new file mode 100644
index 000000000..26d16823c
--- /dev/null
+++ b/gcc-4.9/gcc/config/lm32/lm32.md
@@ -0,0 +1,1015 @@
+;; Machine description of the Lattice Mico32 architecture for GNU C compiler.
+;; Contributed by Jon Beniston <jon@beniston.com>
+
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
+
+;; 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/>.
+
+;; Include predicate and constraint definitions
+(include "predicates.md")
+(include "constraints.md")
+
+
+;; Register numbers
+(define_constants
+ [(RA_REGNUM 29) ; return address register.
+ ]
+)
+
+;; LM32 specific volatile operations
+(define_constants
+ [(UNSPECV_BLOCKAGE 1)] ; prevent scheduling across pro/epilog boundaries
+)
+
+;; LM32 specific operations
+(define_constants
+ [(UNSPEC_GOT 2)
+ (UNSPEC_GOTOFF_HI16 3)
+ (UNSPEC_GOTOFF_LO16 4)]
+)
+
+;; ---------------------------------
+;; instruction types
+;; ---------------------------------
+
+(define_attr "type"
+ "unknown,load,store,arith,compare,shift,multiply,divide,call,icall,ubranch,uibranch,cbranch"
+ (const_string "unknown"))
+
+;; ---------------------------------
+;; instruction lengths
+;; ---------------------------------
+
+; All instructions are 4 bytes
+; Except for branches that are out of range, and have to be implemented
+; as two instructions
+(define_attr "length" ""
+ (cond [
+ (eq_attr "type" "cbranch")
+ (if_then_else
+ (lt (abs (minus (match_dup 2) (pc)))
+ (const_int 32768)
+ )
+ (const_int 4)
+ (const_int 8)
+ )
+ ]
+ (const_int 4))
+)
+
+;; ---------------------------------
+;; scheduling
+;; ---------------------------------
+
+(define_automaton "lm32")
+
+(define_cpu_unit "x" "lm32")
+(define_cpu_unit "m" "lm32")
+(define_cpu_unit "w" "lm32")
+
+(define_insn_reservation "singlecycle" 1
+ (eq_attr "type" "store,arith,call,icall,ubranch,uibranch,cbranch")
+ "x")
+
+(define_insn_reservation "twocycle" 2
+ (eq_attr "type" "compare,shift,divide")
+ "x,m")
+
+(define_insn_reservation "threecycle" 3
+ (eq_attr "type" "load,multiply")
+ "x,m,w")
+
+;; ---------------------------------
+;; mov
+;; ---------------------------------
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (can_create_pseudo_p ())
+ {
+ if (GET_CODE (operand0) == MEM)
+ {
+ /* Source operand for store must be in a register. */
+ operands[1] = force_reg (QImode, operands[1]);
+ }
+ }
+}")
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (can_create_pseudo_p ())
+ {
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ /* Source operand for store must be in a register. */
+ operands[1] = force_reg (HImode, operands[1]);
+ }
+ }
+}")
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (can_create_pseudo_p ())
+ {
+ if (GET_CODE (operands[0]) == MEM
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == MEM))
+ {
+ /* Source operand for store must be in a register. */
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+ }
+
+ if (flag_pic && symbolic_operand (operands[1], SImode))
+ {
+ if (GET_CODE (operands[1]) == LABEL_REF
+ || (GET_CODE (operands[1]) == SYMBOL_REF
+ && SYMBOL_REF_LOCAL_P (operands[1])
+ && !SYMBOL_REF_WEAK (operands[1])))
+ {
+ emit_insn (gen_movsi_gotoff_hi16 (operands[0], operands[1]));
+ emit_insn (gen_addsi3 (operands[0],
+ operands[0],
+ pic_offset_table_rtx));
+ emit_insn (gen_movsi_gotoff_lo16 (operands[0],
+ operands[0],
+ operands[1]));
+ }
+ else
+ emit_insn (gen_movsi_got (operands[0], operands[1]));
+ crtl->uses_pic_offset_table = 1;
+ DONE;
+ }
+ else if (flag_pic && GET_CODE (operands[1]) == CONST)
+ {
+ rtx op = XEXP (operands[1], 0);
+ if (GET_CODE (op) == PLUS)
+ {
+ rtx arg0 = XEXP (op, 0);
+ rtx arg1 = XEXP (op, 1);
+ if (GET_CODE (arg0) == LABEL_REF
+ || (GET_CODE (arg0) == SYMBOL_REF
+ && SYMBOL_REF_LOCAL_P (arg0)
+ && !SYMBOL_REF_WEAK (arg0)))
+ {
+ emit_insn (gen_movsi_gotoff_hi16 (operands[0], arg0));
+ emit_insn (gen_addsi3 (operands[0],
+ operands[0],
+ pic_offset_table_rtx));
+ emit_insn (gen_movsi_gotoff_lo16 (operands[0],
+ operands[0],
+ arg0));
+ }
+ else
+ emit_insn (gen_movsi_got (operands[0], arg0));
+ emit_insn (gen_addsi3 (operands[0], operands[0], arg1));
+ crtl->uses_pic_offset_table = 1;
+ DONE;
+ }
+ }
+ else if (!flag_pic && reloc_operand (operands[1], GET_MODE (operands[1])))
+ {
+ emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_HIGH (SImode, operands[1])));
+ emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_LO_SUM (SImode, operands[0], operands[1])));
+ DONE;
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (!(satisfies_constraint_K (operands[1])
+ || satisfies_constraint_L (operands[1])
+ || satisfies_constraint_U (operands[1])))
+ {
+ emit_insn (gen_movsi_insn (operands[0],
+ GEN_INT (INTVAL (operands[1]) & ~0xffff)));
+ emit_insn (gen_iorsi3 (operands[0],
+ operands[0],
+ GEN_INT (INTVAL (operands[1]) & 0xffff)));
+ DONE;
+ }
+ }
+}")
+
+(define_expand "movmemsi"
+ [(parallel [(set (match_operand:BLK 0 "general_operand" "")
+ (match_operand:BLK 1 "general_operand" ""))
+ (use (match_operand:SI 2 "" ""))
+ (use (match_operand:SI 3 "const_int_operand" ""))])]
+ ""
+{
+ if (!lm32_expand_block_move (operands))
+ FAIL;
+ DONE;
+})
+
+;; ---------------------------------
+;; load/stores/moves
+;; ---------------------------------
+
+(define_insn "movsi_got"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT))]
+ "flag_pic"
+ "lw %0, (gp+got(%1))"
+ [(set_attr "type" "load")]
+)
+
+(define_insn "movsi_gotoff_hi16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF_HI16))]
+ "flag_pic"
+ "orhi %0, r0, gotoffhi16(%1)"
+ [(set_attr "type" "load")]
+)
+
+(define_insn "movsi_gotoff_lo16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand 2 "" ""))] UNSPEC_GOTOFF_LO16))]
+ "flag_pic"
+ "addi %0, %1, gotofflo16(%2)"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "*movsi_lo_sum"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "reloc_operand" "i")))]
+ "!flag_pic"
+ "ori %0, %0, lo(%2)"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "*movqi_insn"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,m,r")
+ (match_operand:QI 1 "general_operand" "m,r,r,J,n"))]
+ "lm32_move_ok (QImode, operands)"
+ "@
+ lbu %0, %1
+ or %0, %1, r0
+ sb %0, %1
+ sb %0, r0
+ addi %0, r0, %1"
+ [(set_attr "type" "load,arith,store,store,arith")]
+)
+
+(define_insn "*movhi_insn"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,m,r,r")
+ (match_operand:HI 1 "general_operand" "m,r,r,J,K,L"))]
+ "lm32_move_ok (HImode, operands)"
+ "@
+ lhu %0, %1
+ or %0, %1, r0
+ sh %0, %1
+ sh %0, r0
+ addi %0, r0, %1
+ ori %0, r0, %1"
+ [(set_attr "type" "load,arith,store,store,arith,arith")]
+)
+
+(define_insn "movsi_insn"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,m,r,r,r,r,r,r")
+ (match_operand:SI 1 "general_operand" "m,r,r,J,K,L,U,S,Y,n"))]
+ "lm32_move_ok (SImode, operands)"
+ "@
+ lw %0, %1
+ or %0, %1, r0
+ sw %0, %1
+ sw %0, r0
+ addi %0, r0, %1
+ ori %0, r0, %1
+ orhi %0, r0, hi(%1)
+ mva %0, gp(%1)
+ orhi %0, r0, hi(%1)
+ ori %0, r0, lo(%1); orhi %0, %0, hi(%1)"
+ [(set_attr "type" "load,arith,store,store,arith,arith,arith,arith,arith,arith")]
+)
+
+;; ---------------------------------
+;; sign and zero extension
+;; ---------------------------------
+
+(define_insn "*extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
+ "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
+ "@
+ lb %0, %1
+ sextb %0, %1"
+ [(set_attr "type" "load,arith")]
+)
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
+ ""
+ "@
+ lbu %0, %1
+ andi %0, %1, 0xff"
+ [(set_attr "type" "load,arith")]
+)
+
+(define_insn "*extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
+ "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
+ "@
+ lb %0, %1
+ sextb %0, %1"
+ [(set_attr "type" "load,arith")]
+)
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
+ ""
+ "@
+ lbu %0, %1
+ andi %0, %1, 0xff"
+ [(set_attr "type" "load,arith")]
+)
+
+(define_insn "*extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
+ "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)"
+ "@
+ lh %0, %1
+ sexth %0, %1"
+ [(set_attr "type" "load,arith")]
+)
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
+ ""
+ "@
+ lhu %0, %1
+ andi %0, %1, 0xffff"
+ [(set_attr "type" "load,arith")]
+)
+
+;; ---------------------------------
+;; compare
+;; ---------------------------------
+
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "register_or_int_operand")]))]
+ ""
+{
+ lm32_expand_scc (operands);
+ DONE;
+})
+
+(define_insn "*seq"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (eq:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_K_operand" "r,K")))]
+ ""
+ "@
+ cmpe %0, %z1, %2
+ cmpei %0, %z1, %2"
+ [(set_attr "type" "compare")]
+)
+
+(define_insn "*sne"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ne:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_K_operand" "r,K")))]
+ ""
+ "@
+ cmpne %0, %z1, %2
+ cmpnei %0, %z1, %2"
+ [(set_attr "type" "compare")]
+)
+
+(define_insn "*sgt"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (gt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_K_operand" "r,K")))]
+ ""
+ "@
+ cmpg %0, %z1, %2
+ cmpgi %0, %z1, %2"
+ [(set_attr "type" "compare")]
+)
+
+(define_insn "*sge"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ge:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_K_operand" "r,K")))]
+ ""
+ "@
+ cmpge %0, %z1, %2
+ cmpgei %0, %z1, %2"
+ [(set_attr "type" "compare")]
+)
+
+(define_insn "*sgtu"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (gtu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ ""
+ "@
+ cmpgu %0, %z1, %2
+ cmpgui %0, %z1, %2"
+ [(set_attr "type" "compare")]
+)
+
+(define_insn "*sgeu"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (geu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ ""
+ "@
+ cmpgeu %0, %z1, %2
+ cmpgeui %0, %z1, %2"
+ [(set_attr "type" "compare")]
+)
+
+;; ---------------------------------
+;; unconditional branch
+;; ---------------------------------
+
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "bi %0"
+ [(set_attr "type" "ubranch")]
+)
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "b %0"
+ [(set_attr "type" "uibranch")]
+)
+
+;; ---------------------------------
+;; conditional branch
+;; ---------------------------------
+
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "nonmemory_operand")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ lm32_expand_conditional_branch (operands);
+ DONE;
+}")
+
+(define_insn "*beq"
+ [(set (pc)
+ (if_then_else (eq:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ return get_attr_length (insn) == 4
+ ? "be %z0,%z1,%2"
+ : "bne %z0,%z1,8\n\tbi %2";
+}
+ [(set_attr "type" "cbranch")])
+
+(define_insn "*bne"
+ [(set (pc)
+ (if_then_else (ne:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ return get_attr_length (insn) == 4
+ ? "bne %z0,%z1,%2"
+ : "be %z0,%z1,8\n\tbi %2";
+}
+ [(set_attr "type" "cbranch")])
+
+(define_insn "*bgt"
+ [(set (pc)
+ (if_then_else (gt:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ return get_attr_length (insn) == 4
+ ? "bg %z0,%z1,%2"
+ : "bge %z1,%z0,8\n\tbi %2";
+}
+ [(set_attr "type" "cbranch")])
+
+(define_insn "*bge"
+ [(set (pc)
+ (if_then_else (ge:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ return get_attr_length (insn) == 4
+ ? "bge %z0,%z1,%2"
+ : "bg %z1,%z0,8\n\tbi %2";
+}
+ [(set_attr "type" "cbranch")])
+
+(define_insn "*bgtu"
+ [(set (pc)
+ (if_then_else (gtu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ return get_attr_length (insn) == 4
+ ? "bgu %z0,%z1,%2"
+ : "bgeu %z1,%z0,8\n\tbi %2";
+}
+ [(set_attr "type" "cbranch")])
+
+(define_insn "*bgeu"
+ [(set (pc)
+ (if_then_else (geu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ return get_attr_length (insn) == 4
+ ? "bgeu %z0,%z1,%2"
+ : "bgu %z1,%z0,8\n\tbi %2";
+}
+ [(set_attr "type" "cbranch")])
+
+;; ---------------------------------
+;; call
+;; ---------------------------------
+
+(define_expand "call"
+ [(parallel [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (clobber (reg:SI RA_REGNUM))
+ ])]
+ ""
+ "
+{
+ rtx addr = XEXP (operands[0], 0);
+ if (!CONSTANT_ADDRESS_P (addr))
+ XEXP (operands[0], 0) = force_reg (Pmode, addr);
+}")
+
+(define_insn "*call"
+ [(call (mem:SI (match_operand:SI 0 "call_operand" "r,s"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI RA_REGNUM))]
+ ""
+ "@
+ call %0
+ calli %0"
+ [(set_attr "type" "call,icall")]
+)
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
+ (clobber (reg:SI RA_REGNUM))
+ ])]
+ ""
+ "
+{
+ rtx addr = XEXP (operands[1], 0);
+ if (!CONSTANT_ADDRESS_P (addr))
+ XEXP (operands[1], 0) = force_reg (Pmode, addr);
+}")
+
+(define_insn "*call_value"
+ [(set (match_operand 0 "register_operand" "=r,r")
+ (call (mem:SI (match_operand:SI 1 "call_operand" "r,s"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI RA_REGNUM))]
+ ""
+ "@
+ call %1
+ calli %1"
+ [(set_attr "type" "call,icall")]
+)
+
+(define_insn "return_internal"
+ [(use (match_operand:SI 0 "register_operand" "r"))
+ (return)]
+ ""
+ "b %0"
+ [(set_attr "type" "uibranch")]
+)
+
+(define_expand "return"
+ [(return)]
+ "lm32_can_use_return ()"
+ ""
+)
+
+(define_expand "simple_return"
+ [(simple_return)]
+ ""
+ ""
+)
+
+(define_insn "*return"
+ [(return)]
+ "reload_completed"
+ "ret"
+ [(set_attr "type" "uibranch")]
+)
+
+(define_insn "*simple_return"
+ [(simple_return)]
+ ""
+ "ret"
+ [(set_attr "type" "uibranch")]
+)
+
+;; ---------------------------------
+;; switch/case statements
+;; ---------------------------------
+
+(define_expand "tablejump"
+ [(set (pc) (match_operand 0 "register_operand" ""))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "
+{
+ rtx target = operands[0];
+ if (flag_pic)
+ {
+ /* For PIC, the table entry is relative to the start of the table. */
+ rtx label = gen_reg_rtx (SImode);
+ target = gen_reg_rtx (SImode);
+ emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1]));
+ emit_insn (gen_addsi3 (target, operands[0], label));
+ }
+ emit_jump_insn (gen_tablejumpsi (target, operands[1]));
+ DONE;
+}")
+
+(define_insn "tablejumpsi"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "b %0"
+ [(set_attr "type" "ubranch")]
+)
+
+;; ---------------------------------
+;; arithmetic
+;; ---------------------------------
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_K_operand" "r,K")))]
+ ""
+ "@
+ add %0, %z1, %2
+ addi %0, %z1, %2"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))]
+ ""
+ "sub %0, %z1, %z2"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (mult:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_K_operand" "r,K")))]
+ "TARGET_MULTIPLY_ENABLED"
+ "@
+ mul %0, %z1, %2
+ muli %0, %z1, %2"
+ [(set_attr "type" "multiply")]
+)
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_DIVIDE_ENABLED"
+ "divu %0, %z1, %2"
+ [(set_attr "type" "divide")]
+)
+
+(define_insn "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umod:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_DIVIDE_ENABLED"
+ "modu %0, %z1, %2"
+ [(set_attr "type" "divide")]
+)
+
+;; ---------------------------------
+;; negation and inversion
+;; ---------------------------------
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))]
+ ""
+ "sub %0, r0, %z1"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))]
+ ""
+ "not %0, %z1"
+ [(set_attr "type" "arith")]
+)
+
+;; ---------------------------------
+;; logical
+;; ---------------------------------
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (and:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ ""
+ "@
+ and %0, %z1, %2
+ andi %0, %z1, %2"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ ""
+ "@
+ or %0, %z1, %2
+ ori %0, %z1, %2"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ ""
+ "@
+ xor %0, %z1, %2
+ xori %0, %z1, %2"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "*norsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (not:SI (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L"))))]
+ ""
+ "@
+ nor %0, %z1, %2
+ nori %0, %z1, %2"
+ [(set_attr "type" "arith")]
+)
+
+(define_insn "*xnorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L"))))]
+ ""
+ "@
+ xnor %0, %z1, %2
+ xnori %0, %z1, %2"
+ [(set_attr "type" "arith")]
+)
+
+;; ---------------------------------
+;; shifts
+;; ---------------------------------
+
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "")
+ (match_operand:SI 2 "register_or_L_operand" "")))]
+ ""
+{
+ if (!TARGET_BARREL_SHIFT_ENABLED)
+ {
+ if (!optimize_size
+ && satisfies_constraint_L (operands[2])
+ && INTVAL (operands[2]) <= 8)
+ {
+ int i;
+ int shifts = INTVAL (operands[2]);
+
+ if (shifts == 0)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ emit_insn (gen_addsi3 (operands[0], operands[1], operands[1]));
+ for (i = 1; i < shifts; i++)
+ emit_insn (gen_addsi3 (operands[0], operands[0], operands[0]));
+ DONE;
+ }
+ else
+ FAIL;
+ }
+})
+
+(define_insn "*ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ "TARGET_BARREL_SHIFT_ENABLED"
+ "@
+ sl %0, %z1, %2
+ sli %0, %z1, %2"
+ [(set_attr "type" "shift")]
+)
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "")
+ (match_operand:SI 2 "register_or_L_operand" "")))]
+ ""
+{
+ if (!TARGET_BARREL_SHIFT_ENABLED)
+ {
+ if (!optimize_size
+ && satisfies_constraint_L (operands[2])
+ && INTVAL (operands[2]) <= 8)
+ {
+ int i;
+ int shifts = INTVAL (operands[2]);
+ rtx one = GEN_INT (1);
+
+ if (shifts == 0)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ emit_insn (gen_ashrsi3_1bit (operands[0], operands[1], one));
+ for (i = 1; i < shifts; i++)
+ emit_insn (gen_ashrsi3_1bit (operands[0], operands[0], one));
+ DONE;
+ }
+ else
+ FAIL;
+ }
+})
+
+(define_insn "*ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ "TARGET_BARREL_SHIFT_ENABLED"
+ "@
+ sr %0, %z1, %2
+ sri %0, %z1, %2"
+ [(set_attr "type" "shift")]
+)
+
+(define_insn "ashrsi3_1bit"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "constant_M_operand" "M")))]
+ "!TARGET_BARREL_SHIFT_ENABLED"
+ "sri %0, %z1, %2"
+ [(set_attr "type" "shift")]
+)
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "")
+ (match_operand:SI 2 "register_or_L_operand" "")))]
+ ""
+{
+ if (!TARGET_BARREL_SHIFT_ENABLED)
+ {
+ if (!optimize_size
+ && satisfies_constraint_L (operands[2])
+ && INTVAL (operands[2]) <= 8)
+ {
+ int i;
+ int shifts = INTVAL (operands[2]);
+ rtx one = GEN_INT (1);
+
+ if (shifts == 0)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ emit_insn (gen_lshrsi3_1bit (operands[0], operands[1], one));
+ for (i = 1; i < shifts; i++)
+ emit_insn (gen_lshrsi3_1bit (operands[0], operands[0], one));
+ DONE;
+ }
+ else
+ FAIL;
+ }
+})
+
+(define_insn "*lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
+ (match_operand:SI 2 "register_or_L_operand" "r,L")))]
+ "TARGET_BARREL_SHIFT_ENABLED"
+ "@
+ sru %0, %z1, %2
+ srui %0, %z1, %2"
+ [(set_attr "type" "shift")]
+)
+
+(define_insn "lshrsi3_1bit"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "constant_M_operand" "M")))]
+ "!TARGET_BARREL_SHIFT_ENABLED"
+ "srui %0, %z1, %2"
+ [(set_attr "type" "shift")]
+)
+
+;; ---------------------------------
+;; function entry / exit
+;; ---------------------------------
+
+(define_expand "prologue"
+ [(const_int 1)]
+ ""
+ "
+{
+ lm32_expand_prologue ();
+ DONE;
+}")
+
+(define_expand "epilogue"
+ [(return)]
+ ""
+ "
+{
+ lm32_expand_epilogue ();
+ DONE;
+}")
+
+;; ---------------------------------
+;; nop
+;; ---------------------------------
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "type" "arith")]
+)
+
+;; ---------------------------------
+;; blockage
+;; ---------------------------------
+
+;; used to stop the scheduler from
+;; scheduling code across certain boundaries
+
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
+ ""
+ ""
+ [(set_attr "length" "0")]
+)