📄 arm.md
字号:
(match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "const_int_operand" "n") (match_operand:SI 3 "const_int_operand" "n")) (const_int 0)))] "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32" "* operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) << INTVAL (operands[3])); output_asm_insn (\"ands\\t%0, %1, %2\", operands); return \"movne\\t%0, #1\";"[(set_attr "conds" "clob") (set_attr "length" "8")]);;; ??? This pattern is bogus. If operand3 has bits outside the range;;; represented by the bitfield, then this will produce incorrect results.;;; Somewhere, the value needs to be truncated. On targets like the m68k,;;; which have a real bitfield insert instruction, the truncation happens;;; in the bitfield insert instruction itself. Since arm does not have a;;; bitfield insert instruction, we would have to emit code here to truncate;;; the value before we insert. This loses some of the advantage of having;;; this insv pattern, so this pattern needs to be reevalutated.(define_expand "insv" [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")) (match_operand:SI 3 "nonmemory_operand" ""))] "" "{ int start_bit = INTVAL (operands[2]); int width = INTVAL (operands[1]); HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1; rtx target, subtarget; target = operands[0]; /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical subreg as the final target. */ if (GET_CODE (target) == SUBREG) { subtarget = gen_reg_rtx (SImode); if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target))) < GET_MODE_SIZE (SImode)) target = SUBREG_REG (target); } else subtarget = target; if (GET_CODE (operands[3]) == CONST_INT) { /* Since we are inserting a known constant, we may be able to reduce the number of bits that we have to clear so that the mask becomes simple. */ /* ??? This code does not check to see if the new mask is actually simpler. It may not be. */ rtx op1 = gen_reg_rtx (SImode); /* ??? Truncate operand3 to fit in the bitfield. See comment before start of this pattern. */ HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]); HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit); emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2))); emit_insn (gen_iorsi3 (subtarget, op1, GEN_INT (op3_value << start_bit))); } else if (start_bit == 0 && ! (const_ok_for_arm (mask) || const_ok_for_arm (~mask))) { /* A Trick, since we are setting the bottom bits in the word, we can shift operand[3] up, operand[0] down, OR them together and rotate the result back again. This takes 3 insns, and the third might be mergable into another op. */ /* The shift up copes with the possibility that operand[3] is wider than the bitfield. */ rtx op0 = gen_reg_rtx (SImode); rtx op1 = gen_reg_rtx (SImode); emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0], operands[1]), op0)); emit_insn (gen_rotlsi3 (subtarget, op1, operands[1])); } else if ((width + start_bit == 32) && ! (const_ok_for_arm (mask) || const_ok_for_arm (~mask))) { /* Similar trick, but slightly less efficient. */ rtx op0 = gen_reg_rtx (SImode); rtx op1 = gen_reg_rtx (SImode); emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); emit_insn (gen_iorsi3 (subtarget, gen_rtx_LSHIFTRT (SImode, op1, operands[1]), op0)); } else { rtx op0 = GEN_INT (mask); rtx op1 = gen_reg_rtx (SImode); rtx op2 = gen_reg_rtx (SImode); if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask))) { rtx tmp = gen_reg_rtx (SImode); emit_insn (gen_movsi (tmp, op0)); op0 = tmp; } /* Mask out any bits in operand[3] that are not needed. */ emit_insn (gen_andsi3 (op1, operands[3], op0)); if (GET_CODE (op0) == CONST_INT && (const_ok_for_arm (mask << start_bit) || const_ok_for_arm (~ (mask << start_bit)))) { op0 = GEN_INT (~(mask << start_bit)); emit_insn (gen_andsi3 (op2, operands[0], op0)); } else { if (GET_CODE (op0) == CONST_INT) { rtx tmp = gen_reg_rtx (SImode); emit_insn (gen_movsi (tmp, op0)); op0 = tmp; } if (start_bit != 0) op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]); emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); } if (start_bit != 0) op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]); emit_insn (gen_iorsi3 (subtarget, op1, op2)); } if (subtarget != target) { /* If TARGET is still a SUBREG, then it must be wider than a word, so we must be careful only to set the subword we were asked to. */ if (GET_CODE (target) == SUBREG) emit_move_insn (target, subtarget); else emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); } DONE;}");; constants for op 2 will never be given to these patterns.(define_insn "*anddi_notdi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0")) (match_operand:DI 1 "s_register_operand" "0,r")))] "" "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"[(set_attr "length" "8")]) (define_insn "*anddi_notzesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (and:DI (not:DI (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) (match_operand:DI 1 "s_register_operand" "0,?r")))] "" "@ bic%?\\t%Q0, %Q1, %2 bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"[(set_attr "length" "4,8")]) (define_insn "*anddi_notsesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (and:DI (not:DI (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) (match_operand:DI 1 "s_register_operand" "?r,0")))] "" "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"[(set_attr "length" "8")]) (define_insn "andsi_notsi_si" [(set (match_operand:SI 0 "s_register_operand" "=r") (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) (match_operand:SI 1 "s_register_operand" "r")))] "" "bic%?\\t%0, %1, %2")(define_insn "andsi_not_shiftsi_si" [(set (match_operand:SI 0 "s_register_operand" "=r") (and:SI (not:SI (match_operator:SI 4 "shift_operator" [(match_operand:SI 2 "s_register_operand" "r") (match_operand:SI 3 "arm_rhs_operand" "rM")])) (match_operand:SI 1 "s_register_operand" "r")))] "" "bic%?\\t%0, %1, %2%S4")(define_insn "*andsi_notsi_si_compare0" [(set (reg:CC_NOOV 24) (compare:CC_NOOV (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) (match_operand:SI 1 "s_register_operand" "r")) (const_int 0))) (set (match_operand:SI 0 "s_register_operand" "=r") (and:SI (not:SI (match_dup 2)) (match_dup 1)))] "" "bic%?s\\t%0, %1, %2"[(set_attr "conds" "set")])(define_insn "*andsi_notsi_si_compare0_scratch" [(set (reg:CC_NOOV 24) (compare:CC_NOOV (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) (match_operand:SI 1 "s_register_operand" "r")) (const_int 0))) (clobber (match_scratch:SI 0 "=r"))] "" "bic%?s\\t%0, %1, %2"[(set_attr "conds" "set")])(define_insn "iordi3" [(set (match_operand:DI 0 "s_register_operand" "=&r") (ior:DI (match_operand:DI 1 "s_register_operand" "%0") (match_operand:DI 2 "s_register_operand" "r")))] "" "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"[(set_attr "length" "8")])(define_insn "*iordi_zesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (ior:DI (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:DI 1 "s_register_operand" "0,?r")))] "" "@ orr%?\\t%Q0, %Q1, %2 orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"[(set_attr "length" "4,8")])(define_insn "*iordi_sesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (ior:DI (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:DI 1 "s_register_operand" "?r,0")))] "" "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"[(set_attr "length" "8")])(define_expand "iorsi3" [(set (match_operand:SI 0 "s_register_operand" "") (ior:SI (match_operand:SI 1 "s_register_operand" "") (match_operand:SI 2 "reg_or_int_operand" "")))] "" " if (GET_CODE (operands[2]) == CONST_INT) { arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], operands[1], (reload_in_progress || reload_completed ? 0 : preserve_subexpressions_p ())); DONE; }")(define_insn "*iorsi3_insn" [(set (match_operand:SI 0 "s_register_operand" "=r,r") (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] "" "@ orr%?\\t%0, %1, %2 #"[(set_attr "length" "4,16")])(define_split [(set (match_operand:SI 0 "s_register_operand" "") (ior:SI (match_operand:SI 1 "s_register_operand" "") (match_operand:SI 2 "const_int_operand" "")))] "! const_ok_for_arm (INTVAL (operands[2]))" [(clobber (const_int 0))] " arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], operands[1], 0); DONE;") (define_insn "*iorsi3_compare0" [(set (reg:CC_NOOV 24) (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") (match_operand:SI 2 "arm_rhs_operand" "rI")) (const_int 0))) (set (match_operand:SI 0 "s_register_operand" "=r") (ior:SI (match_dup 1) (match_dup 2)))] "" "orr%?s\\t%0, %1, %2"[(set_attr "conds" "set")])(define_insn "*iorsi3_compare0_scratch" [(set (reg:CC_NOOV 24) (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") (match_operand:SI 2 "arm_rhs_operand" "rI")) (const_int 0))) (clobber (match_scratch:SI 0 "=r"))] "" "orr%?s\\t%0, %1, %2"[(set_attr "conds" "set")])(define_insn "xordi3" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0") (match_operand:DI 2 "s_register_operand" "r,0")))] "" "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"[(set_attr "length" "8")])(define_insn "*xordi_zesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (xor:DI (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:DI 1 "s_register_operand" "0,?r")))] "" "@ eor%?\\t%Q0, %Q1, %2 eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"[(set_attr "length" "4,8")])(define_insn "*xordi_sesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (xor:DI (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:DI 1 "s_register_operand" "?r,0")))] "" "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"[(set_attr "length" "8")])(define_insn "xorsi3" [(set (match_operand:SI 0 "s_register_operand" "=r") (xor:SI (match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "arm_rhs_operand" "rI")))] "" "eor%?\\t%0, %1, %2")(define_insn "*xorsi3_compare0" [(set (reg:CC_NOOV 24) (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "arm_rhs_operand" "rI")) (const_int 0))) (set (match_operand:SI 0 "s_register_operand" "=r") (xor:SI (match_dup 1) (match_dup 2)))] "" "eor%?s\\t%0, %1, %2"[(set_attr "conds" "set")])(define_insn "*xorsi3_compare0_scratch" [(set (reg:CC_NOOV 24) (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") (match_operand:SI 1 "arm_rhs_operand" "rI")) (const_int 0)))] "" "teq%?\\t%0, %1"[(set_attr "conds" "set")]);; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), ;; (NOT D) we can sometimes merge the final NOT into one of the following;; insns(define_split [(set (match_operand:SI 0 "s_register_operand" "=r") (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r")) (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))) (match_operand:SI 3 "arm_rhs_operand" "rI"))) (clobber (match_operand:SI 4 "s_register_operand" "=r"))] "" [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) (not:SI (match_dup 3)))) (set (match_dup 0) (not:SI (match_dup 4)))] "")(define_insn "*andsi_iorsi3_notsi" [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] "" "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"[(set_attr "length" "8")])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -