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

📄 h8300.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Subroutines for insn-output.c for Hitachi H8/300.   Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.   Contributed by Steve Chamberlain (sac@cygnus.com),   Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include <stdio.h>#include "config.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "expr.h"#include "tree.h"/* Forward declarations.  */void print_operand_address ();char *index ();/* CPU_TYPE, says what cpu we're compiling for.  */int cpu_type;/* True if a #pragma interrupt has been seen for the current function.  */int pragma_interrupt;/* True if a #pragma saveall has been seen for the current function.  */int pragma_saveall;static char *names_big[] ={"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"};static char *names_extended[] ={"er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"};static char *names_upper_extended[] ={"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"};/* Points to one of the above.  *//* ??? The above could be put in an array indexed by CPU_TYPE.  */char **h8_reg_names;/* Various operations needed by the following, indexed by CPU_TYPE.  *//* ??? The h8/300 assembler doesn't understand pop.w (yet).  */static char *h8_push_ops[2] ={"push", "push.l"};static char *h8_pop_ops[2] ={"pop", "pop.l"};static char *h8_mov_ops[2] ={"mov.w", "mov.l"};char *h8_push_op, *h8_pop_op, *h8_mov_op;/* Initialize various cpu specific globals at start up.  */voidh8300_init_once (){  if (TARGET_H8300)    {      cpu_type = (int) CPU_H8300;      h8_reg_names = names_big;    }  else    {      cpu_type = (int) CPU_H8300H;      h8_reg_names = names_extended;    }  h8_push_op = h8_push_ops[cpu_type];  h8_pop_op = h8_pop_ops[cpu_type];  h8_mov_op = h8_mov_ops[cpu_type];}char *byte_reg (x, b)     rtx x;     int b;{  static char *names_small[] =  {"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",   "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7lBAD", "r7hBAD"};  return names_small[REGNO (x) * 2 + b];}/* REGNO must be saved/restored across calls if this macro is true.  */#define WORD_REG_USED(regno)					\  (regno < 7 &&							\   (pragma_interrupt						\    || pragma_saveall						\    || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])	\    || (regs_ever_live[regno] & !call_used_regs[regno])))/* Output assembly language to FILE for the operation OP with operand size   SIZE to adjust the stack pointer.  *//* ??? FPED is currently unused.  */static voiddosize (file, op, size, fped)     FILE *file;     char *op;     unsigned int size;     int fped;{  switch (size)    {    case 4:      /* ??? TARGET_H8300H can do this in one insn.  */    case 3:      fprintf (file, "\t%ss\t#%d,sp\n", op, 2);      size -= 2;      /* Fall through...  */    case 2:    case 1:      fprintf (file, "\t%ss\t#%d,sp\n", op, size);      size = 0;      break;    case 0:      break;    default:      if (TARGET_H8300)	fprintf (file, "\tmov.w\t#%d,r3\n\t%s.w\tr3,sp\n", size, op);      else	fprintf (file, "\t%s\t#%d,sp\n", op, size);      size = 0;      break;    }}/* Output assembly language code for the function prologue.  */static int push_order[FIRST_PSEUDO_REGISTER] ={6, 5, 4, 3, 2, 1, 0, -1, -1};static int pop_order[FIRST_PSEUDO_REGISTER] ={0, 1, 2, 3, 4, 5, 6, -1, -1};/* This is what the stack looks like after the prolog of    a function with a frame has been set up:   <args>   PC   FP			<- fp   <locals>   <saved registers> 	<- sp   This is what the stack looks like after the prolog of   a function which doesn't have a frame:   <args>   PC   <locals>   <saved registers>   	<- sp*/int current_function_anonymous_args;/* Extra arguments to pop, in words (IE: 2 bytes for 300, 4 for 300h */static int extra_pop;voidfunction_prologue (file, size)     FILE *file;     int size;{  register int mask = 0;  int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;  int idx;  extra_pop = 0;  if (current_function_anonymous_args && TARGET_QUICKCALL)    {      /* Push regs as if done by caller, and move around return address.  */      switch (current_function_args_info.nbytes / UNITS_PER_WORD)	{	case 0:	  /* get ret addr */	  fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[1]);	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[0]);	  /* push it again */	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);	  extra_pop = 3;	  break;	case 1:	  /* get ret addr */	  fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[1]);	  /* push it again */	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);	  extra_pop = 2;	  break;	case 2:	  /* get ret addr */	  fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);	  /* push it again */	  fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);	  extra_pop = 1;	  break;	default:	  fprintf (file, "; varargs\n");	  break;	}    }  if (frame_pointer_needed)    {      /* Push fp */      fprintf (file, "\t%s\t%s\n", h8_push_op,	       h8_reg_names[FRAME_POINTER_REGNUM]);      fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,	       h8_reg_names[STACK_POINTER_REGNUM],	       h8_reg_names[FRAME_POINTER_REGNUM]);      /* leave room for locals */      dosize (file, "sub", fsize, 1);      /* Push the rest of the registers */      for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)	{	  int regno = push_order[idx];	  if (regno >= 0 && WORD_REG_USED (regno) && regno != FRAME_POINTER_REGNUM)	    fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);	}    }  else    {      dosize (file, "sub", fsize, 0);      for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)	{	  int regno = push_order[idx];	  if (regno >= 0 && WORD_REG_USED (regno))	    fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);	}    }}/* Output assembly language code for the function epilogue.  */voidfunction_epilogue (file, size)     FILE *file;     int size;{  register int regno;  register int mask = 0;  int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;  int nregs;  int offset;  int idx;  rtx insn = get_last_insn ();  /* If the last insn was a BARRIER, we don't have to write any code.  */  if (GET_CODE (insn) == NOTE)    insn = prev_nonnote_insn (insn);  if (insn && GET_CODE (insn) == BARRIER)    return;  nregs = 0;  if (frame_pointer_needed)    {      /* Pop saved registers */      for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)	{	  regno = pop_order[idx];	  if (regno >= 0 && regno != FRAME_POINTER_REGNUM && WORD_REG_USED (regno))	    fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);	}      /* deallocate locals */      dosize (file, "add", fsize, 1);      /* pop frame pointer */      fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[FRAME_POINTER_REGNUM]);    }  else    {      /* pop saved registers */      for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)	{	  regno = pop_order[idx];	  if (regno >= 0 && WORD_REG_USED (regno))	    fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);	}      /* deallocate locals */      dosize (file, "add", fsize, 0);    }  if (extra_pop)    {      fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);      while (extra_pop)	{	  fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[2]);	  extra_pop--;	}      fprintf (file, "\tjmp	@%s\n", h8_reg_names[3]);    }  else    {      if (pragma_interrupt)	fprintf (file, "\trte\n");      else	fprintf (file, "\trts\n");    }  pragma_interrupt = 0;  pragma_saveall = 0;  current_function_anonymous_args = 0;}/* Output assembly code for the start of the file.  */asm_file_start (file)     FILE *file;{  fprintf (file, ";\tGCC For the Hitachi H8/300\n");  fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n");  fprintf (file, ";\trelease F-1\n");  if (optimize)    fprintf (file, "; -O%d\n", optimize);  if (TARGET_H8300H)    fprintf (file, "\n\t.h8300h\n");  else    fprintf (file, "\n\n");  output_file_directive (file, main_input_filename);}/* Output assembly language code for the end of file.  */voidasm_file_end (file)     FILE *file;{  fprintf (file, "\t.end\n");}/* Return true if VALUE is a valid constant for constraint 'P'.   IE: VALUE is a power of two <= 2**15.  */intsmall_power_of_two (value)     int value;{  switch (value)    {    case 1:    case 2:    case 4:    case 8:    case 16:    case 32:    case 64:    case 128:    case 256:    case 512:    case 1024:    case 2048:    case 4096:    case 8192:    case 16384:    case 32768:      return 1;    }  return 0;}/* Return true if VALUE is a valid constant for constraint 'O', which   means that the constant would be ok to use as a bit for a bclr   instruction.  */intok_for_bclr (value)     int value;{  return small_power_of_two ((~value) & 0xff);}/* Return true is OP is a valid source operand for an integer move   instruction.  */intgeneral_operand_src (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)    return 1;  return general_operand (op, mode);}/* Return true if OP is a valid destination operand for an integer move   instruction.  */intgeneral_operand_dst (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC)    return 1;  return general_operand (op, mode);}/* Return true if OP is a const valid for a bit clear instruction.  */into_operand (operand, mode)     rtx operand;     enum machine_mode mode;{  return (GET_CODE (operand) == CONST_INT	  && CONST_OK_FOR_O (INTVAL (operand)));}/* Return true if OP is a const valid for a bit set or bit xor instruction.  */intp_operand (operand, mode)     rtx operand;     enum machine_mode mode;{  return (GET_CODE (operand) == CONST_INT	  && CONST_OK_FOR_P (INTVAL (operand)));}/* Return true if OP is a valid call operand.  */intcall_insn_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == MEM)    {      rtx inside = XEXP (op, 0);      if (register_operand (inside, Pmode))	return 1;      if (CONSTANT_ADDRESS_P (inside))	return 1;    }  return 0;}/* Return true if OP is a valid jump operand.  */intjump_address_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == REG)    return mode == Pmode;  if (GET_CODE (op) == MEM)    {      rtx inside = XEXP (op, 0);      if (register_operand (inside, Pmode))	return 1;      if (CONSTANT_ADDRESS_P (inside))	return 1;    }  return 0;}/* Recognize valid operands for bitfield instructions.  */extern int rtx_equal_function_value_matters;intbit_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* We can except any general operand, expept that MEM operands must     be limited to those that use addresses valid for the 'U' constraint.  */  if (!general_operand (op, mode))    return 0;  /* Accept any mem during RTL generation.  Otherwise, the code that does     insv and extzv will think that we can not handle memory.  However,     to avoid reload problems, we only accept 'U' MEM operands after RTL     generation.  This means that any named pattern which uses this predicate     must force its operands to match 'U' before emitting RTL.  */

⌨️ 快捷键说明

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