?? i386.md
?? 這是完整的gcc源代碼
?? MD
?? 第 1 頁 / 共 4 頁
字號:
??
;; 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 1, 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.;;- instruction definitions;;- @@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.;;- When naming insn's (operand 0 of define_insn) be careful about using;;- names from other targets machine descriptions.;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code;;- updates for most instructions.;;- Operand classes for the register allocator:;;- 'a' for eax;;- 'd' for edx;;- 'c' for ecx;;- 'b' for ebx;;- 'f' for anything in FLOAT_REGS;;- 'r' any (non-floating-point) register;;- 'q' regs that allow byte operations (A, B, C and D);;- 'A' A and D registers;; 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];; 's' output a '*';; 'w' If the operand is a REG, it uses the mode size to determine the;; printing of the reg;; Put tstsi first among test insns so it matches a CONST_INT operand.(define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "general_operand" "rm"))] "" "*{ operands[1] = const0_rtx; if (REG_P (operands[0])) return AS2 (test%L0,%0,%0); return AS2 (cmp%L0,%1,%0);}")(define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "general_operand" "rm"))] "" "*{ operands[1] = const0_rtx; if (REG_P (operands[0])) return AS2 (test%W0,%0,%0); return AS2 (cmp%W0,%1,%0);}")(define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "general_operand" "qm"))] "" "*{ operands[1] = const0_rtx; if (REG_P (operands[0])) return AS2 (test%B0,%0,%0); return AS2 (cmp%B0,%1,%0);}")(define_insn "tstsf" [(set (cc0) (match_operand:SF 0 "general_operand" "rm,f")) (clobber (reg:SI 0))] "TARGET_80387" "*{ rtx xops[1]; if (!FP_REG_P (operands[0])) fp_push_sf (operands[0]);/* fp_pop_level--; */ xops[0] = FP_TOP; cc_status.flags |= CC_IN_80387; if (FP_REG_P (operands[0]) && ! top_dead_p (insn)) output_asm_insn (\"ftst\;fnstsw %R0ax\;sahf\", xops); else output_asm_insn (\"ftst\;fstp %0(0)\;fnstsw %R0ax\;sahf\", xops); RETCOM (testsf);}")(define_insn "tstdf" [(set (cc0) (match_operand:DF 0 "general_operand" "rm,f")) (clobber (reg:SI 0)) ] "TARGET_80387" "*{ rtx xops[1]; if (!FP_REG_P (operands[0])) fp_push_df (operands[0]);/* fp_pop_level--; */ xops[0] = FP_TOP; cc_status.flags |= CC_IN_80387; if (FP_REG_P (operands[0]) && ! top_dead_p (insn)) output_asm_insn (\"ftst\;fnstsw %R0ax\;sahf\", xops); else output_asm_insn (\"ftst\;fstp %0(0)\;fnstsw %R0ax\;sahf\", xops); RETCOM (testdf);}");;- compare instructions;; Put cmpsi first among compare insns so it matches two CONST_INT operands.(define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "general_operand" "mr,ri") (match_operand:SI 1 "general_operand" "ri,mr")))] "" "*{ if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return AS2 (cmp%L0,%0,%1); } return AS2 (cmp%L0,%1,%0);}")(define_insn "cmphi" [(set (cc0) (compare (match_operand:HI 0 "general_operand" "mr,ri") (match_operand:HI 1 "general_operand" "ri,mr")))] "" "*{ if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return AS2 (cmp%W0,%0,%1); } return AS2 (cmp%W0,%1,%0);}")(define_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "general_operand" "qn,mq") (match_operand:QI 1 "general_operand" "qm,nq")))] "" "*{ if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return AS2 (cmp%B0,%0,%1); } return AS2 (cmp%B0,%1,%0);}")(define_insn "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "general_operand" "m,f*r,m,f,r,!*r") (match_operand:DF 1 "general_operand" "m,m,f*r,r,f,*r"))) (clobber (reg:SI 0))] "TARGET_80387" "*{ if (FP_REG_P (operands[0])) { rtx tem = operands[1]; operands[1] = operands[0]; operands[0] = tem; cc_status.flags |= CC_REVERSED; } if (! FP_REG_P (operands[1])) output_movdf (FP_TOP, operands[1]); output_movdf (FP_TOP, operands[0]);/* fp_pop_level--; fp_pop_level--; */ cc_status.flags |= CC_IN_80387; return \"fcompp\;fnstsw %R0ax\;sahf\";}")(define_insn "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "general_operand" "m,f*r,m,f,r,!*r") (match_operand:SF 1 "general_operand" "m,m,f*r,r,f,*r"))) (clobber (reg:SI 0))] "TARGET_80387" "*{ if (FP_REG_P (operands[0])) { rtx tem = operands[1]; operands[1] = operands[0]; operands[0] = tem; cc_status.flags |= CC_REVERSED; } if (! FP_REG_P (operands[1])) output_movsf (FP_TOP, operands[1]); output_movsf (FP_TOP, operands[0]);/* fp_pop_level--; fp_pop_level--; */ cc_status.flags |= CC_IN_80387; return \"fcompp\;fnstsw %R0ax\;sahf\";}");; logical compare(define_insn "" [(set (cc0) (and:SI (match_operand:SI 0 "general_operand" "rm,ri") (match_operand:SI 1 "general_operand" "ri,rm")))] "" "*{ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%L0,%1,%0); return AS2 (test%L0,%0,%1);}")(define_insn "" [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "rm,ri") (match_operand:HI 1 "general_operand" "ri,rm")))] "" "*{ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%W0,%1,%0); return AS2 (test%W0,%0,%1);}")(define_insn "" [(set (cc0) (and:QI (match_operand:QI 0 "general_operand" "qm,qi") (match_operand:QI 1 "general_operand" "qi,qm")))] "" "*{ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%B0,%1,%0); return AS2 (test%B0,%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"))] "" "push%L0 %1");; General case of fullword move.(define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=g,r") (match_operand:SI 1 "general_operand" "ri,m"))] "" "*{ rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) return \"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. */ && ! XEXP (link, 0)->volatil && GET_CODE (XEXP (link, 0)) != NOTE /* Make sure cross jumping didn't happen here. */ && no_labels_between_p (XEXP (link, 0), insn)) /* Fastest way to change a 0 to a 1. */ return \"inc%L0 %0\"; return \"mov%L0 %1,%0\";}")(define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "general_operand" "g"))] "" "push%W0 %1")(define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=g,r") (match_operand:HI 1 "general_operand" "ri,m"))] "" "*{ rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) return \"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. */ && ! XEXP (link, 0)->volatil && GET_CODE (XEXP (link, 0)) != NOTE /* Make sure cross jumping didn't happen here. */ && no_labels_between_p (XEXP (link, 0), insn)) /* Fastest way to change a 0 to a 1. */ return \"inc%W0 %0\"; return \"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 "general_operand" "q"))] "" "*{ operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); return \"push%W0 %1\";}")(define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=q,*r,m") (match_operand:QI 1 "general_operand" "*g,q,qi"))] "" "*{ rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) return \"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. */ && ! XEXP (link, 0)->volatil && GET_CODE (XEXP (link, 0)) != NOTE /* Make sure cross jumping didn't happen here. */ && no_labels_between_p (XEXP (link, 0), insn)) /* Fastest way to change a 0 to a 1. */ return \"inc%B0 %0\"; /* If mov%B0 isn't allowed for one of these regs, use mov%W0. */ if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) return (AS2 (mov%W0,%w1,%w0)); return (AS2 (mov%B0,%1,%0));}"); I suspect nothing can ever match this ???;(define_insn ""; [(set (match_operand:SF 0 "general_operand" "rm"); (match_operand:SF 1 "general_operand" "f")); (clobber (reg:SF 8))]; ""; "*;{; output_asm_insn ("???", operands);; fpop_sf (operands[0]);; RETCOM (movsf_clobber);;}")(define_insn "" [(set (match_operand:SF 0 "push_operand" "=<,<") (match_operand:SF 1 "general_operand" "gF,f"))] "" "*{ if (FP_REG_P (operands[1])) { rtx xops[3]; xops[0] = AT_SP (SFmode); xops[1] = gen_rtx (CONST_INT, VOIDmode, 4); xops[2] = stack_pointer_rtx;/* fp_pop_level--; */ output_asm_insn (AS2 (sub%L0,%1,%2), xops); if (top_dead_p (insn)) output_asm_insn (\"fstp%S0 %0\", xops); else output_asm_insn (\"fst%S0 %0\", xops); RET; } return \"push%L0 %1\";}")(define_insn "movsf" ;; `rf' is duplicated in the second alternative ;; to make sure an optional reload is generated ;; for the memref in operand 0. Otherwise ;; we could use too many hard regs. [(set (match_operand:SF 0 "general_operand" "=rf,mrf,!rm") (match_operand:SF 1 "general_operand" "mrf,rf,F"))] "" "*{ if (FP_REG_P (operands[1]) && !FP_REG_P (operands[0]) && !top_dead_p (insn)) fp_store_sf (operands[0]); else output_movsf (operands[0], operands[1]); RETCOM (movsf);}");;should change to handle the memory operands[1] without doing df push..(define_insn "" [(set (match_operand:DF 0 "push_operand" "=<,<") (match_operand:DF 1 "general_operand" "gF,f"))] "" "*{ if (FP_REG_P (operands[1])) { rtx xops[3]; xops[0] = AT_SP (DFmode); xops[1] = gen_rtx (CONST_INT, VOIDmode, 8); xops[2] = stack_pointer_rtx;/* fp_pop_level--; */ output_asm_insn (AS2 (sub%L0,%1,%2), xops); if (top_dead_p(insn)) output_asm_insn (\"fstp%Q0 %0\", xops); else output_asm_insn (\"fst%Q0 %0\", xops); RETCOM (pushdf); } else return output_move_double (operands);}")(define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=rmf,&fr,!rm") ;; `rf' is duplicated in the second alternative ;; to make sure that optional reloads are generated ;; for the memory reference in operand 1. (match_operand:DF 1 "general_operand" "fr,mrf,F"))] "" "*{ if (FP_REG_P (operands[1]) && ! FP_REG_P (operands[0]) && ! top_dead_p (insn)) fp_store_df (operands[0]); else output_movdf (operands[0], operands[1]); RETCOM (movdf);}")(define_insn "" [(set (match_operand:DI 0 "push_operand" "=<") (match_operand:DI 1 "general_operand" "roiF"))] "" "*{ return output_move_double (operands);}")(define_insn "movdi" [(set (match_operand:DI 0 "general_operand" "=&r,rm") (match_operand:DI 1 "general_operand" "m,riF"))] "" "*{ return output_move_double (operands);}");; These go after the move instructions;; because the move instructions are better (require no spilling);; when they can apply. But these go before the add and subtract insns;; because it is often shorter to use these when both apply.;Lennart Augustsson <augustss@cs.chalmers.se>;says this pattern just makes slower code:; pushl %ebp; addl $-80,(%esp);instead of; leal -80(%ebp),%eax; pushl %eax;;(define_insn ""; [(set (match_operand:SI 0 "push_operand" "=<"); (plus:SI (match_operand:SI 1 "general_operand" "%r"); (match_operand:SI 2 "general_operand" "ri")))]; ""; "*;{; rtx xops[4];; xops[0] = operands[0];; xops[1] = operands[1];; xops[2] = operands[2];; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);; output_asm_insn (\"push%z1 %1\", xops);; output_asm_insn (AS2 (add%z3,%2,%3), xops);; RET;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -