sparc.md
来自「GCC编译器源代码」· Markdown 代码 · 共 2,069 行 · 第 1/5 页
MD
2,069 行
"! TARGET_LIVE_G0" "{ if (! TARGET_V9) { rtx tem; /* We can do geu easily, so if both operands are registers, swap them and do a GEU. */ if ((GET_CODE (sparc_compare_op0) == REG || GET_CODE (sparc_compare_op0) == SUBREG) && (GET_CODE (sparc_compare_op1) == REG || GET_CODE (sparc_compare_op1) == SUBREG)) { tem = sparc_compare_op0; sparc_compare_op0 = sparc_compare_op1; sparc_compare_op1 = tem; emit_insn (gen_sgeu (operands[0])); DONE; } } else { if (gen_v9_scc (LEU, operands)) DONE; } operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);}");; Now the DEFINE_INSNs for the scc cases.;; The SEQ and SNE patterns are special because they can be done;; without any branching and do not involve a COMPARE.(define_insn "*snesi_zero" [(set (match_operand:SI 0 "register_operand" "=r") (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;addx %%g0,0,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*neg_snesi_zero" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;subx %%g0,0,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*snesi_zero_extend" [(set (match_operand:DI 0 "register_operand" "=r") (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))) (clobber (reg:CC 100))] "TARGET_ARCH64" "subcc %%g0,%1,%%g0\;addx %%g0,0,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*snedi_zero" [(set (match_operand:DI 0 "register_operand" "=&r") (ne:DI (match_operand:DI 1 "register_operand" "r") (const_int 0)))] "TARGET_ARCH64" "mov 0,%0\;movrnz %1,1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*neg_snedi_zero" [(set (match_operand:DI 0 "register_operand" "=&r") (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r") (const_int 0))))] "TARGET_ARCH64" "mov 0,%0\;movrnz %1,-1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*snedi_zero_trunc" [(set (match_operand:SI 0 "register_operand" "=&r") (ne:DI (match_operand:DI 1 "register_operand" "r") (const_int 0)))] "TARGET_ARCH64" "mov 0,%0\;movrnz %1,1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*seqsi_zero" [(set (match_operand:SI 0 "register_operand" "=r") (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*neg_seqsi_zero" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*seqsi_zero_extend" [(set (match_operand:DI 0 "register_operand" "=r") (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0))) (clobber (reg:CC 100))] "TARGET_ARCH64" "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*seqdi_zero" [(set (match_operand:DI 0 "register_operand" "=&r") (eq:DI (match_operand:DI 1 "register_operand" "r") (const_int 0)))] "TARGET_ARCH64" "mov 0,%0\;movrz %1,1,%0" [(set_attr "type" "unary") (set_attr "length" "2")])(define_insn "*neg_seqdi_zero" [(set (match_operand:DI 0 "register_operand" "=&r") (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r") (const_int 0))))] "TARGET_ARCH64" "mov 0,%0\;movrz %1,-1,%0" [(set_attr "type" "unary") (set_attr "length" "2")]) (define_insn "*seqdi_zero_trunc" [(set (match_operand:SI 0 "register_operand" "=&r") (eq:DI (match_operand:DI 1 "register_operand" "r") (const_int 0)))] "TARGET_ARCH64" "mov 0,%0\;movrz %1,1,%0" [(set_attr "type" "unary") (set_attr "length" "2")]);; We can also do (x + (i == 0)) and related, so put them in.;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode;; versions for v9.(define_insn "*x_plus_i_ne_0" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)) (match_operand:SI 2 "register_operand" "r"))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;addx %2,0,%0" [(set_attr "length" "2")])(define_insn "*x_minus_i_ne_0" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 2 "register_operand" "r") (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;subx %2,0,%0" [(set_attr "length" "2")])(define_insn "*x_plus_i_eq_0" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)) (match_operand:SI 2 "register_operand" "r"))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;subx %2,-1,%0" [(set_attr "length" "2")])(define_insn "*x_minus_i_eq_0" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 2 "register_operand" "r") (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) (clobber (reg:CC 100))] "! TARGET_LIVE_G0" "subcc %%g0,%1,%%g0\;addx %2,-1,%0" [(set_attr "length" "2")]);; We can also do GEU and LTU directly, but these operate after a compare.;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode;; versions for v9.(define_insn "*sltu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (ltu:SI (reg:CC 100) (const_int 0)))] "! TARGET_LIVE_G0" "addx %%g0,0,%0" [(set_attr "type" "misc")])(define_insn "*neg_sltu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))] "! TARGET_LIVE_G0" "subx %%g0,0,%0" [(set_attr "type" "misc")]);; ??? Combine should canonicalize these next two to the same pattern.(define_insn "*neg_sltu_minus_x" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0))) (match_operand:SI 1 "arith_operand" "rI")))] "! TARGET_LIVE_G0" "subx %%g0,%1,%0" [(set_attr "type" "unary")])(define_insn "*neg_sltu_plus_x" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) (match_operand:SI 1 "arith_operand" "rI"))))] "! TARGET_LIVE_G0" "subx %%g0,%1,%0" [(set_attr "type" "unary")])(define_insn "*sgeu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (geu:SI (reg:CC 100) (const_int 0)))] "! TARGET_LIVE_G0" "subx %%g0,-1,%0" [(set_attr "type" "misc")])(define_insn "*neg_sgeu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (geu:SI (reg:CC 100) (const_int 0))))] "! TARGET_LIVE_G0" "addx %%g0,-1,%0" [(set_attr "type" "misc")]);; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode;; versions for v9.(define_insn "*sltu_plus_x" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) (match_operand:SI 1 "arith_operand" "rI")))] "! TARGET_LIVE_G0" "addx %%g0,%1,%0" [(set_attr "type" "unary")])(define_insn "*sltu_plus_x_plus_y" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) (plus:SI (match_operand:SI 1 "arith_operand" "%r") (match_operand:SI 2 "arith_operand" "rI"))))] "" "addx %1,%2,%0")(define_insn "*x_minus_sltu" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "r") (ltu:SI (reg:CC 100) (const_int 0))))] "" "subx %1,0,%0" [(set_attr "type" "unary")]);; ??? Combine should canonicalize these next two to the same pattern.(define_insn "*x_minus_y_minus_sltu" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")) (ltu:SI (reg:CC 100) (const_int 0))))] "" "subx %1,%2,%0")(define_insn "*x_minus_sltu_plus_y" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "r") (plus:SI (ltu:SI (reg:CC 100) (const_int 0)) (match_operand:SI 2 "arith_operand" "rI"))))] "" "subx %1,%2,%0")(define_insn "*sgeu_plus_x" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (geu:SI (reg:CC 100) (const_int 0)) (match_operand:SI 1 "register_operand" "r")))] "" "subx %1,-1,%0" [(set_attr "type" "unary")])(define_insn "*x_minus_sgeu" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "r") (geu:SI (reg:CC 100) (const_int 0))))] "" "addx %1,-1,%0" [(set_attr "type" "unary")]);; Now we have the generic scc insns.;; !v9: These will be done using a jump.;; v9: Use conditional moves which are defined elsewhere.;; We have to exclude the cases above, since we will not want combine to;; turn something that does not require a jump into something that does.(define_insn "*scc_si" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 2 "noov_compare_op" [(match_operand 1 "icc_or_fcc_reg_operand" "") (const_int 0)]))] "" "* return output_scc_insn (operands, insn); " [(set_attr "type" "multi") (set_attr "length" "3")])(define_insn "*scc_di" [(set (match_operand:DI 0 "register_operand" "=r") (match_operator:DI 2 "noov_compare_op" [(match_operand 1 "icc_or_fcc_reg_operand" "") (const_int 0)]))] "TARGET_ARCH64" "* return output_scc_insn (operands, insn); " [(set_attr "type" "multi") (set_attr "length" "3")]);; These control RTL generation for conditional jump insns;; The quad-word fp compare library routines all return nonzero to indicate;; true, which is different from the equivalent libgcc routines, so we must;; handle them specially here.(define_expand "beq" [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx && GET_CODE (sparc_compare_op0) == REG && GET_MODE (sparc_compare_op0) == DImode) { emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]); DONE; } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); emit_jump_insn (gen_bne (operands[0])); DONE; } operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);}")(define_expand "bne" [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx && GET_CODE (sparc_compare_op0) == REG && GET_MODE (sparc_compare_op0) == DImode) { emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]); DONE; } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); emit_jump_insn (gen_bne (operands[0])); DONE; } operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);}")(define_expand "bgt" [(set (pc) (if_then_else (gt (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx && GET_CODE (sparc_compare_op0) == REG && GET_MODE (sparc_compare_op0) == DImode) { emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]); DONE; } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); emit_jump_insn (gen_bne (operands[0])); DONE; } operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);}")(define_expand "bgtu" [(set (pc) (if_then_else (gtu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?