📄 arm.md
字号:
(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)(define_function_unit "core" 1 0 (and (eq_attr "core_cycles" "multi") (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32);;---------------------------------------------------------------------------;; Insn patterns;;;; Addition insns.;; Note: For DImode insns, there is normally no reason why operands should;; not be in the same register, what we don't want is for something being;; written to partially overlap something that is an input.(define_expand "adddi3" [(parallel [(set (match_operand:DI 0 "s_register_operand" "") (plus:DI (match_operand:DI 1 "s_register_operand" "") (match_operand:DI 2 "s_register_operand" ""))) (clobber (reg:CC CC_REGNUM))])] "TARGET_EITHER" " if (TARGET_THUMB) { if (GET_CODE (operands[1]) != REG) operands[1] = force_reg (SImode, operands[1]); if (GET_CODE (operands[2]) != REG) operands[2] = force_reg (SImode, operands[2]); } ")(define_insn "*thumb_adddi3" [(set (match_operand:DI 0 "register_operand" "=l") (plus:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "l"))) (clobber (reg:CC CC_REGNUM)) ] "TARGET_THUMB" "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2" [(set_attr "length" "4")])(define_insn_and_split "*arm_adddi3" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") (match_operand:DI 2 "s_register_operand" "r, 0"))) (clobber (reg:CC CC_REGNUM))] "TARGET_ARM" "#" "TARGET_ARM && reload_completed" [(parallel [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1))) (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) (plus:SI (match_dup 4) (match_dup 5))))] " { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); operands[4] = gen_highpart (SImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); operands[5] = gen_highpart (SImode, operands[2]); operands[2] = gen_lowpart (SImode, operands[2]); }" [(set_attr "conds" "clob") (set_attr "length" "8")])(define_insn_and_split "*adddi_sesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (plus:DI (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:DI 1 "s_register_operand" "r,0"))) (clobber (reg:CC CC_REGNUM))] "TARGET_ARM" "#" "TARGET_ARM && reload_completed" [(parallel [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1))) (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) (plus:SI (ashiftrt:SI (match_dup 2) (const_int 31)) (match_dup 4))))] " { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); operands[4] = gen_highpart (SImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_lowpart (SImode, operands[2]); }" [(set_attr "conds" "clob") (set_attr "length" "8")])(define_insn_and_split "*adddi_zesidi_di" [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (plus:DI (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")) (match_operand:DI 1 "s_register_operand" "r,0"))) (clobber (reg:CC CC_REGNUM))] "TARGET_ARM" "#" "TARGET_ARM && reload_completed" [(parallel [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1))) (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) (plus:SI (match_dup 4) (const_int 0))))] " { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); operands[4] = gen_highpart (SImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_lowpart (SImode, operands[2]); }" [(set_attr "conds" "clob") (set_attr "length" "8")])(define_expand "addsi3" [(set (match_operand:SI 0 "s_register_operand" "") (plus:SI (match_operand:SI 1 "s_register_operand" "") (match_operand:SI 2 "reg_or_int_operand" "")))] "TARGET_EITHER" " if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT) { arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], operands[1], (no_new_pseudos ? 0 : preserve_subexpressions_p ())); DONE; } "); If there is a scratch available, this will be faster than synthesising the; addition.(define_peephole2 [(match_scratch:SI 3 "r") (set (match_operand:SI 0 "s_register_operand" "") (plus:SI (match_operand:SI 1 "s_register_operand" "") (match_operand:SI 2 "const_int_operand" "")))] "TARGET_ARM && !(const_ok_for_arm (INTVAL (operands[2])) || const_ok_for_arm (-INTVAL (operands[2]))) && const_ok_for_arm (~INTVAL (operands[2]))" [(set (match_dup 3) (match_dup 2)) (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))] "")(define_insn_and_split "*arm_addsi3" [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r") (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] "TARGET_ARM" "@ add%?\\t%0, %1, %2 sub%?\\t%0, %1, #%n2 #" "TARGET_ARM && GET_CODE (operands[2]) == CONST_INT && !(const_ok_for_arm (INTVAL (operands[2])) || const_ok_for_arm (-INTVAL (operands[2])))" [(clobber (const_int 0))] " arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], operands[1], 0); DONE; " [(set_attr "length" "4,4,16") (set_attr "predicable" "yes")]);; Register group 'k' is a single register group containing only the stack;; register. Trying to reload it will always fail catastrophically,;; so never allow those alternatives to match if reloading is needed.(define_insn "*thumb_addsi3" [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k") (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k") (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))] "TARGET_THUMB" "* static const char * const asms[] = { \"add\\t%0, %0, %2\", \"sub\\t%0, %0, #%n2\", \"add\\t%0, %1, %2\", \"add\\t%0, %0, %2\", \"add\\t%0, %0, %2\", \"add\\t%0, %1, %2\", \"add\\t%0, %1, %2\" }; if ((which_alternative == 2 || which_alternative == 6) && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return \"sub\\t%0, %1, #%n2\"; return asms[which_alternative]; " [(set_attr "length" "2")]);; Reloading and elimination of the frame pointer can;; sometimes cause this optimization to be missed.(define_peephole2 [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "const_int_operand" "")) (set (match_dup 0) (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))] "TARGET_THUMB && REGNO (operands[2]) == STACK_POINTER_REGNUM && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 && (INTVAL (operands[1]) & 3) == 0" [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))] "")(define_insn "*addsi3_compare0" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV (plus:SI (match_operand:SI 1 "s_register_operand" "r, r") (match_operand:SI 2 "arm_add_operand" "rI,L")) (const_int 0))) (set (match_operand:SI 0 "s_register_operand" "=r,r") (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_ARM" "@ add%?s\\t%0, %1, %2 sub%?s\\t%0, %1, #%n2" [(set_attr "conds" "set")])(define_insn "*addsi3_compare0_scratch" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV (plus:SI (match_operand:SI 0 "s_register_operand" "r, r") (match_operand:SI 1 "arm_add_operand" "rI,L")) (const_int 0)))] "TARGET_ARM" "@ cmn%?\\t%0, %1 cmp%?\\t%0, #%n1" [(set_attr "conds" "set")]);; These patterns are the same ones as the two regular addsi3_compare0;; patterns, except we write them slightly different - the combiner;; tends to generate them this way.(define_insn "*addsi3_compare0_for_combiner" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:SI 1 "s_register_operand" "r,r") (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L")))) (set (match_operand:SI 0 "s_register_operand" "=r,r") (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_ARM" "@ add%?s\\t%0, %1, %2 sub%?s\\t%0, %1, #%n2" [(set_attr "conds" "set")])(define_insn "*addsi3_compare0_scratch_for_combiner" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))] "TARGET_ARM" "@ cmn%?\\t%0, %1 cmp%?\\t%0, #%n1" [(set_attr "conds" "set")]);; The next four insns work because they compare the result with one of;; the operands, and we know that the use of the condition code is;; either GEU or LTU, so we can use the carry flag from the addition;; instead of doing the compare a second time.(define_insn "*addsi3_compare_op1" [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operand:SI 2 "arm_add_operand" "rI,L")) (match_dup 1))) (set (match_operand:SI 0 "s_register_operand" "=r,r") (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_ARM" "@ add%?s\\t%0, %1, %2 sub%?s\\t%0, %1, #%n2" [(set_attr "conds" "set")])(define_insn "*addsi3_compare_op2" [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operand:SI 2 "arm_add_operand" "rI,L")) (match_dup 2))) (set (match_operand:SI 0 "s_register_operand" "=r,r") (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_ARM" "@ add%?s\\t%0, %1, %2 sub%?s\\t%0, %1, #%n2" [(set_attr "conds" "set")])(define_insn "*compare_addsi2_op0" [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") (match_operand:SI 1 "arm_add_operand" "rI,L")) (match_dup 0)))] "TARGET_ARM" "@ cmn%?\\t%0, %1 cmp%?\\t%0, #%n1" [(set_attr "conds" "set")])(define_insn "*compare_addsi2_op1" [(set (reg:CC_C CC_REGNUM) (compare:CC_C (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") (match_operand:SI 1 "arm_add_operand" "rI,L")) (match_dup 1)))] "TARGET_ARM" "@ cmn%?\\t%0, %1 cmp%?\\t%0, #%n1" [(set_attr "conds" "set")])(define_insn "*addsi3_carryin" [(set (match_operand:SI 0 "s_register_operand" "=r") (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) (plus:SI (match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "arm_rhs_operand" "rI"))))] "TARGET_ARM" "adc%?\\t%0, %1, %2" [(set_attr "conds" "use")])(define_insn "*addsi3_carryin_shift" [(set (match_operand:SI 0 "s_register_operand" "") (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) (plus:SI (match_operator:SI 2 "shift_operator" [(match_operand:SI 3 "s_register_operand" "") (match_operand:SI 4 "reg_or_int_operand" "")]) (match_operand:SI 1 "s_register_operand" ""))))] "TARGET_ARM" "adc%?\\t%0, %1, %3%S2" [(set_attr "conds" "use")])(define_insn "*addsi3_carryin_alt1" [(set (match_operand:SI 0 "s_register_operand" "=r") (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "arm_rhs_operand" "rI")) (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] "TARGET_ARM" "adc%?\\t%0, %1, %2" [(set_attr "conds" "use")])(define_insn "*addsi3_carryin_alt2" [(set (match_operand:SI 0 "s_register_operand" "=r") (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) (match_operand:SI 1 "s_register_operand" "r")) (match_operand:SI 2 "arm_rhs_operand" "rI")))] "TARGET_ARM" "adc%?\\t%0, %1, %2"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -