⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 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 + -