📄 i386.md
字号:
&& 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 (i386_aligned_p (operands[1])) { operands[1] = i386_sext16_if_const (operands[1]); return AS2 (mov%L0,%k1,%k0); } if (TARGET_PENTIUMPRO) { /* movzwl is faster than movw on the Pentium Pro, * although not as fast as an aligned movl. */#ifdef INTEL_SYNTAX return AS2 (movzx,%1,%k0);#else return AS2 (movz%W0%L0,%1,%k0);#endif } } 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 "const_int_operand" "n"))] "" "* 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);}")(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.(define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 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 (QImode, operands[1]); }}")(define_insn "" [(set (match_operand:QI 0 "nonimmediate_operand" "=q,*r,qm") (match_operand:QI 1 "general_operand" "*g,r,qn"))] "(!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,%k0,%k0); 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%B0,%0); /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) return (AS2 (mov%L0,%k1,%k0)); return (AS2 (mov%B0,%1,%0));}");; If it becomes necessary to support movstrictqi into %esi or %edi,;; use the insn sequence:;;;; shrdl $8,srcreg,dstreg;; rorl $24,dstreg;;;; If operands[1] is a constant, then an andl/orl sequence would be;; faster.(define_expand "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "general_operand" "")) (match_operand:QI 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 (QImode, operands[1]); }}")(define_insn "" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (match_operand:QI 1 "general_operand" "*qn,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%B0,%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%B0,%0); /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) { abort (); return (AS2 (mov%L0,%k1,%k0)); } return AS2 (mov%B0,%1,%0);}")(define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" ""))] "" "{ /* Special case memory->memory moves and pushes */ if (TARGET_MOVE && (reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) == MEM && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode))) { rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode)) ? gen_movsf_push : gen_movsf_mem; emit_insn ((*genfunc) (operands[0], operands[1])); DONE; } /* If we are loading a floating point constant that isn't 0 or 1 into a register, indicate we need the pic register loaded. This could be optimized into stores of constants if the target eventually moves to memory, but better safe than sorry. */ if ((reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) == CONST_DOUBLE && !standard_80387_constant_p (operands[1])) { rtx insn, note, fp_const; fp_const = force_const_mem (SFmode, operands[1]); if (flag_pic) current_function_uses_pic_offset_table = 1; insn = emit_insn (gen_rtx (SET, SFmode, operands[0], fp_const)); note = find_reg_note (insn, REG_EQUAL, NULL_RTX); if (note) XEXP (note, 0) = operands[1]; else REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn)); }}")(define_insn "movsf_push_nomove" [(set (match_operand:SF 0 "push_operand" "=<,<") (match_operand:SF 1 "general_operand" "gF,f"))] "!TARGET_MOVE" "*{ if (STACK_REG_P (operands[1])) { rtx xops[3]; if (! STACK_TOP_P (operands[1])) abort (); xops[0] = AT_SP (SFmode); xops[1] = GEN_INT (4); xops[2] = stack_pointer_rtx; output_asm_insn (AS2 (sub%L2,%1,%2), xops); if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp%S0,%0), xops); else output_asm_insn (AS1 (fst%S0,%0), xops); RET; } return AS1 (push%L1,%1);}")(define_insn "movsf_push" [(set (match_operand:SF 0 "push_operand" "=<,<,<,<") (match_operand:SF 1 "general_operand" "rF,f,m,m")) (clobber (match_scratch:SI 2 "=X,X,r,X"))] "" "*{ if (STACK_REG_P (operands[1])) { rtx xops[3]; if (! STACK_TOP_P (operands[1])) abort (); xops[0] = AT_SP (SFmode); xops[1] = GEN_INT (4); xops[2] = stack_pointer_rtx; output_asm_insn (AS2 (sub%L2,%1,%2), xops); if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp%S0,%0), xops); else output_asm_insn (AS1 (fst%S0,%0), xops); RET; } else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG) return AS1 (push%L1,%1); else { output_asm_insn (AS2 (mov%L2,%1,%2), operands); return AS1 (push%L2,%2); }}");; Special memory<->memory pattern that combine will recreate from the;; moves to pseudos.(define_insn "movsf_mem" [(set (match_operand:SF 0 "memory_operand" "=m") (match_operand:SF 1 "memory_operand" "m")) (clobber (match_scratch:SI 2 "=&r"))] "" "*{ output_asm_insn (AS2 (mov%L2,%1,%2), operands); return AS2 (mov%L0,%2,%0);}");; For the purposes of regclass, prefer FLOAT_REGS.(define_insn "movsf_normal" [(set (match_operand:SF 0 "nonimmediate_operand" "=*rfm,*rf,f,!*rm") (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "*{ int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; /* First handle a `pop' insn or a `fld %st(0)' */ if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) { if (stack_top_dies) return AS1 (fstp,%y0); else return AS1 (fld,%y0); } /* Handle a transfer between the 387 and a 386 register */ if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1])) { output_op_from_reg (operands[1], AS1 (fld%z0,%y1)); RET; } if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { output_to_reg (operands[0], stack_top_dies, 0); RET; } /* Handle other kinds of writes from the 387 */ if (STACK_TOP_P (operands[1])) { if (stack_top_dies) return AS1 (fstp%z0,%y0); else return AS1 (fst%z0,%y0); } /* Handle other kinds of reads to the 387 */ if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) return output_move_const_single (operands); if (STACK_TOP_P (operands[0])) return AS1 (fld%z1,%y1); /* Handle all SFmode moves not involving the 387 */ return singlemove_string (operands);}" [(set_attr "type" "fld")])(define_insn "swapsf" [(set (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")) (set (match_dup 1) (match_dup 0))] "" "*{ if (STACK_TOP_P (operands[0])) return AS1 (fxch,%1); else return AS1 (fxch,%0);}")(define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] "" "{ /* Special case memory->memory moves and pushes */ if (TARGET_MOVE && (reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) == MEM && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode))) { rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode)) ? gen_movdf_push : gen_movdf_mem; emit_insn ((*genfunc) (operands[0], operands[1])); DONE; } /* If we are loading a floating point constant that isn't 0 or 1 into a register, indicate we need the pic register loaded. This could be optimized into stores of constants if the target eventually moves to memory, but better safe than sorry. */ if ((reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) == CONST_DOUBLE && !standard_80387_constant_p (operands[1])) { rtx insn, note, fp_const; fp_const = force_const_mem (DFmode, operands[1]); if (flag_pic) current_function_uses_pic_offset_table = 1; insn = emit_insn (gen_rtx (SET, DFmode, operands[0], fp_const)); note = find_reg_note (insn, REG_EQUAL, NULL_RTX); if (note) XEXP (note, 0) = operands[1]; else REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn)); }}")(define_insn "movdf_push_nomove"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -