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

📄 m32r.md

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 MD
📖 第 1 页 / 共 5 页
字号:
;; Machine description of the Renesas M32R cpu for GNU C compiler;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004;  Free Software Foundation, Inc.;; This file is part of GCC.;; GCC 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.;; GCC 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 GCC; 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.;; UNSPEC_VOLATILE usage(define_constants  [(UNSPECV_BLOCKAGE		0)   (UNSPECV_FLUSH_ICACHE	1)]);; UNSPEC usage(define_constants  [(UNSPEC_LOAD_SDA_BASE	2)   (UNSPEC_SET_CBIT		3)   (UNSPEC_PIC_LOAD_ADDR	4)   (UNSPEC_GET_PC		5)   (UNSPEC_GOTOFF		6)   ]);; Insn type.  Used to default other attribute values.(define_attr "type"  "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc"  (const_string "misc"));; Length in bytes.(define_attr "length" ""  (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2")	 (const_int 2)	 (eq_attr "type" "int4,load4,store4,shift4,div4")	 (const_int 4)	 (eq_attr "type" "multi")	 (const_int 8)	 (eq_attr "type" "uncond_branch,branch,call")	 (const_int 4)]	 (const_int 4)));; The length here is the length of a single asm.  Unfortunately it might be;; 2 or 4 so we must allow for 4.  That's ok though.(define_asm_attributes  [(set_attr "length" "4")   (set_attr "type" "multi")]);; Whether an instruction is short (16-bit) or long (32-bit).(define_attr "insn_size" "short,long"  (if_then_else (eq_attr "type" "int2,load2,store2,shift2,mul2")		(const_string "short")		(const_string "long")));; The target CPU we're compiling for.(define_attr "cpu" "m32r,m32r2,m32rx"  (cond [(ne (symbol_ref "TARGET_M32RX") (const_int 0))	     (const_string "m32rx")	 (ne (symbol_ref "TARGET_M32R2") (const_int 0))	     (const_string "m32r2")]    (const_string "m32r")));; Defines the pipeline where an instruction can be executed on.;; For the M32R, a short instruction can execute one of the two pipes.;; For the M32Rx, the restrictions are modelled in the second;;  condition of this attribute definition.(define_attr "m32r_pipeline" "either,s,o,long"  (cond [(and (eq_attr "cpu" "m32r")	      (eq_attr "insn_size" "short"))	     (const_string "either")         (eq_attr "insn_size" "!short")	     (const_string "long")]	 (cond [(eq_attr "type" "int2")		   (const_string "either")	        (eq_attr "type" "load2,store2,shift2,uncond_branch,branch,call")		   (const_string "o")	        (eq_attr "type" "mul2")		   (const_string "s")]	 (const_string "long"))));; ::::::::::::::::::::;; ::;; :: Pipeline description;; ::;; ::::::::::::::::::::;; This model is based on Chapter 2, Appendix 3 and Appendix 4 of the;; "M32R-FPU Software Manual", Revision 1.01, plus additional information;; obtained by our best friend and mine, Google.;;;; The pipeline is modelled as a fetch unit, and a core with a memory unit,;; two execution units, where "fetch" models IF and D, "memory" for MEM1;; and MEM2, and "EXEC" for E, E1, E2, EM, and EA.  Writeback and;; bypasses are not modelled.(define_automaton "m32r");; We pretend there are two short (16 bits) instruction fetchers.  The;; "s" short fetcher cannot be reserved until the "o" short fetcher is;; reserved.  Some instructions reserve both the left and right fetchers.;; These fetch units are a hack to get GCC to better pack the instructions;; for the M32Rx processor, which has two execution pipes.;;;; In reality there is only one decoder, which can decode either two 16 bits;; instructions, or a single 32 bits instruction.;;;; Note, "fetch" models both the IF and the D pipeline stages.;;;; The m32rx core has two execution pipes.  We name them o_E and s_E.;; In addition, there's a memory unit.(define_cpu_unit "o_IF,s_IF,o_E,s_E,memory" "m32r");; Prevent the s pipe from being reserved before the o pipe.(absence_set "s_IF" "o_IF")(absence_set "s_E"  "o_E");; On the M32Rx, long instructions execute on both pipes, so reserve;; both fetch slots and both pipes.(define_reservation "long_IF" "o_IF+s_IF")(define_reservation "long_E" "o_E+s_E");; ::::::::::::::::::::;; Simple instructions do 4 stages: IF D E WB.  WB is not modelled.;; Hence, ready latency is 1.(define_insn_reservation "short_left" 1  (and (eq_attr "m32r_pipeline" "o")       (and (eq_attr "insn_size" "short")	    (eq_attr "type" "!load2")))  "o_IF,o_E")(define_insn_reservation "short_right" 1  (and (eq_attr "m32r_pipeline" "s")       (and (eq_attr "insn_size" "short")	    (eq_attr "type" "!load2")))  "s_IF,s_E")(define_insn_reservation "short_either" 1  (and (eq_attr "m32r_pipeline" "either")       (and (eq_attr "insn_size" "short")	    (eq_attr "type" "!load2")))  "o_IF|s_IF,o_E|s_E")(define_insn_reservation "long_m32r" 1  (and (eq_attr "cpu" "m32r")       (and (eq_attr "insn_size" "long")	    (eq_attr "type" "!load4,load8")))  "long_IF,long_E")(define_insn_reservation "long_m32rx" 2  (and (eq_attr "m32r_pipeline" "long")       (and (eq_attr "insn_size" "long")	    (eq_attr "type" "!load4,load8")))  "long_IF,long_E");; Load/store instructions do 6 stages: IF D E MEM1 MEM2 WB.;; MEM1 may require more than one cycle depending on locality.  We;; optimistically assume all memory is nearby, i.e. MEM1 takes only;; one cycle.  Hence, ready latency is 3.;; The M32Rx can do short load/store only on the left pipe.(define_insn_reservation "short_load_left" 3  (and (eq_attr "m32r_pipeline" "o")       (and (eq_attr "insn_size" "short")	    (eq_attr "type" "load2")))  "o_IF,o_E,memory*2")(define_insn_reservation "short_load" 3  (and (eq_attr "m32r_pipeline" "either")       (and (eq_attr "insn_size" "short")	    (eq_attr "type" "load2")))  "s_IF|o_IF,s_E|o_E,memory*2")(define_insn_reservation "long_load" 3  (and (eq_attr "cpu" "m32r")       (and (eq_attr "insn_size" "long")	    (eq_attr "type" "load4,load8")))  "long_IF,long_E,memory*2")(define_insn_reservation "long_load_m32rx" 3  (and (eq_attr "m32r_pipeline" "long")       (eq_attr "type" "load4,load8"))  "long_IF,long_E,memory*2");; Expand prologue as RTL(define_expand "prologue"  [(const_int 1)]  ""  "{  m32r_expand_prologue ();  DONE;}");; Move instructions.;;;; For QI and HI moves, the register must contain the full properly;; sign-extended value.  nonzero_bits assumes this [otherwise;; SHORT_IMMEDIATES_SIGN_EXTEND must be used, but the comment for it;; says it's a kludge and the .md files should be fixed instead].(define_expand "movqi"  [(set (match_operand:QI 0 "general_operand" "")	(match_operand:QI 1 "general_operand" ""))]  ""  "{  /* Fixup PIC cases.  */  if (flag_pic)    {      if (symbolic_operand (operands[1], QImode))        {          if (reload_in_progress || reload_completed)            operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]);          else            operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX);        }    }  /* Everything except mem = const or mem = mem can be done easily.     Objects in the small data area are handled too.  */  if (GET_CODE (operands[0]) == MEM)    operands[1] = force_reg (QImode, operands[1]);}")(define_insn "*movqi_insn"  [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,T,m")	(match_operand:QI 1 "move_src_operand" "r,I,JQR,T,m,r,r"))]  "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)"  "@   mv %0,%1   ldi %0,%#%1   ldi %0,%#%1   ldub %0,%1   ldub %0,%1   stb %1,%0   stb %1,%0"  [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4")   (set_attr "length" "2,2,4,2,4,2,4")])(define_expand "movhi"  [(set (match_operand:HI 0 "general_operand" "")	(match_operand:HI 1 "general_operand" ""))]  ""  "{  /* Fixup PIC cases.  */  if (flag_pic)    {      if (symbolic_operand (operands[1], HImode))        {          if (reload_in_progress || reload_completed)            operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]);          else            operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX);        }    }  /* Everything except mem = const or mem = mem can be done easily.  */  if (GET_CODE (operands[0]) == MEM)    operands[1] = force_reg (HImode, operands[1]);}")(define_insn "*movhi_insn"  [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,r,T,m")	(match_operand:HI 1 "move_src_operand" "r,I,JQR,K,T,m,r,r"))]  "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)"  "@   mv %0,%1   ldi %0,%#%1   ldi %0,%#%1   ld24 %0,%#%1   lduh %0,%1   lduh %0,%1   sth %1,%0   sth %1,%0"  [(set_attr "type" "int2,int2,int4,int4,load2,load4,store2,store4")   (set_attr "length" "2,2,4,4,2,4,2,4")])(define_expand "movsi_push"  [(set (mem:SI (pre_dec:SI (match_operand:SI 0 "register_operand" "")))	(match_operand:SI 1 "register_operand" ""))]  ""  "")(define_expand "movsi_pop"  [(set (match_operand:SI 0 "register_operand" "")	(mem:SI (post_inc:SI (match_operand:SI 1 "register_operand" ""))))]  ""  "")(define_expand "movsi"  [(set (match_operand:SI 0 "general_operand" "")	(match_operand:SI 1 "general_operand" ""))]  ""  "{  /* Fixup PIC cases.  */  if (flag_pic)    {      if (symbolic_operand (operands[1], SImode))        {          if (reload_in_progress || reload_completed)            operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]);          else            operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX);        }    }  /* Everything except mem = const or mem = mem can be done easily.  */  if (GET_CODE (operands[0]) == MEM)    operands[1] = force_reg (SImode, operands[1]);  /* Small Data Area reference?  */  if (small_data_operand (operands[1], SImode))    {      emit_insn (gen_movsi_sda (operands[0], operands[1]));      DONE;    }  /* If medium or large code model, symbols have to be loaded with     seth/add3.  */  if (addr32_operand (operands[1], SImode))    {      emit_insn (gen_movsi_addr32 (operands[0], operands[1]));      DONE;    }}");; ??? Do we need a const_double constraint here for large unsigned values?(define_insn "*movsi_insn"  [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,S,m")	(match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))]  "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"  "*{  if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == SUBREG)    {      switch (GET_CODE (operands[1]))	{	  HOST_WIDE_INT value;	  default:	    break;	  case REG:	  case SUBREG:	    return \"mv %0,%1\";	  case MEM:	    if (GET_CODE (XEXP (operands[1], 0)) == POST_INC		&& XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)	      return \"pop %0\";	    return \"ld %0,%1\";	  case CONST_INT:	    value = INTVAL (operands[1]);	    if (INT16_P (value))	      return \"ldi %0,%#%1\\t; %X1\";	    if (UINT24_P (value))	      return \"ld24 %0,%#%1\\t; %X1\";	    if (UPPER16_P (value))	      return \"seth %0,%#%T1\\t; %X1\";	    return \"#\";	  case CONST:	  case SYMBOL_REF:	  case LABEL_REF:	    if (TARGET_ADDR24)	      return \"ld24 %0,%#%1\";	    return \"#\";	}    }  else if (GET_CODE (operands[0]) == MEM	   && (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG))    {      if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC	  && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)	return \"push %1\";      return \"st %1,%0\";    }  abort ();}"  [(set_attr "type" "int2,int2,int4,int4,int4,multi,load2,load2,load4,store2,store2,store4")   (set_attr "length" "2,2,4,4,4,8,2,2,4,2,2,4")]); Try to use a four byte / two byte pair for constants not loadable with; ldi, ld24, seth.(define_split [(set (match_operand:SI 0 "register_operand" "")       (match_operand:SI 1 "two_insn_const_operand" ""))]  ""  [(set (match_dup 0) (match_dup 2))   (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))]  "{  unsigned HOST_WIDE_INT val = INTVAL (operands[1]);  unsigned HOST_WIDE_INT tmp;  int shift;  /* In all cases we will emit two instructions.  However we try to     use 2 byte instructions wherever possible.  We can assume the     constant isn't loadable with any of ldi, ld24, or seth.  */  /* See if we can load a 24 bit unsigned value and invert it.  */  if (UINT24_P (~ val))    {      emit_insn (gen_movsi (operands[0], GEN_INT (~ val)));      emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));      DONE;    }  /* See if we can load a 24 bit unsigned value and shift it into place.     0x01fffffe is just beyond ld24's range.  */  for (shift = 1, tmp = 0x01fffffe;       shift < 8;       ++shift, tmp <<= 1)    {      if ((val & ~tmp) == 0)	{	  emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift)));	  emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift)));	  DONE;	}    }  /* Can't use any two byte insn, fall back to seth/or3.  Use ~0xffff instead     of 0xffff0000, since the later fails on a 64-bit host.  */  operands[2] = GEN_INT ((val) & ~0xffff);  operands[3] = GEN_INT ((val) & 0xffff);}")(define_split  [(set (match_operand:SI 0 "register_operand" "")	(match_operand:SI 1 "seth_add3_operand" ""))]  "TARGET_ADDR32"  [(set (match_dup 0)	(high:SI (match_dup 1)))   (set (match_dup 0)	(lo_sum:SI (match_dup 0)		   (match_dup 1)))]  "")

⌨️ 快捷键说明

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