📄 i386.md
字号:
;; GCC machine description for Intel 80386.;; Copyright (C) 1988 Free Software Foundation, Inc.;; Mostly by William Schelter.;; This file is part of GNU CC.;; GNU CC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GNU CC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GNU CC; see the file COPYING. If not, write to;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.;; The original PO technology requires these to be ordered by speed,;; so that assigner will pick the fastest.;; See file "rtl.def" for documentation on define_insn, match_*, et. al.;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code;; updates for most instructions.;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register;; constraint letters.;; the special asm out single letter directives following a '%' are:;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of;; operands[1].;; 'L' Print the opcode suffix for a 32-bit integer opcode.;; 'W' Print the opcode suffix for a 16-bit integer opcode.;; 'B' Print the opcode suffix for an 8-bit integer opcode.;; 'S' Print the opcode suffix for a 32-bit float opcode.;; 'Q' Print the opcode suffix for a 64-bit float opcode.;; 'b' Print the QImode name of the register for the indicated operand.;; %b0 would print %al if operands[0] is reg 0.;; 'w' Likewise, print the HImode name of the register.;; 'k' Likewise, print the SImode name of the register.;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.;; 'y' Print "st(0)" instead of "st" as a register.;; UNSPEC usage:;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode.;; operand 0 is the memory address to scan.;; operand 1 is a register containing the value to scan for. The mode;; of the scas opcode will be the same as the mode of this operand.;; operand 2 is the known alignment of operand 0.;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT.;; operand 0 is the argument for `sin'.;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT.;; operand 0 is the argument for `cos'.;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".;; But restricting MEM here would mean that gcc could not remove a redundant;; test in cases like "incl MEM / je TARGET".;;;; We don't want to allow a constant operand for test insns because;; (set (cc0) (const_int foo)) has no mode information. Such insns will;; be folded while optimizing anyway.;; All test insns have expanders that save the operands away without;; actually generating RTL. The bCOND or sCOND (emitted immediately;; after the tstM or cmp) will actually emit the tstM or cmpM.(define_insn "tstsi_cc" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "rm"))] "" "*{ if (REG_P (operands[0])) return AS2 (test%L0,%0,%0); operands[1] = const0_rtx; return AS2 (cmp%L0,%1,%0);}")(define_expand "tstsi" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" ""))] "" "{ i386_compare_gen = gen_tstsi_cc; i386_compare_op0 = operands[0]; DONE;}")(define_insn "tsthi_cc" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" "rm"))] "" "*{ if (REG_P (operands[0])) return AS2 (test%W0,%0,%0); operands[1] = const0_rtx; return AS2 (cmp%W0,%1,%0);}")(define_expand "tsthi" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" ""))] "" "{ i386_compare_gen = gen_tsthi_cc; i386_compare_op0 = operands[0]; DONE;}")(define_insn "tstqi_cc" [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" "qm"))] "" "*{ if (REG_P (operands[0])) return AS2 (test%B0,%0,%0); operands[1] = const0_rtx; return AS2 (cmp%B0,%1,%0);}")(define_expand "tstqi" [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" ""))] "" "{ i386_compare_gen = gen_tstqi_cc; i386_compare_op0 = operands[0]; DONE;}")(define_insn "tstsf_cc" [(set (cc0) (match_operand:SF 0 "register_operand" "f")) (clobber (match_scratch:HI 1 "=a"))] "TARGET_80387 && ! TARGET_IEEE_FP" "*{ if (! STACK_TOP_P (operands[0])) abort (); output_asm_insn (\"ftst\", operands); if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp,%y0), operands); return (char *) output_fp_cc0_set (insn);}");; Don't generate tstsf if generating IEEE code, since the `ftst' opcode;; isn't IEEE compliant.(define_expand "tstsf" [(parallel [(set (cc0) (match_operand:SF 0 "register_operand" "")) (clobber (match_scratch:HI 1 ""))])] "TARGET_80387 && ! TARGET_IEEE_FP" "{ i386_compare_gen = gen_tstsf_cc; i386_compare_op0 = operands[0]; DONE;}")(define_insn "tstdf_cc" [(set (cc0) (match_operand:DF 0 "register_operand" "f")) (clobber (match_scratch:HI 1 "=a"))] "TARGET_80387 && ! TARGET_IEEE_FP" "*{ if (! STACK_TOP_P (operands[0])) abort (); output_asm_insn (\"ftst\", operands); if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp,%y0), operands); return (char *) output_fp_cc0_set (insn);}");; Don't generate tstdf if generating IEEE code, since the `ftst' opcode;; isn't IEEE compliant.(define_expand "tstdf" [(parallel [(set (cc0) (match_operand:DF 0 "register_operand" "")) (clobber (match_scratch:HI 1 ""))])] "TARGET_80387 && ! TARGET_IEEE_FP" "{ i386_compare_gen = gen_tstdf_cc; i386_compare_op0 = operands[0]; DONE;}");;- compare instructions. See comments above tstM patterns about;; expansion of these insns.(define_insn "cmpsi_cc" [(set (cc0) (compare:CC (match_operand:SI 0 "nonimmediate_operand" "mr,ri") (match_operand:SI 1 "general_operand" "ri,mr")))] "" "*{ if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) { cc_status.flags |= CC_REVERSED; return AS2 (cmp%L0,%0,%1); } return AS2 (cmp%L0,%1,%0);}")(define_expand "cmpsi" [(set (cc0) (compare:CC (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" "")))] "" "{ i386_compare_gen = gen_cmpsi_cc; i386_compare_op0 = operands[0]; i386_compare_op1 = operands[1]; DONE;}")(define_insn "cmphi_cc" [(set (cc0) (compare:CC (match_operand:HI 0 "nonimmediate_operand" "mr,ri") (match_operand:HI 1 "general_operand" "ri,mr")))] "" "*{ if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) { cc_status.flags |= CC_REVERSED; return AS2 (cmp%W0,%0,%1); } return AS2 (cmp%W0,%1,%0);}")(define_expand "cmphi" [(set (cc0) (compare:CC (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" "")))] "" "{ i386_compare_gen = gen_cmphi_cc; i386_compare_op0 = operands[0]; i386_compare_op1 = operands[1]; DONE;}")(define_insn "cmpqi_cc" [(set (cc0) (compare:CC (match_operand:QI 0 "nonimmediate_operand" "qn,mq") (match_operand:QI 1 "general_operand" "qm,nq")))] "" "*{ if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) { cc_status.flags |= CC_REVERSED; return AS2 (cmp%B0,%0,%1); } return AS2 (cmp%B0,%1,%0);}")(define_expand "cmpqi" [(set (cc0) (compare:CC (match_operand:QI 0 "nonimmediate_operand" "") (match_operand:QI 1 "general_operand" "")))] "" "{ i386_compare_gen = gen_cmpqi_cc; i386_compare_op0 = operands[0]; i386_compare_op1 = operands[1]; DONE;}");; These implement float point compares. For each of DFmode and;; SFmode, there is the normal insn, and an insn where the second operand;; is converted to the desired mode.(define_insn "cmpdf_cc" [(set (cc0) (compare:CC (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "nonimmediate_operand" "fm"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" "* return (char *) output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (compare:CC (match_operand:DF 0 "register_operand" "f,f") (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))) (clobber (match_scratch:HI 2 "=a,a"))] "TARGET_80387" "* return (char *) output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (compare:CC (match_operand:DF 0 "register_operand" "f,f") (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,!*r")))) (clobber (match_scratch:HI 2 "=a,a"))] "TARGET_80387" "* return (char *) output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" "* return (char *) output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" "* return (char *) output_float_compare (insn, operands);")(define_insn "cmpsf_cc" [(set (cc0) (compare:CC (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "nonimmediate_operand" "fm"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" "* return (char *) output_float_compare (insn, operands);")(define_insn "" [(set (cc0) (compare:CC (match_operand:SF 0 "register_operand" "f,f") (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))) (clobber (match_scratch:HI 2 "=a,a"))] "TARGET_80387" "* return (char *) 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 (char *) output_float_compare (insn, operands);")(define_expand "cmpdf" [(set (cc0) (compare:CC (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:CC (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 "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_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")))] "" "*{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -