📄 thumb.md
字号:
operands[1] = force_reg (QImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24))); emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24))); DONE; }")(define_insn "*zero_extendqisi2_insn" [(set (match_operand:SI 0 "register_operand" "=l") (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] "" "ldrb\\t%0, %1")(define_expand "extendhisi2" [(parallel [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" ""))) (clobber (match_scratch:SI 2 ""))])] "" " if (GET_CODE (operands[1]) != MEM) { rtx temp = gen_reg_rtx (SImode); operands[1] = force_reg (HImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16))); emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16))); DONE; }")(define_insn "*extendhisi2_insn" [(set (match_operand:SI 0 "register_operand" "=l") (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) (clobber (match_scratch:SI 2 "=&l"))] "" "*{ rtx ops[4]; /* This code used to try to use 'V', and fix the address only if it was offsettable, but this fails for e.g. REG+48 because 48 is outside the range of QImode offsets, and offsettable_address_p does a QImode address check. */ if (GET_CODE (XEXP (operands[1], 0)) == PLUS) { ops[1] = XEXP (XEXP (operands[1], 0), 0); ops[2] = XEXP (XEXP (operands[1], 0), 1); } else { ops[1] = XEXP (operands[1], 0); ops[2] = const0_rtx; } if (GET_CODE (ops[2]) == REG) return \"ldrsh\\t%0, %1\"; ops[0] = operands[0]; ops[3] = operands[2]; output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); return \"\";}"[(set_attr "length" "4")])(define_expand "extendqisi2" [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " if (GET_CODE (operands[1]) != MEM) { rtx temp = gen_reg_rtx (SImode); operands[1] = force_reg (QImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24))); emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24))); DONE; }")(define_insn "*extendqisi2_insn" [(set (match_operand:SI 0 "register_operand" "=l,l") (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] "" "*{ rtx ops[3]; if (which_alternative == 0) return \"ldrsb\\t%0, %1\"; ops[0] = operands[0]; if (GET_CODE (XEXP (operands[1], 0)) == PLUS) { ops[1] = XEXP (XEXP (operands[1], 0), 0); ops[2] = XEXP (XEXP (operands[1], 0), 1); if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG) output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); else if (GET_CODE (ops[1]) == REG) { if (REGNO (ops[1]) == REGNO (operands[0])) output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops); else output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); } else { if (REGNO (ops[2]) == REGNO (operands[0])) output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops); else output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); } } else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0))) { output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops); } else { ops[1] = XEXP (operands[1], 0); ops[2] = const0_rtx; output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); } return \"\";}"[(set_attr "length" "2,6")]);; We don't really have extzv, but defining this using shifts helps;; to reduce register pressure later on.(define_expand "extzv" [(set (match_dup 4) (ashift:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" ""))) (set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_dup 4) (match_operand:SI 3 "const_int_operand" "")))] "" "{ HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]); HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]); operands[3] = GEN_INT (rshift); if (lshift == 0) { emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3])); DONE; } operands[2] = GEN_INT (lshift); operands[4] = gen_reg_rtx (SImode);}");; Block-move insns(define_expand "movstrqi" [(match_operand:BLK 0 "general_operand" "") (match_operand:BLK 1 "general_operand" "") (match_operand:SI 2 "" "") (match_operand:SI 3 "const_int_operand" "")] "" " if (INTVAL (operands[3]) != 4 || GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 48) FAIL; thumb_expand_movstrqi (operands); DONE;")(define_insn "movmem12b" [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l")) (mem:SI (match_operand:SI 1 "register_operand" "+&l"))) (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (mem:SI (plus:SI (match_dup 1) (const_int 4)))) (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (mem:SI (plus:SI (match_dup 1) (const_int 8)))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12))) (clobber (match_scratch:SI 2 "=&l")) (clobber (match_scratch:SI 3 "=&l")) (clobber (match_scratch:SI 4 "=&l"))] "" "* return output_move_mem_multiple (3, operands);"[(set_attr "length" "4")])(define_insn "movmem8b" [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l")) (mem:SI (match_operand:SI 1 "register_operand" "+&l"))) (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (mem:SI (plus:SI (match_dup 1) (const_int 4)))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8))) (clobber (match_scratch:SI 2 "=&l")) (clobber (match_scratch:SI 3 "=&l"))] "" "* return output_move_mem_multiple (2, operands);"[(set_attr "length" "4")]);; Arithmetic insns(define_insn "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")))] "" "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"[(set_attr "conds" "changed") (set_attr "length" "8")]);; 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 "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")))] "" "* static char *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 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return \"sub\\t%0, %1, #%n2\"; return asms[which_alternative];"); reloading and elimination of the frame pointer can sometimes cause this; optimization to be missed.(define_peephole [(set (match_operand:SI 0 "register_operand" "=l") (match_operand:SI 1 "const_int_operand" "M")) (set (match_dup 0) (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))] "REGNO (operands[2]) == STACK_POINTER_REGNUM && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 && (INTVAL (operands[1]) & 3) == 0" "add\\t%0, %2, %1")(define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=l") (minus:DI (match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "register_operand" "l")))] "" "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"[(set_attr "conds" "changed") (set_attr "length" "8")])(define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=l") (minus:SI (match_operand:SI 1 "register_operand" "l") (match_operand:SI 2 "register_operand" "l")))] "" "sub\\t%0, %1, %2");; We must ensure that one input matches the output, and that the other input;; does not match the output. Using 0 satisfies the first, and using &;; satisfies the second. Unfortunately, this fails when operands 1 and 2;; are the same, because reload will make operand 0 match operand 1 without;; realizing that this conflicts with operand 2. We fix this by adding another;; alternative to match this case, and then `reload' it ourselves. This;; alternative must come first.(define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l") (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0") (match_operand:SI 2 "register_operand" "l,l,l")))] "" "*{ if (which_alternative < 2) return \"mov\\t%0, %1\;mul\\t%0, %0, %2\"; else return \"mul\\t%0, %0, %2\";}" [(set_attr "length" "4,4,2")])(define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=l") (neg:SI (match_operand:SI 1 "register_operand" "l")))] "" "neg\\t%0, %1");; Logical insns(define_expand "andsi3" [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] "" " if (GET_CODE (operands[2]) != CONST_INT) operands[2] = force_reg (SImode, operands[2]); else { int i; if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256) { operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2]))); emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1])); DONE; } for (i = 9; i <= 31; i++) if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2])) { emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i), const0_rtx)); DONE; } else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2])) { rtx shift = GEN_INT (i); rtx reg = gen_reg_rtx (SImode); emit_insn (gen_lshrsi3 (reg, operands[1], shift)); emit_insn (gen_ashlsi3 (operands[0], reg, shift)); DONE; } operands[2] = force_reg (SImode, operands[2]); }")(define_insn "*andsi3_insn" [(set (match_operand:SI 0 "register_operand" "=l") (and:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "l")))] "" "and\\t%0, %0, %2")(define_insn "bicsi3" [(set (match_operand:SI 0 "register_operand" "=l") (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) (match_operand:SI 2 "register_operand" "0")))] "" "bic\\t%0, %0, %1")(define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=l") (ior:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "l")))] "" "orr\\t%0, %0, %2")(define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=l") (xor:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "l")))] "" "eor\\t%0, %0, %2")(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=l") (not:SI (match_operand:SI 1 "register_operand" "l")))] "" "mvn\\t%0, %1");; Shift and rotation insns(define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=l,l") (ashift:SI (match_operand:SI 1 "register_operand" "l,0") (match_operand:SI 2 "nonmemory_operand" "N,l")))] "" "@ lsl\\t%0, %1, %2 lsl\\t%0, %0, %2")(define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=l,l") (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") (match_operand:SI 2 "nonmemory_operand" "N,l")))] "" "@ asr\\t%0, %1, %2 asr\\t%0, %0, %2")(define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=l,l")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -