📄 i386.md
字号:
(define_insn "cmpsf_cc_1" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" [(match_operand:SF 0 "nonimmediate_operand" "f,fm") (match_operand:SF 1 "nonimmediate_operand" "fm,f")])) (clobber (match_scratch:HI 3 "=a,a"))] "TARGET_80387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "* return output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" [(match_operand:SF 0 "register_operand" "f") (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" "* return output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" [(float:SF (match_operand:SI 0 "nonimmediate_operand" "rm")) (match_operand:SF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" "* return output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (compare:CCFPEQ (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" "* return output_float_compare (insn, operands);")(define_expand "cmpxf" [(set (cc0) (compare (match_operand:XF 0 "register_operand" "") (match_operand:XF 1 "nonimmediate_operand" "")))] "TARGET_80387" "{ i386_compare_gen = gen_cmpxf_cc; i386_compare_gen_eq = gen_cmpxf_ccfpeq; i386_compare_op0 = operands[0]; i386_compare_op1 = operands[1]; DONE;}")(define_expand "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "nonimmediate_operand" "")))] "TARGET_80387" "{ i386_compare_gen = gen_cmpdf_cc; i386_compare_gen_eq = gen_cmpdf_ccfpeq; i386_compare_op0 = operands[0]; i386_compare_op1 = operands[1]; DONE;}")(define_expand "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "nonimmediate_operand" "")))] "TARGET_80387" "{ i386_compare_gen = gen_cmpsf_cc; i386_compare_gen_eq = gen_cmpsf_ccfpeq; i386_compare_op0 = operands[0]; i386_compare_op1 = operands[1]; DONE;}")(define_expand "cmpxf_cc" [(parallel [(set (cc0) (compare (match_operand:XF 0 "register_operand" "") (match_operand:XF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" "")(define_expand "cmpxf_ccfpeq" [(parallel [(set (cc0) (compare:CCFPEQ (match_operand:XF 0 "register_operand" "") (match_operand:XF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" "{ if (! register_operand (operands[1], XFmode)) operands[1] = copy_to_mode_reg (XFmode, operands[1]);}")(define_expand "cmpdf_cc" [(parallel [(set (cc0) (compare (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" "")(define_expand "cmpdf_ccfpeq" [(parallel [(set (cc0) (compare:CCFPEQ (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" "{ if (! register_operand (operands[1], DFmode)) operands[1] = copy_to_mode_reg (DFmode, operands[1]);}")(define_expand "cmpsf_cc" [(parallel [(set (cc0) (compare (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" "")(define_expand "cmpsf_ccfpeq" [(parallel [(set (cc0) (compare:CCFPEQ (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" "{ if (! register_operand (operands[1], SFmode)) operands[1] = copy_to_mode_reg (SFmode, operands[1]);}");; logical compare(define_insn "" [(set (cc0) (and:SI (match_operand:SI 0 "general_operand" "%ro") (match_operand:SI 1 "general_operand" "ri")))] "" "*{ /* For small integers, we may actually use testb. */ if (GET_CODE (operands[1]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) { /* We may set the sign bit spuriously. */ if ((INTVAL (operands[1]) & ~0xff) == 0) { cc_status.flags |= CC_NOT_NEGATIVE; return AS2 (test%B0,%1,%b0); } if ((INTVAL (operands[1]) & ~0xff00) == 0) { cc_status.flags |= CC_NOT_NEGATIVE; operands[1] = GEN_INT (INTVAL (operands[1]) >> 8); if (QI_REG_P (operands[0])) return AS2 (test%B0,%1,%h0); else { operands[0] = adj_offsettable_operand (operands[0], 1); return AS2 (test%B0,%1,%b0); } } if (GET_CODE (operands[0]) == MEM && (INTVAL (operands[1]) & ~0xff0000) == 0) { cc_status.flags |= CC_NOT_NEGATIVE; operands[1] = GEN_INT (INTVAL (operands[1]) >> 16); operands[0] = adj_offsettable_operand (operands[0], 2); return AS2 (test%B0,%1,%b0); } if (GET_CODE (operands[0]) == MEM && (INTVAL (operands[1]) & ~0xff000000) == 0) { operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff); operands[0] = adj_offsettable_operand (operands[0], 3); return AS2 (test%B0,%1,%b0); } } if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%L0,%1,%0); return AS2 (test%L1,%0,%1);}")(define_insn "" [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "%ro") (match_operand:HI 1 "general_operand" "ri")))] "" "*{ if (GET_CODE (operands[1]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) { if ((INTVAL (operands[1]) & 0xff00) == 0) { /* ??? This might not be necessary. */ if (INTVAL (operands[1]) & 0xffff0000) operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); /* We may set the sign bit spuriously. */ cc_status.flags |= CC_NOT_NEGATIVE; return AS2 (test%B0,%1,%b0); } if ((INTVAL (operands[1]) & 0xff) == 0) { operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff); if (QI_REG_P (operands[0])) return AS2 (test%B0,%1,%h0); else { operands[0] = adj_offsettable_operand (operands[0], 1); return AS2 (test%B0,%1,%b0); } } } if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%W0,%1,%0); return AS2 (test%W1,%0,%1);}")(define_insn "" [(set (cc0) (and:QI (match_operand:QI 0 "general_operand" "%qm") (match_operand:QI 1 "general_operand" "qi")))] "" "*{ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%B0,%1,%0); return AS2 (test%B1,%0,%1);}");; move instructions.;; There is one for each machine mode,;; and each is preceded by a corresponding push-insn pattern;; (since pushes are not general_operands on the 386).(define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "general_operand" "g"))] "TARGET_386" "push%L0 %1");; On a 486, it is faster to move MEM to a REG and then push, rather than;; push MEM directly.(define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "nonmemory_operand" "ri"))] "!TARGET_386 && TARGET_MOVE" "push%L0 %1")(define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "general_operand" "ri"))] "!TARGET_386 && !TARGET_MOVE" "push%L0 %1");; General case of fullword move.;; If generating PIC code and operands[1] is a symbolic CONST, emit a;; move to get the address of the symbolic object from the GOT.(define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" "{ extern int flag_pic; if (flag_pic && SYMBOLIC_CONST (operands[1])) emit_pic_move (operands, SImode); /* Don't generate memory->memory moves, go through a register */ else if (TARGET_MOVE && (reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) { operands[1] = force_reg (SImode, operands[1]); }}");; On i486, incl reg is faster than movl $1,reg.(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,r") (match_operand:SI 1 "general_operand" "ri,m"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "*{ rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) return AS2 (xor%L0,%0,%0); if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) /* Make sure the insn that stored the 0 is still present. */ && ! INSN_DELETED_P (XEXP (link, 0)) && GET_CODE (XEXP (link, 0)) != NOTE /* Make sure cross jumping didn't happen here. */ && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) /* Fastest way to change a 0 to a 1. */ return AS1 (inc%L0,%0); if (flag_pic && SYMBOLIC_CONST (operands[1])) return AS2 (lea%L0,%a1,%0); return AS2 (mov%L0,%1,%0);}")(define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "general_operand" "g"))] "TARGET_386" "push%W0 %1")(define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "nonmemory_operand" "ri"))] "!TARGET_386 && TARGET_MOVE" "push%W0 %1")(define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "general_operand" "ri"))] "!TARGET_386 && !TARGET_MOVE" "push%W0 %1");; On i486, an incl and movl are both faster than incw and movw.(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "{ /* Don't generate memory->memory moves, go through a register */ if (TARGET_MOVE && (reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) { operands[1] = force_reg (HImode, operands[1]); }}")(define_insn "" [(set (match_operand:HI 0 "general_operand" "=g,r") (match_operand:HI 1 "general_operand" "ri,m"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "*{ rtx link; if (REG_P (operands[0]) && operands[1] == const0_rtx) return AS2 (xor%L0,%k0,%k0); if (REG_P (operands[0]) && operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) /* Make sure the insn that stored the 0 is still present. */ && ! INSN_DELETED_P (XEXP (link, 0)) && GET_CODE (XEXP (link, 0)) != NOTE /* Make sure cross jumping didn't happen here. */ && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) /* Fastest way to change a 0 to a 1. */ return AS1 (inc%L0,%k0); if (REG_P (operands[0])) { if (REG_P (operands[1])) return AS2 (mov%L0,%k1,%k0); else if (CONSTANT_P (operands[1])) return AS2 (mov%L0,%1,%k0); } return AS2 (mov%W0,%1,%0);}")(define_expand "movstricthi" [(set (strict_low_part (match_operand:HI 0 "general_operand" "")) (match_operand:HI 1 "general_operand" ""))] "" "{ /* Don't generate memory->memory moves, go through a register */ if (TARGET_MOVE && (reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) { operands[1] = force_reg (HImode, operands[1]); }}")(define_insn "" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r")) (match_operand:HI 1 "general_operand" "ri,m"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "*{ rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) return AS2 (xor%W0,%0,%0); if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) /* Make sure the insn that stored the 0 is still present. */ && ! INSN_DELETED_P (XEXP (link, 0)) && GET_CODE (XEXP (link, 0)) != NOTE /* Make sure cross jumping didn't happen here. */ && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) /* Fastest way to change a 0 to a 1. */ return AS1 (inc%W0,%0); return AS2 (mov%W0,%1,%0);}");; emit_push_insn when it calls move_by_pieces;; requires an insn to "push a byte".;; But actually we use pushw, which has the effect of rounding;; the amount pushed up to a halfword.(define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "immediate_operand" "n"))] "" "* return AS1 (push%W0,%1);")(define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "nonimmediate_operand" "q"))] "!TARGET_MOVE" "*{ operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); return AS1 (push%W0,%1);}")(define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "register_operand" "q"))] "TARGET_MOVE" "*{ operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); return AS1 (push%W0,%1);}");; On i486, incb reg is faster than movb $1,reg.;; ??? Do a recognizer for zero_extract that looks just like this, but reads;; or writes %ah, %bh, %ch, %dh.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -