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

📄 h8300.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for Hitachi H8/300.   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000   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 "config.h"#include <stdio.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"#include "obstack.h"/* Forward declarations.  */void print_operand_address ();char *index ();static int h8300_interrupt_function_p PROTO ((tree));static int h8300_monitor_function_p PROTO ((tree));static int h8300_os_task_function_p PROTO ((tree));/* CPU_TYPE, says what cpu we're compiling for.  */int cpu_type;/* True if the current function is an interrupt handler   (either via #pragma or an attribute specification).  */int interrupt_handler;/* True if the current function is an OS Task   (via an attribute specification).  */int os_task;/* True if the current function is a monitor   (via an attribute specification).  */int monitor;/* 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.  */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    {      /* For this we treat the H8/300 and H8/S the same.  */      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", "r7l", "r7h"};  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 &&							\   (interrupt_handler						\    || 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.  */static voiddosize (file, op, size)     FILE *file;     char *op;     unsigned int size;{  /* On the h8300h and h8300s, for sizes <= 8 bytes it is as good or     better to use adds/subs insns rather than add.l/sub.l     with an immediate value.   */  if (size > 4 && size <= 8 && (TARGET_H8300H || TARGET_H8300S))    {      /* Crank the size down to <= 4 */      fprintf (file, "\t%ss\t#%d,sp\n", op, 4);      size -= 4;    }  switch (size)    {    case 4:      if (TARGET_H8300H || TARGET_H8300S)	{	  fprintf (file, "\t%ss\t#%d,sp\n", op, 4);	  size = 0;	  break;	}    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)	{	  if (current_function_needs_context	      && strcmp (op, "sub") == 0)	    {	      /* Egad.  We don't have a temporary to hold the		 size of the frame in the prologue!  Just inline		 the bastard since this shouldn't happen often.  */	      while (size >= 2)		{		  fprintf (file, "\tsubs\t#2,sp\n");		  size -= 2;		}	      if (size)		fprintf (file, "\tsubs\t#1,sp\n");	      size = 0;	    }	  else	    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] ={0, 1, 2, 3, 4, 5, 6, -1, -1, -1};static int pop_order[FIRST_PSEUDO_REGISTER] ={6, 5, 4, 3, 2, 1, 0, -1, -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*/voidfunction_prologue (file, size)     FILE *file;     int size;{  register int mask = 0;  int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;  int idx;  /* Note a function with the interrupt attribute and set interrupt_handler     accordingly.  */  if (h8300_interrupt_function_p (current_function_decl))    interrupt_handler = 1;  /* If the current function has the OS_Task attribute set, then     we have a naked prologue.  */  if (h8300_os_task_function_p (current_function_decl))    {      fprintf (file, ";OS_Task prologue\n");      os_task = 1;      return;    }  if (h8300_monitor_function_p (current_function_decl))    {      /* My understanding of monitor functions is they act just	 like interrupt functions, except the prologue must	 mask interrupts.  */      fprintf (file, ";monitor prologue\n");      interrupt_handler = 1;      monitor = 1;      if (TARGET_H8300)	{	  fprintf (file, "\tsubs\t#2,sp\n");	  fprintf (file, "\tpush\tr0\n");	  fprintf (file, "\tstc\tccr,r0l\n");	  fprintf (file, "\torc\t#128,ccr\n");	  fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");	}      else	{	  fprintf (file, "\tpush\ter0\n");	  fprintf (file, "\tstc\tccr,r0l\n");	  fprintf (file, "\torc\t#128,ccr\n");	  fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");	}    }  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);  /* 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)	  && (!frame_pointer_needed || regno != FRAME_POINTER_REGNUM))	{	  if (TARGET_H8300S)	    {	      /* Try to push multiple registers.  */	      if (regno == 0 || regno == 4)		{		  int second_regno = push_order[idx + 1];		  int third_regno = push_order[idx + 2];		  int fourth_regno = push_order[idx + 3];		  if (fourth_regno >= 0		      && WORD_REG_USED (fourth_regno)		      && (!frame_pointer_needed			  || fourth_regno != FRAME_POINTER_REGNUM)		      && third_regno >= 0		      && WORD_REG_USED (third_regno)		      && (!frame_pointer_needed			  || third_regno != FRAME_POINTER_REGNUM)		      && second_regno >= 0		      && WORD_REG_USED (second_regno)		      && (!frame_pointer_needed			  || second_regno != FRAME_POINTER_REGNUM))		    {		      fprintf (file, "\tstm.l %s-%s,@-sp\n", 			       h8_reg_names[regno],			       h8_reg_names[fourth_regno]);		      idx += 3;		      continue;		    }		}	      if (regno == 0 || regno == 4)		{		  int second_regno = push_order[idx + 1];		  int third_regno = push_order[idx + 2];		  if (third_regno >= 0		      && WORD_REG_USED (third_regno)		      && (!frame_pointer_needed			  || third_regno != FRAME_POINTER_REGNUM)		      && second_regno >= 0		      && WORD_REG_USED (second_regno)		      && (!frame_pointer_needed			  || second_regno != FRAME_POINTER_REGNUM))		    {		      fprintf (file, "\tstm.l %s-%s,@-sp\n", 			       h8_reg_names[regno],			       h8_reg_names[third_regno]);		      idx += 2;		      continue;		    }		}	      if (regno == 0 || regno == 2 || regno == 4 || regno == 6)		{		  int second_regno = push_order[idx + 1];		  if (second_regno >= 0		      && WORD_REG_USED (second_regno)		      && (!frame_pointer_needed			  || second_regno != FRAME_POINTER_REGNUM))		    {		      fprintf (file, "\tstm.l %s-%s,@-sp\n", 			       h8_reg_names[regno],			       h8_reg_names[second_regno]);		      idx += 1;		      continue;		    }		}	    }	  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 idx;  rtx insn = get_last_insn ();  if (os_task)    {      /* OS_Task epilogues are nearly naked -- they just have an	 rts instruction.  */      fprintf (file, ";OS_task epilogue\n");      fprintf (file, "\trts\n");      goto out;    }  /* monitor epilogues are the same as interrupt function epilogues.     Just make a note that we're in an monitor epilogue.  */  if (monitor)    fprintf(file, ";monitor epilogue\n");  /* 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)    goto out;  /* Pop the saved registers. */  for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)    {      int regno = pop_order[idx];      if (regno >= 0	  && WORD_REG_USED (regno)	  && (!frame_pointer_needed || regno != FRAME_POINTER_REGNUM))	{	  if (TARGET_H8300S)	    {	      /* Try to pop multiple registers.  */	      if (regno == 7 || regno == 3)		{		  int second_regno = pop_order[idx + 1];		  int third_regno = pop_order[idx + 2];		  int fourth_regno = pop_order[idx + 3];		  if (fourth_regno >= 0		      && WORD_REG_USED (fourth_regno)		      && (!frame_pointer_needed			  || fourth_regno != FRAME_POINTER_REGNUM)		      && third_regno >= 0		      && WORD_REG_USED (third_regno)		      && (!frame_pointer_needed			  || third_regno != FRAME_POINTER_REGNUM)		      && second_regno >= 0		      && WORD_REG_USED (second_regno)		      && (!frame_pointer_needed			  || second_regno != FRAME_POINTER_REGNUM))		    {		      fprintf (file, "\tldm.l @sp+,%s-%s\n", 			       h8_reg_names[fourth_regno],			       h8_reg_names[regno]);		      idx += 3;		      continue;		    }		}	      if (regno == 6 || regno == 2)		{		  int second_regno = pop_order[idx + 1];		  int third_regno = pop_order[idx + 2];		  if (third_regno >= 0		      && WORD_REG_USED (third_regno)		      && (!frame_pointer_needed			  || third_regno != FRAME_POINTER_REGNUM)		      && second_regno >= 0		      && WORD_REG_USED (second_regno)		      && (!frame_pointer_needed			  || second_regno != FRAME_POINTER_REGNUM))		    {		      fprintf (file, "\tldm.l @sp+,%s-%s\n", 			       h8_reg_names[third_regno],			       h8_reg_names[regno]);		      idx += 2;		      continue;		    }		}	      if (regno == 7 || regno == 5 || regno == 3 || regno == 1)		{		  int second_regno = pop_order[idx + 1];		  if (second_regno >= 0		      && WORD_REG_USED (second_regno)		      && (!frame_pointer_needed			  || second_regno != FRAME_POINTER_REGNUM))		    {		      fprintf (file, "\tldm.l @sp+,%s-%s\n", 			       h8_reg_names[second_regno],			       h8_reg_names[regno]);		      idx += 1;		      continue;		    }		}	    }	  fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);	}    }  /* deallocate locals */  dosize (file, "add", fsize);  /* pop frame pointer if we had one. */  if (frame_pointer_needed)    fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[FRAME_POINTER_REGNUM]);  /* If this is a monitor function, there is one register still left on     the stack.  */  if (monitor)    fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[0]);  if (interrupt_handler)    fprintf (file, "\trte\n");  else    fprintf (file, "\trts\n");out:  interrupt_handler = 0;  os_task = 0;  monitor = 0;

⌨️ 快捷键说明

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