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

📄 romp.md

📁 linux下的gcc编译器
💻 MD
📖 第 1 页 / 共 5 页
字号:
;;- Machine description for ROMP chip for GNU C compiler;;   Copyright (C) 1988, 1991, 1993, 1994, 1995, 1998, 1999, 2000;;   Free Software Foundation, Inc.;;   Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu);; 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.;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.;; Define the attributes for the ROMP.;; Insn type.  Used to default other attribute values.(define_attr "type"  "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc"  (const_string "arith"));; Length in bytes.(define_attr "length" ""  (cond [(eq_attr "type" "branch")	 (if_then_else (and (ge (minus (pc) (match_dup 0))				(const_int -256))			    (le (minus (pc) (match_dup 0))				(const_int 254)))		       (const_int 2)		       (const_int 4))	 (eq_attr "type" "return,ibranch") (const_int 2)	 (eq_attr "type" "fp")		(const_int 10)	 (eq_attr "type" "call")	(const_int 4)	 (eq_attr "type" "load")	   (cond [(match_operand 1 "short_memory_operand" "") (const_int 2)		  (match_operand 1 "symbolic_memory_operand" "") (const_int 8)]		 (const_int 4))         (eq_attr "type" "loadz")	   (cond [(match_operand 1 "zero_memory_operand" "") (const_int 2)		  (match_operand 1 "symbolic_memory_operand" "") (const_int 8)]		 (const_string "4"))	 (eq_attr "type" "store")	   (cond [(match_operand 0 "short_memory_operand" "") (const_int 2)		  (match_operand 0 "symbolic_memory_operand" "") (const_int 8)]		 (const_int 4))]	(const_int 4)));; Whether insn can be placed in a delay slot.(define_attr "in_delay_slot" "yes,no"   (cond [(eq_attr "length" "8,10,38")			(const_string "no")	 (eq_attr "type" "branch,ibranch,return,call,multi")	 (const_string "no")]	(const_string "yes")));; Whether insn needs a delay slot.  We have to say that two-byte;; branches do not need a delay slot.  Otherwise, branch shortening will;; try to do something with delay slot insns (we want it to on the PA).;; This is a kludge, which should be cleaned up at some point.(define_attr "needs_delay_slot" "yes,no"  (if_then_else (ior (and (eq_attr "type" "branch")			  (eq_attr "length" "4"))		     (eq_attr "type" "ibranch,return,call"))		(const_string "yes") (const_string "no")));; What insn does to the condition code.(define_attr "cc"  "clobber,none,sets,change0,copy1to0,compare,tbit"  (cond [(eq_attr "type" "load,loadz")		(const_string "change0")	 (eq_attr "type" "store")		(const_string "none")	 (eq_attr "type" "fp,call")		(const_string "clobber")	 (eq_attr "type" "branch,ibranch,return") (const_string "none")	 (eq_attr "type" "address")		(const_string "change0")	 (eq_attr "type" "compare")		(const_string "compare")	 (eq_attr "type" "arith")		(const_string "sets")]	(const_string "clobber")));; Define attributes for `asm' insns.(define_asm_attributes [(set_attr "type" "misc")			(set_attr "length" "8")			(set_attr "in_delay_slot" "no")			(set_attr "cc" "clobber")]);; Define the delay slot requirements for branches and calls.  We don't have;; any annulled insns.;;(define_delay (eq_attr "needs_delay_slot" "yes")  [(eq_attr "in_delay_slot" "yes") (nil) (nil)]);; We cannot give a floating-point comparison a delay slot, even though it;; could make use of it.  This is because it would confuse next_cc0_user;; to do so.  Other fp insns can't get a delay slow because they set their;; result and use their input after the delay slot insn is executed.  This;; isn't what reorg.c expects.  ;; Define load & store delays.  These were obtained by measurements done by;; jfc@athena.mit.edu.;;;; In general, the memory unit can support at most two simultaneous operations.;;;; Loads take 5 cycles to return the data and can be pipelined up to the;; limit of two simultaneous operations.(define_function_unit "memory" 1 2 (eq_attr "type" "load,loadz") 5 0);; Stores do not return data, but tie up the memory unit for 2 cycles if the;; next insn is also a store.(define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 2  [(eq_attr "type" "store")]);; Move word instructions.;;;; If destination is memory but source is not register, force source to;; register.;;;; If source is a constant that is too large to load in a single insn, build;; it in two pieces.;;;; If destination is memory and source is a register, a temporary register;; will be needed.  In that case, make a PARALLEL of the SET and a;; CLOBBER of a SCRATCH to allocate the required temporary.;;;; This temporary is ACTUALLY only needed when the destination is a;; relocatable expression.  For generating RTL, however, we always;; place the CLOBBER.  In insns where it is not needed, the SCRATCH will;; not be allocated to a register.;;;; Also, avoid creating pseudo-registers or SCRATCH rtx's during reload as;; they will not be correctly handled.  We never need pseudos for that;; case anyway.;;;; We do not use DEFINE_SPLIT for loading constants because the number;; of cases in the resulting unsplit insn would be too high to deal;; with practically.(define_expand "movsi"  [(set (match_operand:SI 0 "general_operand" "")	(match_operand:SI 1 "general_operand" ""))]  ""  "{ rtx op0 = operands[0];  rtx op1 = operands[1];  if (GET_CODE (op1) == REG && REGNO (op1) == 16)    DONE;  if (GET_CODE (op0) == REG && REGNO (op0) == 16)    DONE;  if (GET_CODE (op0) == MEM && ! reload_in_progress)    {      emit_insn (gen_storesi (operands[0], force_reg (SImode, operands[1])));      DONE;    }  else if (GET_CODE (op1) == CONST_INT)    {      int const_val = INTVAL (op1);      /* Try a number of cases to see how to best load the constant.  */      if ((const_val & 0xffff) == 0	  || (const_val & 0xffff0000) == 0	  || (unsigned) (const_val + 0x8000) < 0x10000)	/* Can do this in one insn, so generate it.  */	;      else if (((- const_val) & 0xffff) == 0	       || ((- const_val) & 0xffff0000) == 0	       || (unsigned) ((- const_val) + 0x8000) < 0x10000)	{	  /* Can do this by loading the negative constant and then negating.  */	  emit_move_insn (operands[0], GEN_INT (- const_val));	  emit_insn (gen_negsi2 (operands[0], operands[0]));	  DONE;	}      else	/* Do this the long way.  */	{	  unsigned int high_part = const_val & 0xffff0000;	  unsigned int low_part = const_val & 0xffff;	  int i;	  if (low_part >= 0x10 && exact_log2 (low_part) >= 0)	    i = high_part, high_part = low_part, low_part = i;	  emit_move_insn (operands[0], GEN_INT (low_part));	  emit_insn (gen_iorsi3 (operands[0], operands[0],				 GEN_INT (high_part)));	  DONE;	}    }}");; Move from a symbolic memory location to a register is special.  In this;; case, we know in advance that the register cannot be r0, so we can improve;; register allocation by treating it separately.(define_insn ""  [(set (match_operand:SI 0 "register_operand" "=b")	(match_operand:SI 1 "symbolic_memory_operand" "m"))]  ""  "load %0,%1"  [(set_attr "type" "load")]);; Generic single-word move insn.  We avoid the case where the destination is;; a symbolic address, as that needs a temporary register.(define_insn ""  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,r,r,r,b,Q")	(match_operand:SI 1 "romp_operand" "rR,I,K,L,M,S,s,Q,m,r"))]  "register_operand (operands[0], SImode)   || register_operand (operands[1], SImode)"  "@   cas %0,%1,r0   lis %0,%1   cal %0,%1(r0)   cal16 %0,%1(r0)   cau %0,%H1(r0)   ail %0,r14,%C1   get %0,$%1   l%M1 %0,%1   load %0,%1   st%M0 %1,%0"  [(set_attr "type" "address,address,address,address,address,arith,misc,load,load,store")   (set_attr "length" "2,2,4,4,4,4,8,*,*,*")])(define_insn "storesi"  [(set (match_operand:SI 0 "memory_operand" "=Q,m")	(match_operand:SI 1 "register_operand" "r,r"))   (clobber (match_scratch:SI 2 "=X,&b"))]  ""  "@   st%M0 %1,%0   store %1,%0,%2"  [(set_attr "type" "store")]);; This pattern is used by reload when we store into a symbolic address.  It;; provides the temporary register required.  This pattern is only used;; when SECONDARY_OUTPUT_RELOAD_CLASS returns something other than;; NO_REGS, so we need not have any predicates here.(define_expand "reload_outsi"  [(parallel [(set (match_operand:SI 0 "symbolic_memory_operand" "=m")		   (match_operand:SI 1 "" "r"))	      (clobber (match_operand:SI 2 "" "=&b"))])]  ""  "");; Now do the same for the QI move instructions.(define_expand "movqi"  [(set (match_operand:QI 0 "general_operand" "")	(match_operand:QI 1 "general_operand" ""))]  ""  "{ rtx op0 = operands[0];  if (GET_CODE (op0) == MEM && ! reload_in_progress)    {      emit_insn (gen_storeqi (operands[0], force_reg (QImode, operands[1])));      DONE;    }}")(define_insn ""  [(set (match_operand:QI 0 "register_operand" "=b")	(match_operand:QI 1 "symbolic_memory_operand" "m"))]  ""   "loadc %0,%1"  [(set_attr "type" "load")])(define_insn ""  [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")	(match_operand:QI 1 "romp_operand" "r,I,n,s,Q,m,r"))]  "register_operand (operands[0], QImode)   || register_operand (operands[1], QImode)"  "@   cas %0,%1,r0   lis %0,%1   cal %0,%L1(r0)   get %0,$%1   lc%M1 %0,%1   loadc %0,%1   stc%M0 %1,%0"  [(set_attr "type" "address,address,address,misc,load,load,store")   (set_attr "length" "2,2,4,8,*,*,*")])(define_insn "storeqi"  [(set (match_operand:QI 0 "memory_operand" "=Q,m")	(match_operand:QI 1 "register_operand" "r,r"))   (clobber (match_scratch:SI 2 "=X,&b"))]  ""  "@   stc%M0 %1,%0   storec %1,%0,%2"  [(set_attr "type" "store")])(define_expand "reload_outqi"  [(parallel [(set (match_operand:QI 0 "symbolic_memory_operand" "=m")		   (match_operand:QI 1 "" "r"))	      (clobber (match_operand:SI 2 "" "=&b"))])]  ""  "");; Finally, the HI instructions.(define_expand "movhi"  [(set (match_operand:HI 0 "general_operand" "")	(match_operand:HI 1 "general_operand" ""))]  ""  "{ rtx op0 = operands[0];  if (GET_CODE (op0) == MEM && ! reload_in_progress)    {      emit_insn (gen_storehi (operands[0], force_reg (HImode, operands[1])));      DONE;    }}")(define_insn ""  [(set (match_operand:HI 0 "register_operand" "=b")	(match_operand:HI 1 "symbolic_memory_operand" "m"))]  ""  "loadha %0,%1"  [(set_attr "type" "load")]);; use cal16 instead of cal for constant source because combine requires;; the high bits of the register to be 0 after a HImode load of a constant(define_insn ""  [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")	(match_operand:HI 1 "romp_operand" "r,I,n,s,Q,m,r"))]  "register_operand (operands[0], HImode)   || register_operand (operands[1], HImode)"  "@   cas %0,%1,r0   lis %0,%1   cal16 %0,%L1(r0)   get %0,$%1   lh%N1 %0,%1   loadh %0,%1   sth%M0 %1,%0"  [(set_attr "type" "address,address,address,misc,loadz,loadz,store")   (set_attr "length" "2,2,4,8,*,*,*")])(define_insn "storehi"  [(set (match_operand:HI 0 "memory_operand" "=Q,m")	(match_operand:HI 1 "register_operand" "r,r"))   (clobber (match_scratch:SI 2 "=X,&b"))]  ""  "@   sth%M0 %1,%0   storeh %1,%0,%2"  [(set_attr "type" "store")])(define_expand "reload_outhi"  [(parallel [(set (match_operand:HI 0 "symbolic_memory_operand" "=m")		   (match_operand:HI 1 "" "r"))	      (clobber (match_operand:SI 2 "" "=&b"))])]  ""  "");; For DI move, if we have a constant, break the operation apart into;; two SImode moves because the optimizer may be able to do a better job;; with the resulting code.;;;; For memory stores, make the required pseudo for a temporary in case we;; are storing into an absolute address.;;;; We need to be careful about the cases where the output is a register that is;; the second register of the input.(define_expand "movdi"  [(set (match_operand:DI 0 "general_operand" "")	(match_operand:DI 1 "general_operand" ""))]  ""  "{ rtx op0 = operands[0];  rtx op1 = operands[1];   if (CONSTANT_P (op1))    {      rtx insns;      start_sequence ();      emit_move_insn (operand_subword (op0, 0, 1, DImode),		      operand_subword (op1, 0, 1, DImode));      emit_move_insn (operand_subword (op0, 1, 1, DImode),		      operand_subword (op1, 1, 1, DImode));      insns = get_insns ();      end_sequence ();      emit_no_conflict_block (insns, op0, op1, 0, op1);      DONE;    }  if (GET_CODE (op0) == MEM && ! reload_in_progress)    {      emit_insn (gen_storedi (operands[0], force_reg (DImode, operands[1])));      DONE;    }}")(define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")       (match_operand:DI 1 "reg_or_mem_operand" "r,Q,m,r"))]  "register_operand (operands[0], DImode)   || register_operand (operands[1], DImode)"

⌨️ 快捷键说明

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