📄 i386.md
字号:
(match_operand:SI 2 "general_operand" "0")))] "GET_CODE (operands[2]) == CONST_INT && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" "and%L0 %1,%0")*/;;- Bit set (inclusive or) instructions;; ??? What if we only change one byte of an offsettable memory reference?(define_insn "iorsi3" [(set (match_operand:SI 0 "general_operand" "=rm,r") (ior:SI (match_operand:SI 1 "general_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & ~0xff) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) == 0xff) return AS2 (mov%B0,%2,%b0); return AS2 (or%B0,%2,%b0); } if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) { CC_STATUS_INIT; operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); if (INTVAL (operands[2]) == 0xff) return AS2 (mov%B0,%2,%h0); return AS2 (or%B0,%2,%h0); } } return AS2 (or%L0,%2,%0);}")(define_insn "iorhi3" [(set (match_operand:HI 0 "general_operand" "=rm,r") (ior:HI (match_operand:HI 1 "general_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { /* Can we ignore the upper byte? */ if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & 0xff00) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) & 0xffff0000) operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) return AS2 (mov%B0,%2,%b0); return AS2 (or%B0,%2,%b0); } /* Can we ignore the lower byte? */ /* ??? what about offsettable memory references? */ if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0) { CC_STATUS_INIT; operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); if (INTVAL (operands[2]) == 0xff) return AS2 (mov%B0,%2,%h0); return AS2 (or%B0,%2,%h0); } } return AS2 (or%W0,%2,%0);}")(define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=qm,q") (ior:QI (match_operand:QI 1 "general_operand" "%0,0") (match_operand:QI 2 "general_operand" "qn,qmn")))] "" "* return AS2 (or%B0,%2,%0);");;- xor instructions;; ??? What if we only change one byte of an offsettable memory reference?(define_insn "xorsi3" [(set (match_operand:SI 0 "general_operand" "=rm,r") (xor:SI (match_operand:SI 1 "general_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & ~0xff) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) == 0xff) return AS1 (not%B0,%b0); return AS2 (xor%B0,%2,%b0); } if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) { CC_STATUS_INIT; operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); if (INTVAL (operands[2]) == 0xff) return AS1 (not%B0,%h0); return AS2 (xor%B0,%2,%h0); } } return AS2 (xor%L0,%2,%0);}")(define_insn "xorhi3" [(set (match_operand:HI 0 "general_operand" "=rm,r") (xor:HI (match_operand:HI 1 "general_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "*{ if (GET_CODE (operands[2]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { /* Can we ignore the upper byte? */ if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & 0xff00) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) & 0xffff0000) operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) return AS1 (not%B0,%b0); return AS2 (xor%B0,%2,%b0); } /* Can we ignore the lower byte? */ /* ??? what about offsettable memory references? */ if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0) { CC_STATUS_INIT; operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); if (INTVAL (operands[2]) == 0xff) return AS1 (not%B0,%h0); return AS2 (xor%B0,%2,%h0); } } return AS2 (xor%W0,%2,%0);}")(define_insn "xorqi3" [(set (match_operand:QI 0 "general_operand" "=qm,q") (xor:QI (match_operand:QI 1 "general_operand" "%0,0") (match_operand:QI 2 "general_operand" "qn,qm")))] "" "* return AS2 (xor%B0,%2,%0);");;- negation instructions(define_insn "negdi2" [(set (match_operand:DI 0 "general_operand" "=&ro") (neg:DI (match_operand:DI 1 "general_operand" "0")))] "" "*{ rtx xops[2], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = const0_rtx; xops[1] = high[0]; output_asm_insn (AS1 (neg%L0,%0), low); output_asm_insn (AS2 (adc%L1,%0,%1), xops); output_asm_insn (AS1 (neg%L0,%0), high); RET;}")(define_insn "negsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (neg:SI (match_operand:SI 1 "general_operand" "0")))] "" "neg%L0 %0")(define_insn "neghi2" [(set (match_operand:HI 0 "general_operand" "=rm") (neg:HI (match_operand:HI 1 "general_operand" "0")))] "" "neg%W0 %0")(define_insn "negqi2" [(set (match_operand:QI 0 "general_operand" "=qm") (neg:QI (match_operand:QI 1 "general_operand" "0")))] "" "neg%B0 %0")(define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") (neg:SF (match_operand:SF 1 "general_operand" "0")))] "TARGET_80387" "fchs")(define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "general_operand" "0")))] "TARGET_80387" "fchs")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] "TARGET_80387" "fchs");; Absolute value instructions(define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") (abs:SF (match_operand:SF 1 "general_operand" "0")))] "TARGET_80387" "fabs")(define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "general_operand" "0")))] "TARGET_80387" "fabs")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] "TARGET_80387" "fabs")(define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsqrt")(define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsqrt")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsqrt")(define_insn "sindf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsin")(define_insn "sinsf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsin")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 1))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsin")(define_insn "cosdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fcos")(define_insn "cossf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fcos")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 2))] "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fcos");;- one complement instructions(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (not:SI (match_operand:SI 1 "general_operand" "0")))] "" "not%L0 %0")(define_insn "one_cmplhi2" [(set (match_operand:HI 0 "general_operand" "=rm") (not:HI (match_operand:HI 1 "general_operand" "0")))] "" "not%W0 %0")(define_insn "one_cmplqi2" [(set (match_operand:QI 0 "general_operand" "=qm") (not:QI (match_operand:QI 1 "general_operand" "0")))] "" "not%B0 %0");;- arithmetic shift instructions;; DImode shifts are implemented using the i386 "shift double" opcode,;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count;; is variable, then the count is in %cl and the "imm" operand is dropped;; from the assembler input.;; This instruction shifts the target reg/mem as usual, but instead of;; shifting in zeros, bits are shifted in from reg operand. If the insn;; is a left shift double, bits are taken from the high order bits of;; reg, else if the insn is a shift right double, bits are taken from the;; low order bits of reg. So if %eax is "1234" and %edx is "5678",;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".;; Since sh[lr]d does not change the `reg' operand, that is done;; separately, making all shifts emit pairs of shift double and normal;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to;; support a 63 bit shift, each shift where the count is in a reg expands;; to three pairs. If the overall shift is by N bits, then the first two;; pairs shift by N / 2 and the last pair by N & 1.;; If the shift count is a constant, we need never emit more than one;; shift pair, instead using moves and sign extension for counts greater;; than 31.(define_expand "ashldi3" [(set (match_operand:DI 0 "register_operand" "") (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" "{ if (GET_CODE (operands[2]) != CONST_INT || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) { operands[2] = copy_to_mode_reg (QImode, operands[2]); emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1], operands[2])); } else emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2])); DONE;}")(define_insn "ashldi3_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashift:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] "" "*{ rtx xops[4], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; xops[1] = const1_rtx; xops[2] = low[0]; xops[3] = high[0]; if (INTVAL (xops[0]) > 31) { output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ output_asm_insn (AS2 (xor%L2,%2,%2), xops); if (INTVAL (xops[0]) > 32) { xops[0] = GEN_INT (INTVAL (xops[0]) - 32); output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */ } } else { output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops); output_asm_insn (AS2 (sal%L2,%0,%2), xops); } RET;}")(define_insn "ashldi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashift:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "register_operand" "c"))) (clobber (match_dup 2))] "" "*{ rtx xops[4], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; xops[1] = const1_rtx; xops[2] = low[0]; xops[3] = high[0]; output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); output_asm_insn (AS2 (sal%L2,%0,%2), xops); output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); output_asm_insn (AS2 (sal%L2,%0,%2), xops); xops[1] = GEN_INT (7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); output_asm_insn (AS2 (sal%L2,%0,%2), xops); RET;}");; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg";; On i486, movl/sall appears slightly faster than leal, but the leal;; is smaller - use leal for now unless the shift count is 1.(define_insn "ashlsi3" [(set (match_operand:SI 0 "general_operand" "=r,rm") (ashift:SI (match_operand:SI 1 "general_operand" "r,0") (match_operand:SI 2 "nonmemory_operand" "M,cI")))] "" "*{ if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) { if (TARGET_486 && INTVAL (operands[2]) == 1) { output_asm_insn (AS2 (mov%L0,%1,%0), operands); return AS2 (add%L0,%1,%0); } else { CC_STATUS_INIT; if (operands[1] == stack_pointer_rtx) { output_asm_insn (AS2 (mov%L0,%1,%0), operands); operands[1] = operands[0]; } operands[1] = gen_rtx (MULT, SImode, operands[1], GEN_INT (1 << INTVAL (operands[2])))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -