mn10200.md

来自「GCC编译器源代码」· Markdown 代码 · 共 1,979 行 · 第 1/4 页

MD
1,979
字号
;; GCC machine description for Matsushita MN10200;; Copyright (C) 1997 Free Software Foundation, Inc.;; Contributed by Jeff Law (law@cygnus.com).;; 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, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, 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.;; Condition code settings.;; none - insn does not affect cc;; none_0hit - insn does not affect cc but it does modify operand 0;;	This attribute is used to keep track of when operand 0 changes.;; 	See the description of NOTICE_UPDATE_CC for more info.;; set_znv - sets z,n,v to usable values; c is unknown.;; set_zn  - sets z,n to usable values; v,c is unknown.;; compare - compare instruction;; clobber - value of cc is unknown(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber"  (const_string "clobber"));; ----------------------------------------------------------------------;; MOVE INSTRUCTIONS;; ----------------------------------------------------------------------;;;; Some general notes on move instructions.;;;; The hardware can't encode nop moves involving data registers, so;; we catch them and emit a nop instead.;;;; Loads/stores to/from address registers must be 16bit aligned,;; thus we avoid them for QImode.;;;; Stores from address registers always store 24bits, so avoid;; stores from address registers in HImode, SImode, and SFmode.;;;; As a result of the various problems using address registers in;; QImode, HImode, SImode, and SFmode, we discourage their use via;; '*' in their constraints.  They're still allowed, but they're never;; the preferred class for for insns with those modes.;; movqi(define_expand "movqi"  [(set (match_operand:QI 0 "general_operand" "")	(match_operand:QI 1 "general_operand" ""))]  ""  "{  /* One of the ops has to be in a register */  if (!register_operand (operand0, QImode)      && !register_operand (operand1, QImode))    operands[1] = copy_to_mode_reg (QImode, operand1);}");; We avoid memory operations involving address registers because we;; can't be sure they'll be suitably aligned.;;;; We also discourage holding QImode values in address registers.(define_insn ""  [(set (match_operand:QI 0 "general_operand" "=d,d,*a,d,d,m,d,*a,*a")	(match_operand:QI 1 "general_operand" "0,I,I,di,m,d,*a,d,i*a"))]  "register_operand (operands[0], QImode)   || register_operand (operands[1], QImode)"  "@  nop  sub %0,%0  sub %0,%0  mov %S1,%0  movbu %1,%0  movb %1,%0  mov %1,%0  mov %1,%0  mov %1,%0"  [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]);; movhi(define_expand "movhi"  [(set (match_operand:HI 0 "general_operand" "")	(match_operand:HI 1 "general_operand" ""))]  ""  "{  /* One of the ops has to be in a register */  if (!register_operand (operand1, HImode)      && !register_operand (operand0, HImode))    operands[1] = copy_to_mode_reg (HImode, operand1);}")(define_insn ""  [(set (match_operand:HI 0 "general_operand" "=d,d,*a,d,d,m,d,*a,*a,*a")	(match_operand:HI 1 "general_operand" "0,I,I,di,m,d,*a,d,i*a,m"))]  "register_operand (operands[0], HImode)   || register_operand (operands[1], HImode)"  "@  nop  sub %0,%0  sub %0,%0  mov %s1,%0  mov %1,%0  mov %1,%0  mov %1,%0  mov %1,%0  mov %1,%0  mov %A1,%0"  [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]);; movpsi and helpers(define_expand "movpsi"  [(set (match_operand:PSI 0 "general_operand" "")	(match_operand:PSI 1 "general_operand" ""))]  ""  "{  /* One of the ops has to be in a register */  if (!register_operand (operand1, PSImode)      && !register_operand (operand0, PSImode))    operands[1] = copy_to_mode_reg (PSImode, operand1);}");; Constant and indexed addresses are not valid addresses for PSImode,;; therefore they won't be matched by the general movpsi pattern below.;; ??? We had patterns to handle indexed addresses, but they kept making;; us run out of regs, so they were eliminated.(define_insn ""  [(set (match_operand:PSI 0 "register_operand" "=a")	(match_operand:PSI 1 "constant_memory_operand" ""))]  ""  "mov %A1,%0"  [(set_attr "cc" "none_0hit")])(define_insn ""  [(set (match_operand:PSI 0 "constant_memory_operand" "=X")	(match_operand:PSI 1 "register_operand" "a"))]  ""  "mov %1,%A0"  [(set_attr "cc" "none_0hit")]);; We want to prefer address registers here because 24bit moves to/from;; memory are shorter and faster when done via address registers.(define_insn ""  [(set (match_operand:PSI 0 "general_operand" "=d,a?d,?da,a,m,?d,m")	(match_operand:PSI 1 "general_operand" "0,I,?dai,m,a,m,?d"))]  "register_operand (operands[0], PSImode)   || register_operand (operands[1], PSImode)"  "@  nop  sub %0,%0  mov %1,%0  mov %A1,%0  mov %1,%A0  movx %A1,%0  movx %1,%A0"  [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])(define_expand "movsi"  [(set (match_operand:SI 0 "general_operand" "")	(match_operand:SI 1 "general_operand" ""))]  ""  "{  /* One of the ops has to be in a register */  if (!register_operand (operand1, SImode)      && !register_operand (operand0, SImode))    operands[1] = copy_to_mode_reg (SImode, operand1);}")(define_insn ""  [(set (match_operand:SI 0 "general_operand" "=d,d,*a,dm,d,d,*a,*a,*a")	(match_operand:SI 1 "general_operand" "0,I,I,d,dim,*a,d,*a,i"))]  "register_operand (operands[0], SImode)   || register_operand (operands[1], SImode)"  "*{  switch (which_alternative)    {    case 0:      return \"nop\";    case 1:    case 2:      return \"sub %H0,%H0\;sub %L0,%L0\";    case 3:    case 5:    case 6:    case 7:      return \"mov %H1,%H0\;mov %L1,%L0\";    /* The next two cases try to optimize cases where one half       of the constant is all zeros, or when the two halves are       the same.  */    case 4:    case 8:      if (REG_P (operands[0])	  && GET_CODE (operands[1]) == CONST_INT	  && (INTVAL (operands[1]) & 0xffff0000) == 0)	output_asm_insn (\"sub %H0,%H0\", operands);      else	output_asm_insn (\"mov %h1,%H0\", operands);      if (GET_CODE (operands[1]) == CONST_INT	  && ((INTVAL (operands[1]) & 0xffff)	      == ((INTVAL (operands[1]) >> 16) & 0xffff)))	output_asm_insn (\"mov %H0,%L0\", operands);      else if (GET_CODE (operands[1]) == CONST_INT	       && (INTVAL (operands[1]) & 0xffff) == 0)	output_asm_insn (\"sub %L0,%L0\", operands);      else	output_asm_insn (\"mov %o1,%L0\", operands);      return \"\";    }}"  [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])(define_expand "movsf"  [(set (match_operand:SF 0 "general_operand" "")	(match_operand:SF 1 "general_operand" ""))]  ""  "{  /* One of the ops has to be in a register */  if (!register_operand (operand1, SFmode)      && !register_operand (operand0, SFmode))    operands[1] = copy_to_mode_reg (SFmode, operand1);}")(define_insn ""  [(set (match_operand:SF 0 "general_operand" "=d,d,*a,dm,d,d,*a,*a,*a")	(match_operand:SF 1 "general_operand" "0,G,G,d,dim,*a,d,*a,i"))]  "register_operand (operands[0], SFmode)   || register_operand (operands[1], SFmode)"  "*{  switch (which_alternative)    {    case 0:      return \"nop\";    case 1:    case 2:      return \"sub %H0,%H0\;sub %L0,%L0\";    default:      {        long val;        REAL_VALUE_TYPE rv;	if (GET_CODE (operands[1]) == CONST_DOUBLE)	  {	    REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);	    REAL_VALUE_TO_TARGET_SINGLE (rv, val);	  }	if (GET_CODE (operands[1]) == CONST_INT)	  val = INTVAL (operands[1]);        if ((GET_CODE (operands[1]) == CONST_INT	     || GET_CODE (operands[1]) == CONST_DOUBLE)	    && (val & 0xffff0000) == 0)	  output_asm_insn (\"sub %H0,%H0\", operands);	else	  output_asm_insn (\"mov %h1,%H0\", operands);		if (GET_CODE (operands[1]) == CONST_INT	    && ((INTVAL (operands[1]) & 0xffff)		 == ((INTVAL (operands[1]) >> 16) & 0xffff)))	  output_asm_insn (\"mov %H0,%L0\", operands);        else if ((GET_CODE (operands[1]) == CONST_INT		  || GET_CODE (operands[1]) == CONST_DOUBLE)		 && (val & 0x0000ffff) == 0)	  output_asm_insn (\"sub %L0,%L0\", operands);	else	  output_asm_insn (\"mov %o1,%L0\", operands);	return \"\";      }    }}"  [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]);; ----------------------------------------------------------------------;; TEST INSTRUCTIONS;; ----------------------------------------------------------------------;; Go ahead and define tsthi and tstpsi so we can eliminate redundant tst insns;; when we start trying to optimize this port.(define_insn "tsthi"  [(set (cc0) (match_operand:HI 0 "general_operand" "da"))]  ""  "* return output_tst (operands[0], insn);"  [(set_attr "cc" "set_znv")])(define_insn "tstpsi"  [(set (cc0) (match_operand:PSI 0 "general_operand" "da"))]  ""  "* return output_tst (operands[0], insn);"  [(set_attr "cc" "set_znv")])(define_insn ""  [(set (cc0) (zero_extend:HI (match_operand:QI 0 "memory_operand" "d")))]  ""  "* return output_tst (operands[0], insn);"  [(set_attr "cc" "set_znv")])(define_insn ""  [(set (cc0) (zero_extend:PSI (match_operand:QI 0 "memory_operand" "d")))]  ""  "* return output_tst (operands[0], insn);"  [(set_attr "cc" "set_znv")])(define_insn "cmphi"  [(set (cc0)	(compare:HI (match_operand:HI 0 "general_operand" "da")		    (match_operand:HI 1 "general_operand" "dai")))]  ""  "cmp %1,%0"  [(set_attr "cc" "compare")])(define_insn "cmppsi"  [(set (cc0)	(compare:PSI (match_operand:PSI 0 "general_operand" "da")		     (match_operand:PSI 1 "general_operand" "dai")))]  ""  "cmp %1,%0"  [(set_attr "cc" "compare")]);; ----------------------------------------------------------------------;; ADD INSTRUCTIONS;; ----------------------------------------------------------------------(define_insn "addhi3"  [(set (match_operand:HI 0 "general_operand" "=d")	(plus:HI (match_operand:HI 1 "general_operand" "%0")		 (match_operand:HI 2 "general_operand" "dai")))]  ""  "add %2,%0"  [(set_attr "cc" "set_zn")])(define_insn "addpsi3"  [(set (match_operand:PSI 0 "general_operand" "=da")	(plus:PSI (match_operand:PSI 1 "general_operand" "%0")		  (match_operand:PSI 2 "general_operand" "dai")))]  ""  "add %2,%0"  [(set_attr "cc" "set_zn")]);; We want to avoid using explicit registers; reload won't tell us;; if it has to spill them and may generate incorrect code in such;; cases.;;;; So we call out to a library routine to perform 32bit add or;; subtract operations.(define_expand "addsi3"  [(set (match_operand:SI 0 "general_operand" "")	(plus:SI (match_operand:SI 1 "general_operand" "")		 (match_operand:SI 2 "general_operand" "")))]  ""  "{  /* If adding a CONST_INT, we are better off generating code ourselves.     During RTL generation we call out to library routines.     After RTL generation we can not call the library routines as     they need to push arguments via virtual_outgoing_args_rtx which     has already been instantiated.  So, after RTL generation we just     FAIL and open code the operation.  */  if (GET_CODE (operands[2]) == CONST_INT)    {      if (!rtx_equal_p (operands[0], operands[1]))	emit_move_insn (operands[0], operands[1]);      emit_insn (gen_addsi3_const (operands[0], operands[0], operands[2]));      DONE;    }  else if (rtx_equal_function_value_matters)    {      rtx ret, insns;      extern rtx emit_library_call_value ();      start_sequence ();      ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__addsi3\"),				     NULL_RTX, 1, SImode, 2, operands[1],				     SImode, operands[2], SImode);      insns = get_insns ();      end_sequence ();      emit_libcall_block (insns, operands[0], ret,			  gen_rtx (ASHIFT, SImode, operands[1], operands[2]));      DONE;    }  else    FAIL;}")(define_insn "addsi3_const"  [(set (match_operand:SI 0 "general_operand" "=d")	(plus:SI (match_operand:SI 1 "general_operand" "0")		 (match_operand:SI 2 "const_int_operand" "i")))   (clobber (match_scratch:SI 3 "=&d"))]  ""  "*{  unsigned long value = INTVAL (operands[2]);  /* If only the high bits are set in the constant, then we only     need a single add operation.  It might be better to catch this     at RTL expansion time.  */  if ((value & 0xffff) == 0)    return \"add %h2,%H0\";  value >>= 16;  value &= 0xffff;  if (value == 0)    return \"sub %3,%3\;add %o2,%L0\;addc %3,%H0\";  else    return \"mov %h2,%3\;add %o2,%L0\;addc %3,%H0\";}"  [(set_attr "cc" "clobber")]);; ----------------------------------------------------------------------;; SUBTRACT INSTRUCTIONS;; ----------------------------------------------------------------------(define_insn "subhi3"  [(set (match_operand:HI 0 "general_operand" "=d")	(minus:HI (match_operand:HI 1 "general_operand" "0")		  (match_operand:HI 2 "general_operand" "dai")))]  ""  "sub %2,%0"  [(set_attr "cc" "set_zn")])(define_insn "subpsi3"  [(set (match_operand:PSI 0 "general_operand" "=da")	(minus:PSI (match_operand:PSI 1 "general_operand" "0")		  (match_operand:PSI 2 "general_operand" "dai")))]  ""  "sub %2,%0"  [(set_attr "cc" "set_zn")])(define_expand "subsi3"  [(set (match_operand:SI 0 "general_operand" "")	(minus:SI (match_operand:SI 1 "general_operand" "")		  (match_operand:SI 2 "general_operand" "")))]  ""  "{  /* During RTL generation we call out to library routines.     After RTL generation we can not call the library routines as     they need to push arguments via virtual_outgoing_args_rtx which     has already been instantiated.  So, after RTL generation we just     FAIL and open code the operation.  */  if (rtx_equal_function_value_matters)    {      rtx ret, insns;      extern rtx emit_library_call_value ();      start_sequence ();      ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__subsi3\"),				     NULL_RTX, 1, SImode, 2, operands[1],				     SImode, operands[2], SImode);      insns = get_insns ();      end_sequence ();      emit_libcall_block (insns, operands[0], ret,			  gen_rtx (ASHIFT, SImode, operands[1], operands[2]));      DONE;    }  else    FAIL;}");; There isn't a negate instruction, so we fake it.;;;; We used to expand this into patterns, but a single pattern

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?