;; Machine description for C-SKY processors. ;; Copyright (C) 2018 Free Software Foundation, Inc. ;; Contributed by C-SKY Microsystems and Mentor Graphics. ;; ;; 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 ;; . */ ;; ------------------------------------------------------------------------ ;; Constant ;; ------------------------------------------------------------------------ ;; Register numbering. (define_constants [(CSKY_NGPR_REGS 32) (CSKY_NPARM_REGS 4) (CSKY_FIRST_PARM_REGNUM 0) (CSKY_FIRST_RET_REGNUM 0) (CSKY_FIRST_VFP_REGNUM 52) (CSKY_LAST_VFP_REGNUM 67) (CSKY_FIRST_HIGH_REGNUM 16) (CSKY_LAST_HIGH_REGNUM 31) (CSKY_FIRST_MINI_REGNUM 0) (CSKY_LAST_MINI_REGNUM 7) (CSKY_T0_REGNUM 12) (CSKY_T1_REGNUM 13) (CSKY_SP_REGNUM 14) (CSKY_CC_REGNUM 33) (CSKY_HI_REGNUM 34) (CSKY_LO_REGNUM 35) (CSKY_LR_REGNUM 15) (CSKY_LAST_HIGH_UNFIXED_REGNUM 25) (CSKY_GB_REGNUM 28) (CSKY_TLS_REGNUM 31) (CSKY_FIRST_EH_RETDATA_REGNUM 0) (CSKY_LAST_EH_RETDATA_REGNUM 1) (CSKY_EH_STACKADJ_REGNUM 2) (CSKY_STACKADJUST_REGNUM 4) ]) ;; Supported TLS relocations. (define_constants [(TLS_GD32 0) (TLS_LDM32 1) (TLS_LDO32 2) (TLS_IE32 3) (TLS_LE32 4) ]) ;; Unspec constants. (define_c_enum "unspec" [ ; Push or pop multiple operation: operand 0 is the first register, ; subsequent registers are in parallel (use ...) expressions. UNSPEC_PUSHPOP_MULT ; Represent TLS base, TLS offset, and TLS base + offset, respectively. UNSPEC_TLS_BASE UNSPEC_TLS_LABEL UNSPEC_TLS ; PIC symbol relocations. UNSPEC_PIC_SYMBOL_GOTPC UNSPEC_PIC_SYMBOL_GOTPC_GRS UNSPEC_PIC_SYMBOL_GOTOFF UNSPEC_PIC_SYMBOL_GOT UNSPEC_PIC_SYMBOL_PLT UNSPEC_PIC_SYMBOL_BSR UNSPEC_PIC_SYMBOL_GRS ; casesi dispatch table. UNSPEC_CSKY_CASESI ]) (define_c_enum "unspecv" [ ; Used for constant pools. VUNSPEC_ALIGN VUNSPEC_POOL_LABEL VUNSPEC_POOL_4 VUNSPEC_POOL_8 VUNSPEC_SYMBOL_REF ; Support for the eh_return pattern. VUNSPEC_EH_RETURN ]) ;; ------------------------------------------------------------------------ ;; Attributes ;; ------------------------------------------------------------------------ ;; LENGTH of an instruction (in bytes). (define_attr "length" "" (if_then_else (match_test "CSKY_TARGET_ARCH (CK801)") (const_int 2) (const_int 4))) ;; Used for ck801 to represent whether we need to use bsr for long ;; distance jumps. If set to yes, the function will save lr in the ;; prologue. (define_attr "far_jump" "yes,no" (const_string "no")) ;; Used for insn schedule. (define_attr "type" "alu,load,store,cmp,branch,cbranch,addsub,alu_ix,branch_jmp,call_jsr,call" (const_string "alu")) ;; ------------------------------------------------------------------------ ;; Include files ;; ------------------------------------------------------------------------ (include "constraints.md") (include "predicates.md") (include "csky_insn_fpu.md") (include "csky_insn_dsp.md") (include "csky_pipeline_ck801.md") (include "csky_pipeline_ck802.md") (include "csky_pipeline_ck803.md") (include "csky_pipeline_ck810.md") ;; ------------------------------------------------------------------------ ;; Mov insns ;; ------------------------------------------------------------------------ (define_mode_iterator QHI [QI HI]) (define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" " { rtx scratch = !can_create_pseudo_p () ? operands[0] : 0; if (can_create_pseudo_p () && MEM_P (operands[0])) { operands[1] = force_reg (SImode, operands[1]); emit_insn (gen_rtx_SET (operands[0], operands[1])); DONE; } /* Recognize the case where operand[1] is a reference to thread-local data and load its address to a register. */ if (csky_tls_referenced_p (operands[1])) { rtx tmp = operands[1]; rtx addend = NULL; if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS) { addend = XEXP (XEXP (tmp, 0), 1); tmp = XEXP (XEXP (tmp, 0), 0); } gcc_assert (GET_CODE (tmp) == SYMBOL_REF); gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0); tmp = csky_legitimize_tls_address (tmp, scratch); if (addend) { tmp = gen_rtx_PLUS (SImode, tmp, addend); tmp = force_operand (tmp, operands[0]); } operands[1] = tmp; } else if (flag_pic && (CONSTANT_P (operands[1]) || csky_symbol_mentioned_p (operands[1]) || csky_label_mentioned_p (operands[1]))) operands[1] = csky_legitimize_pic_address (operands[1], scratch, true); }" ) ;; Note that we conservatively estimate all load and store insns as having ;; a size of 4 bytes throughout even though some variants can be encoded ;; as 2-byte machine instructions. Getting more accurate instruction counts ;; would be better handled by calling into a C function than encoding it ;; as an RTL conditional here. ;; Also note that we don't count the extra space required for constant ;; pool entries here; that's handled by the constant pool entries themselves. ;; In -mno-constpool cases where we're relying on the assembler to create ;; the constant pool, we'll undercount branch lengths, but in that case the ;; assembler also handles branch relaxation as needed. It's only ck801 that ;; requires compiler cooperation when long branches are needed. (define_insn "*cskyv2_movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "=b,r,r,r, r, r, r,r, m,r,*y,*r,*v,*r,*v") (match_operand:SI 1 "general_operand" " b,r,I,Un,Uc,Uo,m,miF,r,c,*r,*y,*r,*v,*v"))] "CSKY_ISA_FEATURE (E2)" "* return csky_output_move (insn, operands, SImode);" [(set_attr "length" "2,4,4,4,4,8,4,4,4,4,4,4,4,4,4") (set_attr "type" "alu,alu,alu,alu,alu,alu,load,load,store,alu,alu,alu,alu,alu,alu")] ) (define_insn "*ck801_movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,a, a,r,r, m,r") (match_operand:SI 1 "general_operand" "r, Up,T,m,miF,r,c"))] "CSKY_ISA_FEATURE (E1)" "* return csky_output_ck801_move (insn, operands, SImode);" [(set_attr "length" "2,2,2,4,4,4,2") (set_attr "type" "alu,alu,alu,load,load,store,alu")] ) ;; Convert negative assignments to zero minus positive numbers. (define_split [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "const_int_operand" ""))] "satisfies_constraint_T (operands[1])" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] "operands[2] = const0_rtx;" ) ;; Convert const assignments to small number of assignments and left shift. (define_split [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "const_int_operand" ""))] "" [(set (match_dup 0) (match_dup 1)) (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] " { unsigned int base, shift; if (!csky_shifted_imm8_constant (INTVAL (operands[1]), &base, &shift)) FAIL; if (shift == 0) FAIL; operands[1] = GEN_INT (base); operands[2] = GEN_INT (shift); }" ) (define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" " { if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (HImode, operands[1]); else if (CONSTANT_P (operands[1]) && (GET_CODE (operands[1]) != CONST_INT || (! CSKY_CONST_OK_FOR_I (INTVAL (operands[1])) && ! CSKY_CONST_OK_FOR_Ub (INTVAL (operands[1])) && ! CSKY_CONST_OK_FOR_Uc (INTVAL (operands[1])))) && ! reload_completed && ! reload_in_progress) { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_movsi (reg, operands[1])); operands[1] = gen_lowpart (HImode, reg); } }" ) (define_insn "*cskyv2_movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=b,r,r,r, r, r, r,r, m,r,*y,*r,*v,*r,*v") (match_operand:HI 1 "general_operand" " b,r,I,Un,Uc,Uo,m,miF,r,c,*r,*y,*r,*v,*v"))] "CSKY_ISA_FEATURE (E2)" "* return csky_output_move (insn, operands, HImode);" [(set_attr "length" "2,4,4,4,4,8,4,4,4,4,4,4,4,4,4") (set_attr "type" "alu,alu,alu,alu,alu,alu,load,load,store,alu,alu,alu,alu,alu,alu")] ) (define_insn "*ck801_movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,a, a,r,r, m,r") (match_operand:HI 1 "general_operand" "r, Up,T,m,miF,r,c"))] "CSKY_ISA_FEATURE (E1)" "* return csky_output_ck801_move (insn, operands, HImode);" [(set_attr "length" "2,2,2,4,4,4,2") (set_attr "type" "alu,alu,alu,load,load,store,alu")] ) (define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 1 "general_operand" ""))] "" " { if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM) operands[1] = force_reg (QImode, operands[1]); else if (CONSTANT_P (operands[1]) && (GET_CODE (operands[1]) != CONST_INT || (! CSKY_CONST_OK_FOR_I (INTVAL (operands[1])) && ! CSKY_CONST_OK_FOR_Ub (INTVAL (operands[1])) && ! CSKY_CONST_OK_FOR_Uc (INTVAL (operands[1])))) && ! reload_completed && ! reload_in_progress) { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_movsi (reg, operands[1])); operands[1] = gen_lowpart (QImode, reg); } }" ) (define_insn "*cskyv2_movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=b,r,r,r, r, r, r,r, m,r,*y,*r,*v,*r,*v") (match_operand:QI 1 "general_operand" " b,r,I,Un,Uc,Uo,m,miF,r,c,*r,*y,*r,*v,*v"))] "CSKY_ISA_FEATURE (E2)" "* return csky_output_move (insn, operands, QImode);" [(set_attr "length" "2,4,4,4,4,8,4,4,4,4,4,4,4,4,4") (set_attr "type" "alu,alu,alu,alu,alu,alu,load,load,store,alu,alu,alu,alu,alu,alu")] ) (define_insn "*ck801_movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,a, a,r,r, m,r") (match_operand:QI 1 "general_operand" "r, Up,T,m,miF,r,c"))] "CSKY_ISA_FEATURE (E1)" "* return csky_output_ck801_move (insn, operands, QImode);" [(set_attr "length" "2,2,2,4,4,4,2") (set_attr "type" "alu,alu,alu,load,load,store,alu")] ) (define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" "if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM) operands[1] = force_reg (DImode, operands[1]);" ) ;; Convert negative assignments to zero minus positive numbers. (define_split [(set (match_operand:QHI 0 "register_operand" "") (match_operand:QHI 1 "const_int_operand" ""))] "satisfies_constraint_T (operands[1])" [(set (match_dup 4) (match_dup 2)) (set (match_dup 4) (match_dup 3)) (set (match_dup 0) (match_dup 5))] " { int low; if (TARGET_BIG_ENDIAN) low = 4 - mode_size[GET_MODE (operands[0])]; else low = 0; operands[2] = const0_rtx; if (can_create_pseudo_p ()) operands[4] = gen_reg_rtx (SImode); else operands[4] = gen_rtx_REG (SImode, REGNO (operands[0])); operands[3] = gen_rtx_PLUS (SImode, operands[4], operands[1]); operands[5] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[4], low); }" ) ;; Convert const assignments to small number of assignments and left shift. (define_split [(set (match_operand:QHI 0 "register_operand" "") (match_operand:QHI 1 "const_int_operand" ""))] "" [(set (match_dup 3) (match_dup 1)) (set (match_dup 3) (ashift:SI (match_dup 3) (match_dup 2))) (set (match_dup 0) (match_dup 4))] " { unsigned int base, shift; int low; if (!csky_shifted_imm8_constant (INTVAL (operands[1]), &base, &shift)) FAIL; if (shift == 0) FAIL; if (TARGET_BIG_ENDIAN) low = 4 - mode_size[GET_MODE (operands[0])]; else low = 0; operands[1] = GEN_INT (base); operands[2] = GEN_INT (shift); if (can_create_pseudo_p ()) operands[3] = gen_reg_rtx (SImode); else operands[3] = gen_rtx_REG (SImode, REGNO (operands[0])); operands[4] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3], low); }" ) (define_insn "*csky_movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "=b,r,r, r,r, m,*r,*y,*v,*r,*v") (match_operand:DI 1 "general_operand" " b,r,Ud,m,miF,r,*y,*r,*r,*v,*v"))] "CSKY_ISA_FEATURE (E2)" "* return csky_output_movedouble (operands, DImode);" [(set_attr "length" "4,8,8,8,8,8,16,16,16,16,16") (set_attr "type" "alu,alu,alu,load,load,store,alu,alu,alu,alu,alu")] ) (define_insn "*ck801_movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,a, a,r,r, m") (match_operand:DI 1 "general_operand" "r, Up,T,m,miF,r"))] "CSKY_ISA_FEATURE (E1)" "* return csky_output_ck801_movedouble (operands, DImode);" [(set_attr "length" "4,4,4,8,8,8") (set_attr "type" "alu,alu,alu,load,load,store")] ) ;; Float mov instructions. (define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" ""))] "" " if (GET_CODE (operands[0]) == MEM && can_create_pseudo_p ()) operands[1] = force_reg (SFmode, operands[1]); " ) ;; FIXME: maybe the vreg load/stores should have their own type attr. (define_insn "*csky_movsf_fpv2" [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,v,r,r,r, m,Q,v,v,v") (match_operand:SF 1 "general_operand" " b,r,r,v,m,mF,r,v,Q,v,m"))] "CSKY_ISA_FEATURE (fpv2_sf)" "* return csky_output_move (insn, operands, SFmode);" [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4") (set_attr "type" "alu,alu,alu,alu,load,load,store,alu,alu,alu,alu")] ) (define_insn "*ck801_movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r, m") (match_operand:SF 1 "general_operand" " r,m,mF,r"))] "CSKY_ISA_FEATURE (E1)" "* return csky_output_ck801_move (insn, operands, SFmode);" [(set_attr "length" "2,4,4,4") (set_attr "type" "alu,load,load,store")] ) (define_insn "*csky_movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,r,r, m") (match_operand:SF 1 "general_operand" " b,r,m,mF,r"))] "CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (fpv2_sf)" "* return csky_output_move (insn, operands, SFmode);" [(set_attr "length" "2,4,4,4,4") (set_attr "type" "alu,alu,load,load,store")] ) (define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] "" " if (GET_CODE (operands[0]) == MEM && can_create_pseudo_p ()) operands[1] = force_reg (DFmode, operands[1]); " ) ;; FIXME: maybe the vreg load/stores should have their own type attr. (define_insn "*csky_movdf_fpv2" [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,v,r,r,r, m,Q,v,v,v") (match_operand:DF 1 "general_operand" "b,r,r,v,m,mF,r,v,Q,v,m"))] "CSKY_ISA_FEATURE (fpv2_df)" "* return csky_output_movedouble (operands, DFmode);" [(set_attr "length" "4,8,8,8,8,8,8,8,8,8,8") (set_attr "type" "alu,alu,alu,alu,load,load,store,alu,alu,alu,alu")] ) (define_insn "*ck801_movdf" [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,r, m") (match_operand:DF 1 "general_operand" " r,m,mF,r"))] "CSKY_ISA_FEATURE (E1)" "* return csky_output_ck801_movedouble (operands, DFmode);" [(set_attr "length" "4,8,8,8") (set_attr "type" "alu,load,load,store")] ) (define_insn "*csky_movdf" [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,r,r, m") (match_operand:DF 1 "general_operand" " b,r,m,mF,r"))] "CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (fpv2_df)" "* return csky_output_movedouble (operands, DFmode);" [(set_attr "length" "4,8,8,8,8") (set_attr "type" "alu,alu,load,load,store")] ) ;; The only CCmode move supported is a nop. Without this pattern, ;; CSE is unable to eliminate redundant comparisons in conditional ;; execution expressions. (define_insn "*movcc_nop" [(set (reg:CC CSKY_CC_REGNUM) (reg:CC CSKY_CC_REGNUM))] "" "" [(set_attr "length" "0")] ) ;; ------------------------------------------------------------------------ ;; Conditional mov insns ;; ------------------------------------------------------------------------ ;; Only handle integer comparisons because float and double require ;; library calls. (define_expand "movsicc" [(set (match_operand 0 "register_operand" "") (if_then_else:SI (match_operand 1 "ordered_comparison_operator" "") (match_operand:SI 2 "register_operand" "") (match_operand:SI 3 "register_operand" "")))] "CSKY_ISA_FEATURE (E2)" " { bool invert = csky_emit_compare (GET_CODE (operands[1]), XEXP (operands[1], 0), XEXP (operands[1], 1)); if (invert) emit_insn (gen_movf (operands[0], operands[2], operands[3])); else emit_insn (gen_movt (operands[0], operands[2], operands[3])); DONE; }") (define_insn "movt" [(set (match_operand:SI 0 "register_operand" "=r, r") (if_then_else:SI (ne (reg:CC CSKY_CC_REGNUM) (const_int 0)) (match_operand:SI 1 "register_operand" "r, 0") (match_operand:SI 2 "register_operand" "0, r")))] "CSKY_ISA_FEATURE (E2)" "@ movt\t%0, %1 movf\t%0, %2" [(set_attr "length" "4,4")] ) (define_insn "movf" [(set (match_operand:SI 0 "register_operand" "=r, r") (if_then_else:SI (eq (reg:CC CSKY_CC_REGNUM) (const_int 0)) (match_operand:SI 1 "register_operand" "r, 0") (match_operand:SI 2 "register_operand" "0, r")))] "CSKY_ISA_FEATURE (E2)" "@ movf\t%0, %1 movt\t%0, %2" [(set_attr "length" "4,4")] ) (define_expand "cstoresi4" [(set (match_operand:SI 0 "register_operand" "") (match_operator 1 "ordered_comparison_operator" [(match_operand:SI 2 "csky_compare_operand" "") (match_operand:SI 3 "nonmemory_operand" "")]))] "" " { bool invert = csky_emit_compare (GET_CODE (operands[1]), operands[2], operands[3]); if (invert) emit_insn (gen_mvcv (operands[0])); else if (CSKY_ISA_FEATURE (E1)) { emit_insn (gen_movsi (operands[0], const0_rtx)); emit_insn (gen_ck801_addc (operands[0], operands[0], operands[0])); } else emit_insn (gen_mvc (operands[0])); DONE; }" ) (define_insn "mvc" [(set (match_operand:SI 0 "register_operand" "=r") (ne:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)))] "CSKY_ISA_FEATURE (E2)" "mvc\t%0" ) (define_insn "mvcv" [(set (match_operand:SI 0 "register_operand" "=r") (eq:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)))] "" "mvcv\t%0" ) ;; ------------------------------------------------------------------------ ;; Arithmetic insns ;; ------------------------------------------------------------------------ (define_insn "abssi2" [(set (match_operand:SI 0 "register_operand" "=r") (abs:SI (match_operand:SI 1 "register_operand" "r")))] "CSKY_ISA_FEATURE (2E3)" "abs\t%0, %1" [(set_attr "type" "alu")] ) (define_insn "extvsi" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extract:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "const_int_operand" "") (match_operand:SI 3 "const_int_operand" "")))] "CSKY_ISA_FEATURE (2E3)" { operands[2] = GEN_INT (INTVAL (operands[3]) + INTVAL (operands[2]) - 1); return \"sext\t%0, %1, %2, %3\"; } ) (define_insn "insvsi" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") (match_operand:SI 1 "const_int_operand" "i") (match_operand:SI 2 "const_int_operand" "i")) (match_operand:SI 3 "register_operand" "r"))] "CSKY_ISA_FEATURE (2E3)" { operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1]) - 1); return \"ins\t%0, %3, %1, %2\"; } ) (define_expand "bseti" [(set (match_operand:SI 0 "register_operand" "") (ior:SI (match_operand:SI 1 "register_operand" "") (ashift:SI (const_int 1) (match_operand:SI 2 "csky_literal_K_operand" ""))))] "" "") (define_insn "smart_bseti" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (match_operand:SI 1 "register_operand" "0") (ashift:SI (const_int 1) (match_operand:SI 2 "csky_literal_K_operand" "K"))))] "TARGET_MINI_REGISTERS" "bseti\t%0, %2" [(set_attr "length" "2")]) (define_insn "fast_bseti" [(set (match_operand:SI 0 "register_operand" "=a,r") (ior:SI (match_operand:SI 1 "register_operand" "0,r") (ashift:SI (const_int 1) (match_operand:SI 2 "csky_literal_K_operand" "K,K"))))] "!TARGET_MINI_REGISTERS" "bseti\t%0, %1, %2" [(set_attr "length" "2,4")]) (define_expand "bclri" [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_operand:SI 1 "register_operand" "") (not:SI (ashift:SI (const_int 1) (match_operand:SI 2 "csky_literal_K_operand" "")))))] "" "") (define_insn "smart_bclri" [(set (match_operand:SI 0 "register_operand" "=r") (and:SI (match_operand:SI 1 "register_operand" "0") (not:SI (ashift:SI (const_int 1) (match_operand:SI 2 "csky_literal_K_operand" "K")))))] "TARGET_MINI_REGISTERS" "bclri\t%0, %2" [(set_attr "length" "2")]) (define_insn "fast_bclri" [(set (match_operand:SI 0 "register_operand" "=a,r") (and:SI (match_operand:SI 1 "register_operand" "0,r") (not:SI (ashift:SI (const_int 1) (match_operand:SI 2 "csky_literal_K_operand" "K,K")))))] "!TARGET_MINI_REGISTERS" "bclri\t%0, %1, %2" [(set_attr "length" "2,4")]) ;; Shift instructions. (define_expand "ashlsi3" [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_K_operand" "")))] "" "" ) (define_insn "*cskyv2_ashlsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,a,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,r,a,r") (match_operand:SI 2 "csky_arith_K_operand" "b,r,K,K")))] "CSKY_ISA_FEATURE (E2)" "@ lsl %0, %1, %2 lsl %0, %1, %2 lsli %0, %1, %2 lsli %0, %1, %2" [(set_attr "length" "2,4,2,4")] ) (define_insn "ck801_ashlsi3" [(set (match_operand:SI 0 "register_operand" "=a,r") (ashift:SI (match_operand:SI 1 "register_operand" "a,0") (match_operand:SI 2 "csky_arith_K_operand" "K,r")))] "CSKY_ISA_FEATURE (E1)" "@ lsli %0, %1, %2 lsl %0, %1, %2" ) (define_expand "ashrsi3" [(set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_K_operand" "")))] "" "" ) (define_insn "*cskyv2_ashrsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,a,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,r,a,r") (match_operand:SI 2 "csky_arith_K_operand" "b,r,K,K")))] "CSKY_ISA_FEATURE (E2)" "@ asr %0, %1, %2 asr %0, %1, %2 asri %0, %1, %2 asri %0, %1, %2" [(set_attr "length" "2,4,2,4")] ) (define_insn "*ck801_ashrsi3" [(set (match_operand:SI 0 "register_operand" "=a,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "a,0") (match_operand:SI 2 "csky_arith_K_operand" "K,r")))] "CSKY_ISA_FEATURE (E1)" "@ asri %0, %1, %2 asr %0, %1, %2" ) (define_expand "lshrsi3" [(set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_K_operand" "")))] "" "" ) (define_insn "*cskyv2_lshrsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,a,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,r,a,r") (match_operand:SI 2 "csky_arith_K_operand" "b,r,K,K")))] "CSKY_ISA_FEATURE (E2)" "@ lsr %0, %1, %2 lsr %0, %1, %2 lsri %0, %1, %2 lsri %0, %1, %2" [(set_attr "length" "2,4,2,4")] ) (define_insn "ck801_lshrsi3" [(set (match_operand:SI 0 "register_operand" "=a,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "a,0") (match_operand:SI 2 "csky_arith_K_operand" "K,r")))] "CSKY_ISA_FEATURE (E1)" "@ lsri %0, %1, %2 lsr %0, %1, %2" ) (define_expand "rotlsi3" [(set (match_operand:SI 0 "register_operand" "") (rotate:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_K_operand" "")))] "" "" ) (define_insn "*cskyv2_rotlsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,r") (rotate:SI (match_operand:SI 1 "register_operand" "0,r,r") (match_operand:SI 2 "csky_arith_K_operand" "b,r,K")))] "CSKY_ISA_FEATURE (E2)" "@ rotl %0, %1, %2 rotl %0, %1, %2 rotli %0, %1, %2" [(set_attr "length" "2,4,4")] ) (define_insn "*ck801_rotlsi3" [(set (match_operand:SI 0 "register_operand" "=r") (rotate:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "csky_arith_K_operand" "r")))] "CSKY_ISA_FEATURE (E1)" "rotl %0, %1, %2" ) ;; Add instructions. ;; C-SKY addi and subi machine instructions only accept positive immediate ;; values, so we have to special case immediates <= 0 in these patterns. (define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] "" "" ) (define_insn "smart_addsi3" [(set (match_operand:SI 0 "register_operand" "=a,r,a,a,a,a, r,r") (plus:SI (match_operand:SI 1 "register_operand" "%a,0,0,a,0,a, r,r") (match_operand:SI 2 "nonmemory_operand" "a, r,N,L,T,Us,M,Um")))] "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2) && operands[0] != stack_pointer_rtx && operands[1] != stack_pointer_rtx" "@ addu\t%0, %1, %2 addu\t%0, %1, %2 addi\t%0, %1, %2 addi\t%0, %1, %2 subi\t%0, %1, %M2 subi\t%0, %1, %M2 addi\t%0, %1, %2 subi\t%0, %1, %M2" [(set_attr "length" "2,2,2,2,2,2,4,4") (set_attr "type" "addsub")] ) (define_insn_and_split "*smart_addsi3_sp" [(set (match_operand:SI 0 "register_operand" "=z,z, z,a,&a,z,a,r") (plus:SI (match_operand:SI 1 "register_operand" "0, 0, 0,z, z,a,z,r") (match_operand:SI 2 "nonmemory_operand" "P, Ug,r,Uq,i,a,a,M")))] "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2) && (operands[0] == stack_pointer_rtx || operands[1] == stack_pointer_rtx)" "@ addi\t%0, %1, %2 subi\t%0, %1, %M2 addu\t%0, %1, %2 addi\t%0, %1, %2 # addu\t%0, %1, %2 addu\t%0, %1, %2 addi\t%0, %1, %2" "(operands[0] != stack_pointer_rtx && operands[1] == stack_pointer_rtx && !satisfies_constraint_Uq (operands[2]))" [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 0)))] "emit_move_insn (operands[0], operands[2]);" [(set_attr "type" "addsub")] ) (define_insn "*ck801_addsi3" [(set (match_operand:SI 0 "register_operand" "=r,a,a,a,a,a, !z,!z,!z,a") (plus:SI (match_operand:SI 1 "register_operand" "%0,a,0,a,0,a, 0, 0, 0, !z") (match_operand:SI 2 "nonmemory_operand" "r, a,N,L,T,Us,P, Ug,r, Uq")))] "CSKY_ISA_FEATURE (E1)" "@ addu\t%0, %1, %2 addu\t%0, %1, %2 addi\t%0, %1, %2 addi\t%0, %1, %2 subi\t%0, %1, %M2 subi\t%0, %1, %M2 addi\t%0, %1, %2 subi\t%0, %1, %M2 addu\t%0, %1, %2 addi\t%0, %1, %2" [(set_attr "type" "addsub")] ) (define_insn "fast_addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r, r") (plus:SI (match_operand:SI 1 "register_operand" "%r,r, r") (match_operand:SI 2 "nonmemory_operand" "M, Um,r")))] "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)" "@ addi\t%0, %1, %2 subi\t%0, %1, %M2 addu\t%0, %1, %2" [(set_attr "type" "addsub")] ) (define_expand "adddi3" [(parallel [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "csky_arith_int1_operand" ""))) (clobber (reg:CC CSKY_CC_REGNUM))])] "" " if (CSKY_ISA_FEATURE (E1) && (GET_CODE (operands[2]) != REG)) operands[2] = force_reg (DImode, operands[2]); " ) /* Note that the csky addc instruction both reads and writes the carry bit. The purpose of the initial cmplt instruction in the expansion is to clear the carry bit before adding the lo words. */ (define_insn_and_split "*cskyv2_adddi3" [(set (match_operand:DI 0 "register_operand" "=&b,&r") (plus:DI (match_operand:DI 1 "register_operand" "%0,r") (match_operand:DI 2 "register_operand" "b, r"))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cmpltsi_r (copy_rtx (l1), copy_rtx (l1))); emit_insn (gen_cskyv2_addc (l0, l1, l2)); emit_insn (gen_cskyv2_addc (h0, h1, h2)); DONE; } [(set_attr "length" "6,12")] ) (define_insn_and_split "*ck801_adddi3" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "r"))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E1)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cmpltsi_r (copy_rtx (l1), copy_rtx (l1))); emit_insn (gen_ck801_addc (l0, l1, l2)); emit_insn (gen_ck801_addc (h0, h1, h2)); DONE; } [(set_attr "length" "6")] ) ;; Special case for "longlong += 1". (define_insn_and_split "*cskyv2_adddi1_1" [(set (match_operand:DI 0 "register_operand" "=&r") (plus:DI (match_operand:DI 1 "register_operand" "0") (const_int 1))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); if (TARGET_MINI_REGISTERS) { emit_insn (gen_smart_addsi3 (l0, copy_rtx (l0), gen_int_mode (1, SImode))); emit_insn (gen_smart_cmpnesi_i (copy_rtx (l0), gen_int_mode (0, SImode))); emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0), gen_int_mode (1, SImode))); } else { emit_insn (gen_fast_addsi3 (l0, copy_rtx (l0), gen_int_mode (1, SImode))); emit_insn (gen_fast_cmpnesi_i (copy_rtx (l0), gen_int_mode (0, SImode))); emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0), gen_int_mode (1, SImode))); } DONE; } [(set (attr "length") (if_then_else (match_test "TARGET_MINI_REGISTERS") (const_int 8) (const_int 12)))] ) ;; sub instructions. (define_expand "subsi3" [(set (match_operand:SI 0 "register_operand" "") (minus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] "" "" ) (define_insn "smart_subsi3" [(set (match_operand:SI 0 "register_operand" "=a,a,a,a,a,a") (minus:SI (match_operand:SI 1 "register_operand" "a, 0,0,a,0,a") (match_operand:SI 2 "nonmemory_operand" "a, a,N,L,T,Us")))] "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2) && operands[0] != stack_pointer_rtx && operands[1] != stack_pointer_rtx" "@ subu\t%0, %1, %2 subu\t%0, %1, %2 subi\t%0, %1, %2 subi\t%0, %1, %2 addi\t%0, %1, %M2 addi\t%0, %1, %M2" [(set_attr "length" "2,2,2,2,2,2") (set_attr "type" "addsub")] ) (define_insn "*smart_subsi3_sp" [(set (match_operand:SI 0 "register_operand" "=z,z, z,a, a,r") (minus:SI (match_operand:SI 1 "register_operand" "0, 0, 0,z, a,r") (match_operand:SI 2 "nonmemory_operand" "P, Ug,a,Ur,a,M")))] "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2) && (operands[0] == stack_pointer_rtx || operands[1] == stack_pointer_rtx)" "@ subi\t%0, %1, %2 addi\t%0, %1, %M2 subu\t%0, %1, %2 addi\t%0, %1, %M2 subu\t%0, %1, %2 subi\t%0, %1, %2" [(set_attr "length" "2,2,2,2,2,4") (set_attr "type" "addsub")] ) (define_insn "*ck801_subsi3" [(set (match_operand:SI 0 "register_operand" "=a,a,a,a,a,a") (minus:SI (match_operand:SI 1 "register_operand" "0, a,0,a,0,a") (match_operand:SI 2 "nonmemory_operand" "a, a,N,L,T,Us")))] "CSKY_ISA_FEATURE (E1) && operands[0] != stack_pointer_rtx && operands[1] != stack_pointer_rtx" "@ subu\t%0, %1, %2 subu\t%0, %1, %2 subi\t%0, %1, %2 subi\t%0, %1, %2 addi\t%0, %1, %M2 addi\t%0, %1, %M2" [(set_attr "type" "addsub")] ) (define_insn "*ck801_subsi3_sp" [(set (match_operand:SI 0 "register_operand" "=a,z,z, z") (minus:SI (match_operand:SI 1 "register_operand" "z, 0,0, 0") (match_operand:SI 2 "nonmemory_operand" "Ur,P,Ug,r")))] "CSKY_ISA_FEATURE (E1) && (operands[0] == stack_pointer_rtx || operands[1] == stack_pointer_rtx)" "@ addi\t%0, %1, %M2 subi\t%0, %1, %2 addi\t%0, %1, %M2 subu\t%0, %1, %2" [(set_attr "type" "addsub")] ) (define_insn "fast_subsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (minus:SI (match_operand:SI 1 "register_operand" "r, r,r") (match_operand:SI 2 "nonmemory_operand" "r, M,Um")))] "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)" "@ subu\t%0, %1, %2 subi\t%0, %1, %2 addi\t%0, %1, %M2" [(set_attr "type" "addsub")] ) (define_expand "subdi3" [(parallel [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (reg:CC CSKY_CC_REGNUM))])] "" "" ) /* Note that the csky subc instruction both reads and writes the C bit. The purpose of the initial cmphs instruction in the expansion is to set the C bit before subtracting the lo words. */ (define_insn_and_split "*cskyv2_subdi3" [(set (match_operand:DI 0 "register_operand" "=&b,&r") (minus:DI (match_operand:DI 1 "register_operand" "0, r") (match_operand:DI 2 "register_operand" "b, r"))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cmpgeusi_r (copy_rtx (l1), copy_rtx (l1))); emit_insn (gen_cskyv2_subc (l0, l1, l2)); emit_insn (gen_cskyv2_subc (h0, h1, h2)); DONE; } [(set_attr "length" "6,12")] ) (define_insn_and_split "*ck801_subdi3" [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "register_operand" "r"))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E1)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cmpgeusi_r (copy_rtx (l1), copy_rtx (l1))); emit_insn (gen_ck801_subc (l0, l1, l2)); emit_insn (gen_ck801_subc (h0, h1, h2)); DONE; } [(set_attr "length" "6")] ) ;; Special case for "longlong -= 1". (define_insn_and_split "*cskyv2_subdi1_1" [(set (match_operand:DI 0 "register_operand" "=&r") (plus:DI (match_operand:DI 1 "register_operand" "0") (const_int -1))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); if (TARGET_MINI_REGISTERS) { emit_insn (gen_smart_cmpnesi_i (copy_rtx (l0), gen_int_mode (0, SImode))); emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0), gen_int_mode (-1, SImode))); emit_insn (gen_smart_subsi3 (l0, copy_rtx (l0), gen_int_mode (1, SImode))); } else { emit_insn (gen_fast_cmpnesi_i (copy_rtx (l0), gen_int_mode (0, SImode))); emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0), gen_int_mode (-1, SImode))); emit_insn (gen_fast_subsi3 (l0, copy_rtx (l0), gen_int_mode (1, SImode))); } DONE; } [(set (attr "length") (if_then_else (match_test "TARGET_MINI_REGISTERS") (const_int 8) (const_int 12)))] ) ;; Add with carry. (define_insn "cskyv2_addc" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (ne:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)) (plus:SI (match_operand:SI 1 "register_operand" "%0,r") (match_operand:SI 2 "register_operand" "r,r")))) (set (reg:CC CSKY_CC_REGNUM) (compare:CC (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] "CSKY_ISA_FEATURE (E2)" "addc\t%0, %1, %2" [(set_attr "length" "2,4") (set_attr "type" "addsub")] ) (define_insn "ck801_addc" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (ne:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)) (plus:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "r")))) (set (reg:CC CSKY_CC_REGNUM) (compare:CC (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] "CSKY_ISA_FEATURE (E1)" "addc\t%0, %1, %2" [(set_attr "length" "2") (set_attr "type" "addsub")] ) ;; Subtract with borrow. ;; Note that in these insns, the sense of C bit is reversed; they subtract 1 ;; if the C bit is not set, and on output the bit is set to 0 for borrow ;; and 1 for no borrow. (define_insn "cskyv2_subc" [(set (match_operand:SI 0 "register_operand" "=r,r") (minus:SI (match_operand:SI 1 "register_operand" "0, r") (plus:SI (match_operand:SI 2 "register_operand" "r, r") (eq:SI (reg:CC CSKY_CC_REGNUM) (const_int 0))))) (set (reg:CC CSKY_CC_REGNUM) (not (compare:CC (match_dup 1) (match_dup 2))))] "CSKY_ISA_FEATURE (E2)" "subc\t%0, %1, %2" [(set_attr "length" "2,4") (set_attr "type" "addsub")] ) (define_insn "ck801_subc" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "0") (plus:SI (match_operand:SI 2 "register_operand" "r") (eq:SI (reg:CC CSKY_CC_REGNUM) (const_int 0))))) (set (reg:CC CSKY_CC_REGNUM) (not (compare:CC (match_dup 1) (match_dup 2))))] "CSKY_ISA_FEATURE (E1)" "subc\t%0, %1, %2" [(set_attr "length" "2") (set_attr "type" "addsub")] ) ;; ------------------------------------------------------------------------ ;; Multiplication insns ;; ------------------------------------------------------------------------ (define_expand "mulsi3" [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] "" "" ) (define_insn "*cskyv2_mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E2)" "mult\t%0, %1, %2" ) (define_insn "*ck801_mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E1)" "mult\t%0, %1, %2" ) (define_insn "mulhisi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r")) (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] "CSKY_ISA_FEATURE (2E3)" "mulsh\t%0, %1, %2" ) ;; ------------------------------------------------------------------------ ;; Conditional add insns ;; ------------------------------------------------------------------------ (define_expand "addsicc" [(match_operand:SI 0 "register_operand" "") (match_operand 1 "ordered_comparison_operator" "") (match_operand:SI 2 "register_operand" "") (match_operand:SI 3 "csky_literal_K_Uh_operand" "")] "CSKY_ISA_FEATURE (E2)" " { bool invert = csky_emit_compare (GET_CODE (operands[1]), XEXP (operands[1], 0), XEXP (operands[1], 1)); if (invert) emit_insn (gen_cskyv2_addcc_invert (operands[0], operands[2], operands[3])); else emit_insn (gen_cskyv2_addcc (operands[0], operands[2], operands[3])); DONE; }" ) (define_insn_and_split "cskyv2_addcc" [(set (match_operand:SI 0 "register_operand" "=r,r,&r,&r") (if_then_else:SI (ne (reg:CC CSKY_CC_REGNUM) (const_int 0)) (plus:SI (match_operand:SI 1 "register_operand" "0,0,r,r") (match_operand:SI 2 "csky_literal_K_Uh_operand" "K,Uh,K,Uh")) (match_dup 1)))] "CSKY_ISA_FEATURE (E2)" "@ inct\t%0, %1, %2 dect\t%0, %1, %M2 # #" "reload_completed && !rtx_equal_p (operands[0], operands[1])" [(set (match_dup 0) (if_then_else:SI (ne (reg:CC CSKY_CC_REGNUM) (const_int 0)) (plus:SI (match_dup 0) (match_dup 2))))] { emit_insn (gen_movf (copy_rtx (operands[0]), copy_rtx (operands[1]), copy_rtx (operands[0]))); } [(set_attr "length" "4,4,8,8") (set_attr "type" "addsub")] ) (define_insn_and_split "cskyv2_addcc_invert" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") (if_then_else:SI (eq (reg:CC CSKY_CC_REGNUM) (const_int 0)) (plus:SI (match_operand:SI 1 "register_operand" "0,0,r,r") (match_operand:SI 2 "csky_literal_K_Uh_operand" "K,Uh,K,Uh")) (match_dup 1)))] "CSKY_ISA_FEATURE (E2)" "@ incf\t%0, %1, %2 decf\t%0, %1, %M2 # #" "reload_completed && !rtx_equal_p (operands[0], operands[1])" [(set (match_dup 0) (if_then_else:SI (eq (reg:CC CSKY_CC_REGNUM) (const_int 0)) (plus:SI (match_dup 0) (match_dup 2))))] { emit_insn (gen_movt (copy_rtx (operands[0]), copy_rtx (operands[1]), copy_rtx (operands[0]))); } [(set_attr "length" "4,4,8,8") (set_attr "type" "addsub")] ) ;; ------------------------------------------------------------------------ ;; Extzv insns ;; ------------------------------------------------------------------------ (define_expand "extzvsi" [(set (match_operand:SI 0 "register_operand" "") (zero_extract:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" "") (match_operand:SI 3 "const_int_operand" "")))] "" "{ /* ck802 has xtrb but not zext, so we'll use xtrb if we can. */ if (CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (2E3) && (INTVAL (operands[2]) == 8) && (INTVAL (operands[3]) % 8 == 0)) { rtx xtrb = gen_rtx_SET (operands[0], gen_rtx_ZERO_EXTRACT (SImode, operands[1], operands[2], operands[3])); emit (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, xtrb, gen_hard_reg_clobber (CCmode, 33)))); DONE; } else if (!CSKY_ISA_FEATURE (2E3)) { /* Use lsri and lsli to do extzv on targets without zext. */ rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3]))); rtx rshft = GEN_INT (32 - INTVAL (operands[2])); rtx tmp1 = gen_reg_rtx (SImode); rtx tmp2 = gen_reg_rtx (SImode); emit_insn (gen_rtx_SET (tmp1, operands[1])); emit_insn (gen_rtx_SET (tmp2, gen_rtx_ASHIFT (SImode, tmp1, lshft))); emit_insn (gen_rtx_SET (operands[0], gen_rtx_LSHIFTRT (SImode, tmp2, rshft))); DONE; } else { emit_insn (gen_cskyv2_extzv (operands[0], operands[1], operands[2], operands[3])); DONE; } }") (define_insn "cskyv2_extzv" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "csky_literal_K_operand" "K") (match_operand:SI 3 "csky_literal_K_operand" "K")))] "CSKY_ISA_FEATURE (2E3)" { operands[2] = GEN_INT (INTVAL (operands[3]) + INTVAL (operands[2]) - 1); return \"zext\t%0, %1, %2, %3\"; } ) (define_insn "*cskyv2_xtrb0" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extract:SI (match_operand:SI 1 "register_operand" "0,r") (const_int 8) (const_int 24))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "@ lsri\t%0, %0, 24 xtrb0\t%0, %1" ) (define_insn "*cskyv2_xtrb1" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 8) (const_int 16))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "xtrb1\t%0, %1" ) (define_insn "*cskyv2_xtrb2" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 8) (const_int 8))) (clobber (reg:CC CSKY_CC_REGNUM))] "CSKY_ISA_FEATURE (E2)" "xtrb2\t%0, %1" ) ;; ------------------------------------------------------------------------- ;; Zero extension instructions ;; ------------------------------------------------------------------------- (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))] "" "zexth\t%0, %1" ) (define_insn "*cskyv2_zextend_ldh" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:HI 1 "csky_simple_mem_operand" "m")))] "" "ld.h\t%0, %1" [(set_attr "length" "4") (set_attr "type" "load")] ) (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))] "" "zextb\t%0, %1" ) (define_insn "*cskyv2_zextend_ldb" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:QI 1 "csky_simple_mem_operand" "m")))] "" "ld.b\t%0, %1" [(set_attr "length" "4") (set_attr "type" "load")] ) (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "zextb\t%0, %1" ) (define_insn "*cskyv2_zextend_ldbhi" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "csky_simple_mem_operand" "m")))] "" "ld.b\t%0, %1" [(set_attr "length" "4") (set_attr "type" "load")] ) ;; ------------------------------------------------------------------------- ;; clzm2 instructions ;; ------------------------------------------------------------------------- (define_insn "clzsi2" [(set (match_operand:SI 0 "register_operand" "=r") (clz:SI (match_operand:SI 1 "register_operand" "r")))] "CSKY_ISA_FEATURE (E2)" "ff1 %0,%1" ) ;; ------------------------------------------------------------------------- ;; one_cmplm2 instructions ;; ------------------------------------------------------------------------- (define_expand "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "") (not:SI (match_operand:SI 1 "register_operand" "")))] "" "" ) (define_insn "cskyv2_one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=b,r") (not:SI (match_operand:SI 1 "register_operand" "0,r")))] "CSKY_ISA_FEATURE (E2)" "not %0, %1" [(set_attr "length" "2,4") (set_attr "type" "alu,alu")] ) (define_insn "ck801_one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") (not:SI (match_operand:SI 1 "register_operand" "0")))] "CSKY_ISA_FEATURE (E1)" "not %0, %1" [(set_attr "length" "2") (set_attr "type" "alu")] ) ;; ------------------------------------------------------------------------- ;; Sign extension instructions ;; ------------------------------------------------------------------------- ;; One test shows that the following code helps to ;; reduce one 'load' and two 'mov'. (define_expand "extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:SI 1 "register_operand" "r"))] "" "{ int low, high; if (TARGET_BIG_ENDIAN) low = 4, high = 0; else low = 0, high = 4; emit_insn (gen_rtx_SET (gen_rtx_SUBREG (SImode, operands[0], low), operands[1])); emit_insn (gen_rtx_SET (gen_rtx_SUBREG (SImode, operands[0], high), gen_rtx_ASHIFTRT (SImode, gen_rtx_SUBREG (SImode, operands[0], low), GEN_INT (31)))); DONE; }" ) (define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] "" "sexth %0, %1" ) (define_insn "*cskyv2_sextend_ldhs" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:HI 1 "csky_simple_mem_operand" "m")))] "CSKY_ISA_FEATURE (E2)" "ld.hs\t%0, %1" [(set_attr "length" "4") (set_attr "type" "load")] ) ;; qi -> si (define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] "" "sextb %0, %1" ) ;; qi -> hi (define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "sextb %0, %1" ) ;; ------------------------------------------------------------------------- ;; And instructions ;; ------------------------------------------------------------------------- (define_expand "andsi3" [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_any_imm_operand" "")))] "" "") (define_insn_and_split "cskyv2_andsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,r,&r") (and:SI (match_operand:SI 1 "register_operand" "%0,r,r,r") (match_operand:SI 2 "csky_arith_any_imm_operand" "b,r,O,i")))] "CSKY_ISA_FEATURE (E2)" "@ and\t%0, %1, %2 and\t%0, %1, %2 andi\t%0, %1, %2 #" "(CONST_INT_P (operands[2]) && (operands[2] == const0_rtx || !csky_arith_O_operand (operands[2], SImode)))" [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))] { if (csky_split_and (operands)) DONE; } [(set_attr "length" "2,4,4,8") (set_attr "type" "alu,alu,alu,alu")] ) (define_insn_and_split "ck801_andsi3" [(set (match_operand:SI 0 "register_operand" "=r,&r") (and:SI (match_operand:SI 1 "register_operand" "%0,r") (match_operand:SI 2 "csky_arith_any_imm_operand" "r,i")))] "CSKY_ISA_FEATURE (E1)" "@ and\t%0, %1, %2 #" "CONST_INT_P (operands[2])" [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))] { if (csky_split_and (operands)) DONE; } [(set_attr "length" "2,4") (set_attr "type" "alu,alu")] ) ;; Note that the operands for the andnsi3 patterns are reversed compared ;; to the actual machine insn: operand 1 is the inverted operand. (define_insn "cskyv2_andnsi3" [(use (and:SI (not:SI (match_operand:SI 1 "csky_arith_O_operand" "b,r,O")) (match_operand:SI 2 "register_operand" "0,r,r"))) (set (match_operand:SI 0 "register_operand" "=b,r,r") (and:SI (not:SI (match_dup 1)) (match_dup 2)))] "CSKY_ISA_FEATURE (E2)" "@ andn\t%0, %2, %1 andn\t%0, %2, %1 andni\t%0, %2, %1" [(set_attr "length" "2,4,4") (set_attr "type" "alu,alu,alu")] ) (define_insn "ck801_andnsi3" [(use (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "0"))) (set (match_operand:SI 0 "register_operand" "=r") (and:SI (not:SI (match_dup 1)) (match_dup 2)))] "CSKY_ISA_FEATURE (E1)" "andn\t%0, %2, %1" ) (define_expand "anddi3" [(set (match_operand:DI 0 "register_operand" "") (and:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "csky_arith_any_imm_operand" "")))] "" " { if (CONST_INT_P (operands[2])) { HOST_WIDE_INT ival = INTVAL (operands[2]); if (ival == (HOST_WIDE_INT) 0xffffffff) { emit_move_insn (gen_lowpart (SImode, operands[0]), gen_lowpart (SImode, operands[1])); emit_move_insn (gen_highpart (SImode, operands[0]), const0_rtx); DONE; } else if (ival == (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) -1 << 32)) { emit_move_insn (gen_lowpart (SImode, operands[0]), const0_rtx); emit_move_insn (gen_highpart (SImode, operands[0]), gen_highpart (SImode, operands[1])); DONE; } else FAIL; } }") (define_insn_and_split "*cskyv2_anddi3" [(set (match_operand:DI 0 "register_operand" "=&b,&r") (and:DI (match_operand:DI 1 "register_operand" "%0,r") (match_operand:DI 2 "register_operand" "b,r")))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cskyv2_andsi3 (l0, l1, l2)); emit_insn (gen_cskyv2_andsi3 (h0, h1, h2)); DONE; } [(set_attr "length" "4,8")] ) (define_insn_and_split "*ck801_anddi3" [(set (match_operand:DI 0 "register_operand" "=&r") (and:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E1)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_ck801_andsi3 (l0, l1, l2)); emit_insn (gen_ck801_andsi3 (h0, h1, h2)); DONE; } [(set_attr "length" "4")] ) ;; ------------------------------------------------------------------------- ;; Ior instructions ;; ------------------------------------------------------------------------- (define_expand "iorsi3" [(set (match_operand:SI 0 "register_operand" "") (ior:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_any_imm_operand" "")))] "" "") (define_insn_and_split "cskyv2_iorsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,r,&r") (ior:SI (match_operand:SI 1 "register_operand" "%0,r,r,r") (match_operand:SI 2 "csky_arith_any_imm_operand" "b, r,I,i")))] "CSKY_ISA_FEATURE (E2)" "@ or\t%0, %1, %2 or\t%0, %1, %2 ori\t%0, %1, %2 #" "(CONST_INT_P (operands[2]) && (operands[2] == const0_rtx || !csky_literal_I_operand (operands[2], SImode)))" [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))] { if (csky_split_ior (operands)) DONE; } [(set_attr "length" "2,4,4,8") (set_attr "type" "alu,alu,alu,alu")] ) (define_insn_and_split "ck801_iorsi3" [(set (match_operand:SI 0 "register_operand" "=r,&r") (ior:SI (match_operand:SI 1 "register_operand" "%0,r") (match_operand:SI 2 "csky_arith_any_imm_operand" "r,i")))] "CSKY_ISA_FEATURE (E1)" "@ or\t%0, %1, %2 #" "CONST_INT_P (operands[2])" [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))] { if (csky_split_ior (operands)) DONE; } [(set_attr "length" "2,4") (set_attr "type" "alu,alu")] ) (define_expand "iordi3" [(set (match_operand:DI 0 "register_operand" "") (ior:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] "" "" ) (define_insn_and_split "*cskyv2_iordi3" [(set (match_operand:DI 0 "register_operand" "=&b,&r") (ior:DI (match_operand:DI 1 "register_operand" "%0, r") (match_operand:DI 2 "register_operand" "b, r")))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cskyv2_iorsi3 (l0, l1, l2)); emit_insn (gen_cskyv2_iorsi3 (h0, h1, h2)); DONE; } [(set_attr "length" "4,8")] ) (define_insn_and_split "*ck801_iordi3" [(set (match_operand:DI 0 "register_operand" "=&r") (ior:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E1)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_ck801_iorsi3 (l0, l1, l2)); emit_insn (gen_ck801_iorsi3 (h0, h1, h2)); DONE; } [(set_attr "length" "4")] ) ;; ------------------------------------------------------------------------- ;; Xor instructions ;; ------------------------------------------------------------------------- (define_expand "xorsi3" [(set (match_operand:SI 0 "register_operand" "") (xor:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "csky_arith_any_imm_operand" "")))] "" "") (define_insn_and_split "cskyv2_xorsi3" [(set (match_operand:SI 0 "register_operand" "=b,r,r,&r") (xor:SI (match_operand:SI 1 "register_operand" "%0,r,r,r") (match_operand:SI 2 "csky_arith_any_imm_operand" "b, r,O,i")))] "CSKY_ISA_FEATURE (E2)" "@ xor\t%0, %1, %2 xor\t%0, %1, %2 xori\t%0, %1, %2 #" "(CONST_INT_P (operands[2]) && (operands[2] == const0_rtx || !csky_arith_O_operand (operands[2], SImode)))" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))] { if (csky_split_xor (operands)) DONE; } [(set_attr "length" "2,4,4,8") (set_attr "type" "alu,alu,alu,alu")] ) (define_insn_and_split "ck801_xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,&r") (xor:SI (match_operand:SI 1 "register_operand" "%0,r") (match_operand:SI 2 "csky_arith_any_imm_operand" "r,i")))] "CSKY_ISA_FEATURE (E1)" "@ xor\t%0, %1, %2 #" "CONST_INT_P (operands[2])" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))] { if (csky_split_xor (operands)) DONE; } [(set_attr "length" "2,4") (set_attr "type" "alu,alu")] ) (define_expand "xordi3" [(set (match_operand:DI 0 "register_operand" "") (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] "" "" ) (define_insn_and_split "*cskyv2_xordi3" [(set (match_operand:DI 0 "register_operand" "=&b,&r") (xor:DI (match_operand:DI 1 "register_operand" "%0, r") (match_operand:DI 2 "register_operand" "b, r")))] "CSKY_ISA_FEATURE (E2)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_cskyv2_xorsi3 (l0, l1, l2)); emit_insn (gen_cskyv2_xorsi3 (h0, h1, h2)); DONE; } [(set_attr "length" "4,8")] ) (define_insn_and_split "*ck801_xordi3" [(set (match_operand:DI 0 "register_operand" "=&r") (xor:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E1)" "#" "reload_completed" [(const_int 0)] { int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD; int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0; rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo); rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi); rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo); rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi); rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo); rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi); emit_insn (gen_ck801_xorsi3 (l0, l1, l2)); emit_insn (gen_ck801_xorsi3 (h0, h1, h2)); DONE; } [(set_attr "length" "4")] ) ;; ------------------------------------------------------------------------- ;; Div instructions ;; ------------------------------------------------------------------------- (define_insn "divsi3" [(set (match_operand:SI 0 "register_operand" "=r") (div:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")))] "TARGET_DIV" "divs\t%0, %1, %2" ) (define_insn "udivsi3" [(set (match_operand:SI 0 "register_operand" "=r") (udiv:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")))] "TARGET_DIV" "divu\t%0, %1, %2" ) ;; ----------------------------------------------------------------- ;; Multiple load and store insns ;; ----------------------------------------------------------------- (define_expand "load_multiple" [(match_par_dup 3 [(set (match_operand:SI 0 "" "") (match_operand:SI 1 "" "")) (use (match_operand:SI 2 "" ""))])] "TARGET_MULTIPLE_STLD" "{ int regno, count, i; rtx base,src; if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 2 || INTVAL (operands[2]) > CSKY_MAX_MULTIPLE_STLD || GET_CODE (operands[1]) != MEM || !REG_P (XEXP (operands[1], 0)) || XEXP (operands[1], 0) != stack_pointer_rtx || GET_CODE (operands[0]) != REG || (REGNO (XEXP (operands[1], 0)) > REGNO (operands[0]) && (REGNO (XEXP (operands[1], 0)) < REGNO (operands[0]) + INTVAL (operands[2])))) FAIL; count = INTVAL (operands[2]); regno = REGNO (operands[0]); operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); base = force_reg (SImode, XEXP (operands[1], 0)); src = replace_equiv_address (operands[1], base); for (i = 0; i < count; i++) XVECEXP (operands[3], 0, i) = gen_rtx_SET (gen_rtx_REG (SImode, regno + i), adjust_address_nv (src, SImode, i * 4)); }" ) (define_expand "store_multiple" [(match_par_dup 3 [(set (match_operand:SI 0 "") (match_operand:SI 1 "")) (use (match_operand:SI 2 ""))])] "TARGET_MULTIPLE_STLD" "{ int regno, count, i; rtx base, dest; /* Support only storing a constant number of registers to memory and only if at least two registers. */ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 2 || INTVAL (operands[2]) > CSKY_MAX_MULTIPLE_STLD || GET_CODE (operands[0]) != MEM || !REG_P (XEXP (operands[0], 0)) || XEXP (operands[0], 0) != stack_pointer_rtx || GET_CODE (operands[1]) != REG || (REGNO (XEXP (operands[0], 0)) >= REGNO (operands[1]) && (REGNO (XEXP (operands[0], 0)) < REGNO (operands[1]) + INTVAL (operands[2])))) FAIL; count = INTVAL (operands[2]); regno = REGNO (operands[1]); operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); base = force_reg (SImode, XEXP (operands[0], 0)); dest = replace_equiv_address (operands[0], base); for (i = 0; i < count; i++) XVECEXP (operands[3], 0, i) = gen_rtx_SET (adjust_address_nv (dest, SImode, i * 4), gen_rtx_REG (SImode, regno + i)); }" ) (define_insn "*csky_ldmsi12" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) (set (match_operand:SI 8 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 24)))) (set (match_operand:SI 9 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 28)))) (set (match_operand:SI 10 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 32)))) (set (match_operand:SI 11 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 36)))) (set (match_operand:SI 12 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 40)))) (set (match_operand:SI 13 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 44)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 12" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi11" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) (set (match_operand:SI 8 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 24)))) (set (match_operand:SI 9 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 28)))) (set (match_operand:SI 10 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 32)))) (set (match_operand:SI 11 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 36)))) (set (match_operand:SI 12 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 40)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 11" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi10" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) (set (match_operand:SI 8 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 24)))) (set (match_operand:SI 9 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 28)))) (set (match_operand:SI 10 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 32)))) (set (match_operand:SI 11 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 36)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 10" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi9" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) (set (match_operand:SI 8 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 24)))) (set (match_operand:SI 9 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 28)))) (set (match_operand:SI 10 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 32)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 9" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi8" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) (set (match_operand:SI 8 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 24)))) (set (match_operand:SI 9 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 28)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 8" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi7" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) (set (match_operand:SI 8 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 24)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 7" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi6" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 20)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 6" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi5" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) (set (match_operand:SI 6 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 16)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 5" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi4" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 12)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 4" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi3" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) (set (match_operand:SI 4 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 8)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 3" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_ldmsi2" [(match_parallel 0 "csky_load_multiple_operation" [(set (match_operand:SI 1 "register_operand" "=r") (mem:SI (match_operand:SI 2 "register_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 2) (const_int 4)))) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 2" { static char load_op[256] = {0}; int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[count]; sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi12" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) (match_operand:SI 8 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) (match_operand:SI 9 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) (match_operand:SI 10 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) (match_operand:SI 11 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) (match_operand:SI 12 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 44))) (match_operand:SI 13 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 12" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi11" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) (match_operand:SI 8 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) (match_operand:SI 9 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) (match_operand:SI 10 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) (match_operand:SI 11 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 40))) (match_operand:SI 12 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 11" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi10" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) (match_operand:SI 8 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) (match_operand:SI 9 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) (match_operand:SI 10 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 36))) (match_operand:SI 11 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 10" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi9" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) (match_operand:SI 8 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) (match_operand:SI 9 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 32))) (match_operand:SI 10 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 9" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi8" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) (match_operand:SI 8 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) (match_operand:SI 9 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 8" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi7" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) (match_operand:SI 8 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 7" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi6" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) (match_operand:SI 7 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 6" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi5" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) (match_operand:SI 6 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 5" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi4" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) (match_operand:SI 5 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 4" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi3" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) (match_operand:SI 4 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 3" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) (define_insn "*csky_stmsi2" [(match_parallel 0 "csky_store_multiple_operation" [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")) (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) (match_operand:SI 3 "register_operand" "r")) ])] "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 2" { static char load_op[256] = {0}; int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1; const char *reg_rz = reg_names[end]; sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz); return load_op; } ) ;; ------------------------------------------------------------------------ ;; Jump and linkage insns ;; ------------------------------------------------------------------------ (define_expand "tablejump" [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))])] "" " if (flag_pic) operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], pic_offset_table_rtx, NULL_RTX, 1, OPTAB_DIRECT); " ) (define_insn "*tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" "jmp %0" [(set_attr "type" "branch_jmp")] ) (define_expand "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "" ) (define_insn "*csky_jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "CSKY_ISA_FEATURE (E2)" "jbr %l0" [(set_attr "type" "branch")] ) ;; The length of bsr is not really 5; it's used to distinguish from br32. ;; Since the length attribute is treated specially it doesn't seem possible ;; to compute the far_jump attribute directly and use that. (define_insn "*ck801_ck802_jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "CSKY_ISA_FEATURE (E1) || CSKY_ISA_FEATURE (E2)" "*{ if (get_attr_length (insn) != 5) return \"jbr\\t%l0\"; else return \"bsr\\t%l0\\t//far jump\"; }" [(set_attr "type" "branch") (set (attr "far_jump") (if_then_else (eq_attr "length" "5") (const_string "yes") (const_string "no"))) (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -1024)) (le (minus (match_dup 0) (pc)) (const_int 1022))) (const_int 2) (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -65536)) (le (minus (match_dup 0) (pc)) (const_int 65534))) (const_int 4) (const_int 5))))] ) (define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "register_operand" "b,r"))] "" "@ jmp\t%0 jmp\t%0" [(set_attr "length" "2,4") (set_attr "type" "branch_jmp")] ) ;; ------------------------------------------------------------------------ ;; Conditional jump insns ;; ------------------------------------------------------------------------ (define_expand "cbranchsi4" [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" [(match_operand:SI 1 "csky_compare_operand") (match_operand:SI 2 "nonmemory_operand")]) (label_ref (match_operand 3 "")) (pc)))] "" "{ enum rtx_code code = GET_CODE (operands[0]); if (CSKY_ISA_FEATURE (2E3) && (code == LE || code == LT || code == GT || code == GE || code == EQ || code == NE) && operands[2] == const0_rtx) { /* These cases match the jbez, jbnez, etc insns below. TODO: Handling this in the expander is suboptimal since it fails to detect cases where the constant 0 would fall out from subsequent forward propagation or loop optimizers; maybe it would be better to have a splitter here, but when to split? */ } else { bool invert = csky_emit_compare (code, operands[1], operands[2]); if (invert) emit_jump_insn (gen_csky_jbf (operands[3])); else emit_jump_insn (gen_csky_jbt (operands[3])); DONE; } }" ) (define_insn "csky_jbt" [(set (pc) (if_then_else (ne (reg:CC CSKY_CC_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "CSKY_ISA_FEATURE (2E3)" "jbt\t%l0" [(set_attr "type" "cbranch")] ) (define_insn "csky_jbf" [(set (pc) (if_then_else (eq (reg:CC CSKY_CC_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "CSKY_ISA_FEATURE (2E3)" "jbf\t%l0" [(set_attr "type" "cbranch")] ) ;;; CK802 has 32-bit jbt/jbf instructions, but no insn other ;;; than bsr for far jumps. (define_insn "ck802_jbt" [(set (pc) (if_then_else (ne (reg:CC CSKY_CC_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "CSKY_ISA_FEATURE (E2)" { if (get_attr_length (insn) == 6) return \"jbf\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\"; else return \"jbt\\t%l0\"; } [(set_attr "type" "cbranch") (set (attr "far_jump") (if_then_else (eq_attr "length" "6") (const_string "yes") (const_string "no"))) (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -1024)) (le (minus (match_dup 0) (pc)) (const_int 1022))) (const_int 2) (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -65534)) (le (minus (match_dup 0) (pc)) (const_int 65534))) (const_int 4) (const_int 6))))] ) (define_insn "ck802_jbf" [(set (pc) (if_then_else (eq (reg:CC CSKY_CC_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "CSKY_ISA_FEATURE (E2)" { if (get_attr_length (insn) == 6) return \"jbt\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\"; else return \"jbf\\t%l0\"; } [(set_attr "type" "cbranch") (set (attr "far_jump") (if_then_else (eq_attr "length" "6") (const_string "yes") (const_string "no"))) (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -1024)) (le (minus (match_dup 0) (pc)) (const_int 1022))) (const_int 2) (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -65534)) (le (minus (match_dup 0) (pc)) (const_int 65534))) (const_int 4) (const_int 6))))] ) ;; The length of the bsr case is not really 7; it's used to distinguish ;; from br32. ;; Note that we have to adjust the backward range of the jbr case to ;; account for the jbf in front of it. (define_insn "ck801_jbt" [(set (pc) (if_then_else (ne (reg:CC CSKY_CC_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "CSKY_ISA_FEATURE (E1)" { if (get_attr_length (insn) == 6) return \"jbf\\t.LCB%=\;jbr\\t%l0\\n.LCB%=:\"; else if (get_attr_length (insn) == 7) return \"jbf\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\"; else return \"jbt\\t%l0\"; } [(set_attr "type" "cbranch") (set (attr "far_jump") (if_then_else (eq_attr "length" "7") (const_string "yes") (const_string "no"))) (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -1024)) (le (minus (match_dup 0) (pc)) (const_int 1022))) (const_int 2) (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -65534)) (le (minus (match_dup 0) (pc)) (const_int 65534))) (const_int 6) (const_int 7))))] ) (define_insn "ck801_jbf" [(set (pc) (if_then_else (eq (reg:CC CSKY_CC_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "CSKY_ISA_FEATURE (E1)" { if (get_attr_length (insn) == 6) return \"jbt\\t.LCB%=\;jbr\\t%l0\\n.LCB%=:\"; else if (get_attr_length (insn) == 7) return \"jbt\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\"; else return \"jbf\\t%l0\"; } [(set_attr "type" "cbranch") (set (attr "far_jump") (if_then_else (eq_attr "length" "7") (const_string "yes") (const_string "no"))) (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -1024)) (le (minus (match_dup 0) (pc)) (const_int 1022))) (const_int 2) (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -65534)) (le (minus (match_dup 0) (pc)) (const_int 65534))) (const_int 6) (const_int 7))))] ) (define_code_iterator zero_cond [lt le gt ge eq ne]) (define_code_attr inst [(lt "jblz") (le "jblsz") (gt "jbhz") (ge "jbhsz") (eq "jbez") (ne "jbnez")]) (define_insn "*" [(set (pc) (if_then_else (zero_cond (match_operand:SI 0 "register_operand" "r") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "CSKY_ISA_FEATURE (2E3)" "\t%0, %l1" [(set_attr "type" "cbranch")] ) ;; ------------------------------------------------------------------------ ;; return insns ;; ------------------------------------------------------------------------ (define_insn "simple_return" [(simple_return)] "reload_completed" "* return csky_output_return_instruction (); " ) (define_expand "eh_return" [(use (match_operand 0 "general_operand" ""))] "" "{ emit_insn (gen_csky_eh_return (operands[0])); DONE; }" ) ;; We can't expand this before we know where the link register is stored. (define_insn_and_split "csky_eh_return" [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_EH_RETURN) (clobber (match_scratch:SI 1 "=&r"))] "" "#" "reload_completed" [(const_int 0)] "{ csky_set_eh_return_address (operands[0], operands[1]); DONE; }" ) ;; ------------------------------------------------------------------------- ;; SImode signed integer comparisons ;; ------------------------------------------------------------------------- (define_insn "*cmpnesi_r" [(set (reg:CC CSKY_CC_REGNUM) (ne:CC (match_operand:SI 0 "register_operand" "b,r") (match_operand:SI 1 "register_operand" "b,r")))] "" "@ cmpne\t%0, %1 cmpne\t%0, %1" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) ;; cmpnei range is 0-31 for Smart mode. (define_insn "smart_cmpnesi_i" [(set (reg:CC CSKY_CC_REGNUM) (ne:CC (match_operand:SI 0 "register_operand" "a") (match_operand:SI 1 "csky_literal_K_operand" "K")))] "TARGET_MINI_REGISTERS" "cmpnei\t%0, %1" [(set_attr "type" "cmp")] ) ;; cmpnei range is 0 - 65536 for Fast mode. (define_insn "fast_cmpnesi_i" [(set (reg:CC CSKY_CC_REGNUM) (ne:CC (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "csky_literal_I_operand" "I")))] "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)" "cmpnei\t%0, %1" [(set_attr "type" "cmp")] ) (define_insn "*cmpgtsi" [(set (reg:CC CSKY_CC_REGNUM) (gt:CC (match_operand:SI 0 "register_operand" "b,r") (match_operand:SI 1 "register_operand" "b,r")))] "" "cmplt\t%1, %0" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) (define_insn "cmpltsi_r" [(set (reg:CC CSKY_CC_REGNUM) (lt:CC (match_operand:SI 0 "register_operand" "b,r") (match_operand:SI 1 "register_operand" "b,r")))] "" "cmplt\t%0, %1" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) ;; cmplti range is 1-32 for Smart mode. (define_insn "*smart_cmpltsi_i" [(set (reg:CC CSKY_CC_REGNUM) (lt:CC (match_operand:SI 0 "register_operand" "a") (match_operand:SI 1 "csky_literal_J_operand" "J")))] "TARGET_MINI_REGISTERS" "cmplti\t%0, %1" [(set_attr "length" "2") (set_attr "type" "cmp")] ) ;; cmplti range is 1-65536 for Fast mode. (define_insn "*fast_cmpltsi_i" [(set (reg:CC CSKY_CC_REGNUM) (lt:CC (match_operand:SI 0 "register_operand" "a,r") (match_operand:SI 1 "csky_literal_Uk_operand" "J,Uk")))] "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)" "cmplti\t%0, %1" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) ; Covers cmplti x,0. (define_insn "*cskyv2_cmpltsi_0" [(set (reg:CC CSKY_CC_REGNUM) (lt:CC (match_operand:SI 0 "register_operand" "a,r") (const_int 0)))] "CSKY_ISA_FEATURE (E2)" "btsti\t%0, 31" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) (define_insn "*ck801_cmpltsi_0" [(set (reg:CC CSKY_CC_REGNUM) (lt:CC (match_operand:SI 0 "register_operand" "a") (const_int 0)))] "CSKY_ISA_FEATURE (E1)" "btsti\t%0, 31" [(set_attr "type" "cmp")] ) ;; Decrement and test instructions. ;; In theory decne could be used in conjunction with jbt to implement ;; doloop_end, but that seems to encourage the loop optimizer to introduce ;; an additional induction variable and doesn't actually result in tighter ;; loop code for that reason. (define_insn "*cskyv2_declt" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "const_int_operand" "Uh"))) (set (reg:CC CSKY_CC_REGNUM) (lt:CC (plus:SI (match_dup 1) (match_dup 2)) (const_int 0)))] "CSKY_ISA_FEATURE (2E3)" "declt\t%0, %1, %M2" ) (define_insn "*cskyv2_decgt" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "const_int_operand" "Uh"))) (set (reg:CC CSKY_CC_REGNUM) (gt:CC (plus:SI (match_dup 1) (match_dup 2)) (const_int 0)))] "CSKY_ISA_FEATURE (2E3)" "decgt\t%0, %1, %M2" ) (define_insn "*cskyv2_decne" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "const_int_operand" "Uh"))) (set (reg:CC CSKY_CC_REGNUM) (ne:CC (plus:SI (match_dup 1) (match_dup 2)) (const_int 0)))] "CSKY_ISA_FEATURE (2E3)" "decne\t%0, %1, %M2" ) ;; ------------------------------------------------------------------------- ;; SImode unsigned integer comparisons ;; ------------------------------------------------------------------------- (define_insn "cmpgeusi_r" [(set (reg:CC CSKY_CC_REGNUM) (geu:CC (match_operand:SI 0 "register_operand" "b,r") (match_operand:SI 1 "register_operand" "b,r")))] "" "cmphs\t%0, %1" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) (define_insn "*smart_cmpgeusi_i" [(set (reg:CC CSKY_CC_REGNUM) (geu:CC (match_operand:SI 0 "register_operand" "a") (match_operand:SI 1 "csky_literal_J_operand" "J")))] "TARGET_MINI_REGISTERS" "cmphsi\t%0, %1" [(set_attr "length" "2") (set_attr "type" "cmp")] ) (define_insn "*fast_cmpgeusi_i" [(set (reg:CC CSKY_CC_REGNUM) (geu:CC (match_operand:SI 0 "register_operand" "a,r") (match_operand:SI 1 "csky_literal_Uk_operand" "J,Uk")))] "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)" "cmphsi\t%0, %1" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) (define_insn "*cmpleusi" [(set (reg:CC CSKY_CC_REGNUM) (leu:CC (match_operand:SI 0 "register_operand" "b,r") (match_operand:SI 1 "register_operand" "b,r")))] "" "cmphs\t%1, %0" [(set_attr "length" "2,4") (set_attr "type" "cmp")] ) ;; ------------------------------------------------------------------------- ;; Function call insns ;; ------------------------------------------------------------------------- (define_expand "call" [(parallel [(call (match_operand:SI 0 "" "") (match_operand 1 "" "")) (clobber (reg:SI CSKY_LR_REGNUM))])] "" " { rtx pic_ref; rtx addr_ref = XEXP (operands[0], 0); if (flag_pic && (CONSTANT_P (addr_ref) || csky_symbol_mentioned_p (addr_ref) || csky_label_mentioned_p (addr_ref))) { pic_ref = csky_legitimize_pic_address (addr_ref, 0, false); operands[0] = gen_rtx_MEM (GET_MODE (pic_ref), pic_ref); } if (GET_CODE (operands[0]) == MEM && ! register_operand (XEXP (operands[0], 0), SImode) && ! csky_symbolic_address_p (XEXP (operands[0], 0)) && ! (flag_pic && csky_unspec_operand (XEXP (operands[0], 0), SImode))) operands[0] = gen_rtx_MEM (GET_MODE (operands[0]), force_reg (Pmode, XEXP (operands[0], 0))); }" ) (define_insn "*call_internal" [(call (mem:SI (match_operand:SI 0 "csky_call_address_operand" "b,r,S")) (match_operand 1 "" "")) (clobber (reg:SI CSKY_LR_REGNUM))] "" "@ jsr\t%0 jsr\t%0 jbsr\t%0" [(set_attr "length" "2,4,4") (set_attr "type" "call_jsr,call_jsr,call")] ) (define_insn "*call_internal_pic" [(call (mem:SI (match_operand:SI 0 "csky_unspec_operand" "X")) (match_operand 1 "" "")) (clobber (reg:SI CSKY_LR_REGNUM))] "flag_pic" "* return csky_output_call (operands, 0);" [(set_attr "length" "4")] ) (define_expand "call_value" [(parallel [(set (match_operand 0 "register_operand" "") (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))])] "" "{ rtx pic_ref; rtx addr_ref = XEXP (operands[1], 0); if (flag_pic && (CONSTANT_P (addr_ref) || csky_symbol_mentioned_p (addr_ref) || csky_label_mentioned_p (addr_ref))) { pic_ref = csky_legitimize_pic_address (addr_ref, 0, false); operands[1] = gen_rtx_MEM (GET_MODE (pic_ref), pic_ref); } if (GET_CODE (operands[1]) == MEM && ! register_operand (XEXP (operands[1], 0), SImode) && ! csky_symbolic_address_p (XEXP (operands[1], 0)) && ! (flag_pic && csky_unspec_operand (XEXP (operands[1], 0), SImode))) operands[1] = gen_rtx_MEM (GET_MODE (operands[1]), force_reg (Pmode, XEXP (operands[1], 0))); }") (define_insn "*call_value_internal" [(set (match_operand 0 "register_operand" "=r,r,r") (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S")) (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "" "@ jsr\t%1 jsr\t%1 jbsr\t%1" [(set_attr "length" "2,4,4") (set_attr "type" "call_jsr,call_jsr,call")] ) (define_insn "*call_value_internal_pic" [(set (match_operand 0 "register_operand" "=r") (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X")) (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "flag_pic" "* return csky_output_call (operands, 1);" ) (define_insn "*call_value_struct" [(set (match_parallel 0 "" [(expr_list (match_operand 3 "register_operand" "") (match_operand 4 "immediate_operand" "")) (expr_list (match_operand 5 "register_operand" "") (match_operand 6 "immediate_operand" ""))]) (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b,r,S")) (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "" "@ jsr\t%1 jsr\t%1 jbsr\t%1" [(set_attr "length" "2,4,4") (set_attr "type" "call_jsr,call_jsr,call")] ) (define_insn "*call_value_struct_pic" [(set (match_parallel 0 "" [(expr_list (match_operand 3 "register_operand" "") (match_operand 4 "immediate_operand" "")) (expr_list (match_operand 5 "register_operand" "") (match_operand 6 "immediate_operand" ""))]) (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X")) (match_operand 2 "" ""))) (clobber (reg:SI CSKY_LR_REGNUM))] "flag_pic" "* return csky_output_call (operands, 1);" ) ;; ------------------------------------------------------------- ;; prologue & epilogue ;; ------------------------------------------------------------- (define_expand "prologue" [(clobber (const_int 0))] "" " { csky_expand_prologue (); DONE; }" ) (define_expand "epilogue" [(clobber (const_int 0))] "" " { csky_expand_epilogue (); DONE; }" ) /* TODO: pushpop */ ;; Push multiple registers to the stack. Registers are in parallel (use ...) ;; expressions. For simplicity, the first register is also in the unspec ;; part. (define_insn "*push_multi" [(match_parallel 2 "registers_push" [(set (match_operand:BLK 0 "push_memory_operand" "") (unspec:BLK [(match_operand:SI 1 "register_operand" "")] UNSPEC_PUSHPOP_MULT))])] "" { int num_saves = XVECLEN (operands[2], 0); int i; char pattern[100]; strcpy (pattern, \"push\\t%1\"); for (i = 1; i < num_saves; i++) { strcat (pattern, \", \"); strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); } output_asm_insn (pattern, operands); return \"\"; } [(set (attr "length") (symbol_ref "csky_compute_pushpop_length (operands)"))] ) ;; Pop (as used in epilogue RTL) ;; (define_insn "*pop_multi" [(match_parallel 2 "registers_pop" [(return) (set (match_operand:SI 1 "register_operand" "") (unspec:SI [(match_operand:SI 0 "pop_memory_operand" "")] UNSPEC_PUSHPOP_MULT))])] "" { int num_saves = XVECLEN (operands[2], 0); int i; char pattern[100]; strcpy (pattern, \"pop\\t%1\"); for (i = 2; i < num_saves; i++) { strcat (pattern, \", \"); strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); } output_asm_insn (pattern, operands); return \"\"; } [(set (attr "length") (symbol_ref "csky_compute_pushpop_length (operands)"))] ) ;; ------------------------------------------------------------------------- ;; PIC related insns ;; ------------------------------------------------------------------------- (define_insn "prologue_get_pc" [(set (reg:SI 28) (match_operand:SI 0 "" "X"))] "(GET_CODE (operands[0]) == UNSPEC) && (XINT (operands[0], 1) == UNSPEC_PIC_SYMBOL_GOTPC_GRS)" { operands[0] = XVECEXP (operands[0], 0, 0); output_asm_insn (\"grs\tgb, %0\", operands); default_internal_label (asm_out_file, \"L\", CODE_LABEL_NUMBER (XEXP (operands[0], 0))); return \"\"; } ) (define_insn "*pic_got_pc" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GOTPC))] "flag_pic" "lrw\t%0, %1@GOTPC" ) (define_insn "*pic_symbol_gotoff" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GOTOFF))] "flag_pic" "lrw\t%0, %1@GOTOFF" ) (define_insn "*pic_symbol_got" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GOT))] "flag_pic" "lrw\t%0, %1@GOT" ) (define_insn "*pic_symbol_plt" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_PLT))] "flag_pic" "lrw\t%0, %1@PLT" ) (define_insn "*pic_symbol_grs" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GRS))] "flag_pic" "grs\t%0, %1" ) (define_expand "builtin_setjmp_receiver" [(label_ref (match_operand 0 "" ""))] "flag_pic" "{ rtx l1 = gen_label_rtx(); rtx grs_label = gen_rtx_LABEL_REF (SImode, l1); rtx reg_gb = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM); rtx reg_temp = gen_rtx_REG (SImode, 12); rtx tmp0_unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, grs_label), UNSPEC_PIC_SYMBOL_GOTPC_GRS); rtx tmp1_unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, grs_label), UNSPEC_PIC_SYMBOL_GOTPC); emit_insn (gen_prologue_get_pc (tmp0_unspec)); emit_move_insn (reg_temp, tmp1_unspec); emit_insn (gen_addsi3 (reg_gb, reg_gb, reg_temp)); emit_use (reg_gb); DONE; }" ) ;; ------------------------------------------------------------------------- ;; TLS related insns ;; ------------------------------------------------------------------------- ;; UNSPEC_TLS can take either 2 or 3 operands. Operand 0 is the symbol_ref, ;; operand 1 is a CONST_INT identifying the TLS model, and the optional ;; operand 3 is an UNSPEC_TLS_LABEL. ;; The 3-operand case is for TLS_GD32, TLS_LDM32, and TLS_IE32. ;; The 2-operand case is for TLS_LE32 and TLS_LDO32. ;; Move PC-relative TLS label to reg. This is used for the TLS_GD32 ;; and TLS_GD32 models (when setting up a call to tls_get_addr) and ;; also TLS_IE32. (define_insn "*tls_pcrel_label" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "const_int_operand" "")] UNSPEC_TLS_LABEL))] "TARGET_TLS" "grs\t%0, .LTLS%1" [(set_attr "length" "4")] ) ;; This pattern is used to load the TLS base for the same models as above. ;; The embedded UNSPEC_TLS_LABEL only identifies the label to emit and ;; doesn't generate a reference to it; that's handled by the *tls_pcrel_label ;; pattern above. The label offset needs to be added to the result stored ;; in operand 0 by this insn. (define_insn "*tls_get_symbol_1" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand 1 "" "") (match_operand 2 "" "") (unspec:SI [(match_operand 3 "" "")] UNSPEC_TLS_LABEL)] UNSPEC_TLS))] "TARGET_TLS" { default_internal_label (asm_out_file, \"LTLS\", INTVAL (operands[3])); switch (INTVAL (operands[2])) { case TLS_GD32: return \"lrw\t%0, %1@TLSGD32\"; case TLS_LDM32: return \"lrw\t%0, %1@TLSLDM32\"; case TLS_IE32: return \"lrw\t%0, %1@GOTTPOFF\"; default: return \"\"; } } ) ;; This pattern matches the two-operand form of UNSPEC_TLS. (define_insn "*tls_get_symbol_2" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand 1 "" "") (match_operand 2 "" "")] UNSPEC_TLS))] "TARGET_TLS" { switch (INTVAL (operands[2])) { case TLS_LE32: return \"lrw\t%0, %1@TPOFF\"; case TLS_LDO32: return \"lrw\t%0, %1@TLSLDO32\"; default: return \"\"; } } ) ;; ------------------------------------------------------------- ;; Misc insns ;; ------------------------------------------------------------- (define_insn "nop" [(const_int 0)] "" "nop" [(set_attr "length" "2")] ) (define_insn "trap" [(trap_if (const_int 1) (const_int 0))] "" "bkpt" [(set (attr "length") (const_int 2)) (set_attr "type" "alu")] ) ;; ------------------------------------------------------------- ;; Special patterns for dealing with the constant pool ;; ------------------------------------------------------------- (define_insn "align_4" [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] "" { assemble_align(32); return \"\"; } [(set_attr "length" "0")] ) (define_insn "csky_constpool_label" [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_LABEL)] "" { char tmp_label[15]; ASM_GENERATE_INTERNAL_LABEL (tmp_label, \"LCP\", INTVAL (operands[0])); assemble_label (asm_out_file, tmp_label); return \"\"; } [(set_attr "length" "0")] ) (define_insn "consttable_4" [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] "" { if (CONST_DOUBLE_P (operands[0])) assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]), SFmode, BITS_PER_WORD); else { assemble_integer (operands[0], 4, BITS_PER_WORD, 1); mark_symbol_refs_as_used (operands[0]); } return \"\"; } [(set_attr "length" "4")] ) (define_insn "consttable_8" [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] "" { if (CONST_DOUBLE_P (operands[0])) assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]), DFmode, BITS_PER_WORD); else assemble_integer (operands[0], 8, BITS_PER_WORD, 1); return \"\"; } [(set_attr "length" "8")] ) ;;FIXME record the deferred symbol_ref information with use insn (define_insn "*cskyv2_use_symbol_ref" [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_SYMBOL_REF)] "" "" [(set_attr "length" "0")] ) ;; ------------------------------------------------------------ ;; switch case optimize ;; ------------------------------------------------------------ (define_expand "casesi" [(match_operand:SI 0 "register_operand" "") ; index to jump on (match_operand:SI 1 "const_int_operand" "") ; lower bound (match_operand:SI 2 "const_int_operand" "") ; total range (max - min) (match_operand:SI 3 "" "") ; table label (match_operand:SI 4 "" "")] ; Out of range label (default:) "TARGET_CASESI" " { enum insn_code code; if (operands[1] != const0_rtx) { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_subsi3 (reg, operands[0], GEN_INT (INTVAL (operands[1])))); operands[0] = reg; } code = CODE_FOR_csky_casesi_internal; if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode)) operands[2] = force_reg (SImode,operands[2]); emit_jump_insn (GEN_FCN ((int) code) (operands[0],operands[2], operands[3],operands[4])); DONE; }" ) (define_expand "csky_casesi_internal" [(match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "csky_literal_Uk_operand" "") (match_operand 2 "" "") (match_operand 3 "" "")] "" { rtx reg0; rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]); emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1], operands[3])); reg0 = gen_rtx_REG (SImode, 0); emit_move_insn (reg0, operands[0]); emit_jump_insn (gen_csky_casesi_dispatch (operands[2])); DONE; } ) (define_insn "csky_casesi_dispatch" [(parallel [(set (pc) (unspec [(reg:SI 0) (label_ref (match_operand 0 "" ""))] UNSPEC_CSKY_CASESI)) (clobber (reg:SI CSKY_LR_REGNUM))])] "" "*return csky_output_casesi (operands);" [(set_attr "length" "4")] ) ;; ------------------------------------------------------------------------ ;; index insns ;; ------------------------------------------------------------------------ (define_insn "*cskyv2_indexsi_t" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 4)) (match_operand:SI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E2)" "ixw\t%0, %2, %1" ) (define_insn "*cskyv2_indexhi_t" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 2)) (match_operand:SI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (E2)" "ixh\t%0, %2, %1" ) (define_insn "*cskyv2_indexdi_t" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 8)) (match_operand:SI 2 "register_operand" "r")))] "CSKY_ISA_FEATURE (2E3)" "ixd\t%0, %2, %1" ) ;; ------------------------------------------------------------------------ ;; swap insns ;; ------------------------------------------------------------------------ (define_insn "bswapsi2" [(set (match_operand:SI 0 "register_operand" "=r") (bswap:SI (match_operand:SI 1 "register_operand" "r")))] "CSKY_ISA_FEATURE (E2)" "revb\t%0, %1" )