arc-dis.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,222 行 · 第 1/2 页

C
1,222
字号
/* Instruction printing code for the ARC.   Copyright 1994, 1995, 1997, 1998, 2000, 2001   Free Software Foundation, Inc.   Contributed by Doug Evans (dje@cygnus.com).   This program 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 of the License, or   (at your option) any later version.   This program 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 this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#include <ansidecl.h>#include <libiberty.h>#include "dis-asm.h"#include "opcode/arc.h"#include "elf-bfd.h"#include "elf/arc.h"#include <string.h>#include "opintl.h"#include <ctype.h>#include <stdarg.h>#include "arc-dis.h"#include "arc-ext.h"#ifndef dbg#define dbg (0)#endif#define BIT(word,n) 	((word) & (1 << n))#define BITS(word,s,e)  (((word) << (31 - e)) >> (s + (31 - e))) #define OPCODE(word) 	(BITS ((word), 27, 31))#define FIELDA(word) 	(BITS ((word), 21, 26))#define FIELDB(word) 	(BITS ((word), 15, 20))#define FIELDC(word) 	(BITS ((word),  9, 14))/* FIELD D is signed in all of its uses, so we make sure argument is   treated as signed for bit shifting purposes:  */#define FIELDD(word) 	(BITS (((signed int)word), 0, 8))#define PUT_NEXT_WORD_IN(a)							\  do										\    {										\      if (is_limm == 1 && !NEXT_WORD (1))					\        mwerror (state, _("Illegal limm reference in last instruction!\n"));	\        a = state->words[1];							\    }										\  while (0)#define CHECK_FLAG_COND_NULLIFY()				\  do								\    {								\      if (is_shimm == 0)					\        {							\          flag = BIT (state->words[0], 8);			\          state->nullifyMode = BITS (state->words[0], 5, 6);	\          cond = BITS (state->words[0], 0, 4);			\        }							\    }								\  while (0)#define CHECK_COND()				\  do						\    {						\      if (is_shimm == 0)			\        cond = BITS (state->words[0], 0, 4);	\    }						\  while (0)#define CHECK_FIELD(field)			\  do						\    {						\      if (field == 62)				\        {					\          is_limm++;				\	  field##isReg = 0;			\	  PUT_NEXT_WORD_IN (field);		\	  limm_value = field;			\	}					\      else if (field > 60)			\        {					\	  field##isReg = 0;			\	  is_shimm++;				\	  flag = (field == 61);			\	  field = FIELDD (state->words[0]);	\	}					\    }						\  while (0)#define CHECK_FIELD_A()				\  do						\    {						\      fieldA = FIELDA(state->words[0]);		\      if (fieldA > 60)				\        {					\	  fieldAisReg = 0;			\	  fieldA = 0;				\	}					\    }						\  while (0)#define CHECK_FIELD_B()				\  do						\    {						\      fieldB = FIELDB (state->words[0]);	\      CHECK_FIELD (fieldB);			\    }						\  while (0)#define CHECK_FIELD_C()				\  do						\    {						\      fieldC = FIELDC (state->words[0]);	\      CHECK_FIELD (fieldC);			\    }						\  while (0)#define IS_SMALL(x) (((field##x) < 256) && ((field##x) > -257))#define IS_REG(x)   (field##x##isReg)#define WRITE_FORMAT_LB_Rx_RB(x)     WRITE_FORMAT(x,"[","]","","")#define WRITE_FORMAT_x_COMMA_LB(x)   WRITE_FORMAT(x,"",",[","",",[")#define WRITE_FORMAT_COMMA_x_RB(x)   WRITE_FORMAT(x,",","]",",","]")#define WRITE_FORMAT_x_RB(x)         WRITE_FORMAT(x,"","]","","]")#define WRITE_FORMAT_COMMA_x(x)      WRITE_FORMAT(x,",","",",","")#define WRITE_FORMAT_x_COMMA(x)      WRITE_FORMAT(x,"",",","",",")#define WRITE_FORMAT_x(x)            WRITE_FORMAT(x,"","","","")#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString,		\				     (IS_REG (x) ? cb1"%r"ca1 :		\				      usesAuxReg ? cb"%a"ca :		\				      IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))#define WRITE_FORMAT_RB() 	strcat (formatString, "]")#define WRITE_COMMENT(str)	(state->comm[state->commNum++] = (str))#define WRITE_NOP_COMMENT() 	if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");#define NEXT_WORD(x) 	(offset += 4, state->words[x])#define add_target(x) 	(state->targets[state->tcnt++] = (x))static char comment_prefix[] = "\t; ";static const char *core_reg_name (state, val)     struct arcDisState * state;     int                  val; {  if (state->coreRegName)    return (*state->coreRegName)(state->_this, val);  return 0;}static const char *aux_reg_name (state, val)     struct arcDisState * state;     int                  val; {  if (state->auxRegName)    return (*state->auxRegName)(state->_this, val);  return 0;}static const char *cond_code_name (state, val)     struct arcDisState * state;     int                  val; {  if (state->condCodeName)    return (*state->condCodeName)(state->_this, val);  return 0;}static const char *instruction_name (state, op1, op2, flags)     struct arcDisState * state;     int    op1;     int    op2;     int *  flags; {  if (state->instName)    return (*state->instName)(state->_this, op1, op2, flags);  return 0;}static voidmwerror (state, msg)     struct arcDisState * state;     const char * msg; {  if (state->err != 0)    (*state->err)(state->_this, (msg));}static const char *post_address (state, addr)     struct arcDisState * state;     int addr; {  static char id[3 * ARRAY_SIZE (state->addresses)];  int j, i = state->acnt;  if (i < ((int) ARRAY_SIZE (state->addresses)))    {      state->addresses[i] = addr;      ++state->acnt;      j = i*3;      id[j+0] = '@';      id[j+1] = '0'+i;      id[j+2] = 0;            return id + j;    }  return "";}static void my_sprintf (	    struct arcDisState * state,	    char * buf,	    const char * format,	    ...){  char *bp;   const char *p;  int size, leading_zero, regMap[2];  long auxNum;  va_list ap;    va_start (ap, format);    bp = buf;   *bp = 0;  p = format;  auxNum = -1;  regMap[0] = 0;  regMap[1] = 0;    while (1)     switch (*p++)      {    case 0:      goto DOCOMM; /* (return)  */      default: 	*bp++ = p[-1]; 	break;      case '%':	size = 0;	leading_zero = 0;      RETRY: ;	switch (*p++) 	  {	  case '0':	  case '1':	  case '2':	  case '3':	  case '4':	  case '5':	  case '6':	  case '7':	  case '8':	  case '9':	    {	      /* size.  */	      size = p[-1] - '0';	      if (size == 0)		leading_zero = 1; /* e.g. %08x  */	      while (*p >= '0' && *p <= '9')		{		  size = size * 10 + *p - '0';		  p++;		}	      goto RETRY;	    }#define inc_bp() bp = bp + strlen (bp)	  case 'h': 	    {	      unsigned u = va_arg (ap, int);	      /* Hex.  We can change the format to 0x%08x in		 one place, here, if we wish.		 We add underscores for easy reading.  */	      if (u > 65536) 		sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);	      else 		sprintf (bp, "0x%x", u);	      inc_bp ();	    } 	    break;	  case 'X': case 'x': 	    {	      int val = va_arg (ap, int);	      if (size != 0) 		if (leading_zero)		  sprintf (bp, "%0*x", size, val);		else		  sprintf (bp, "%*x", size, val);	      else		sprintf (bp, "%x", val);	      inc_bp ();	    }	    break;	  case 'd': 	    {	      int val = va_arg (ap, int);	    	      if (size != 0)		sprintf (bp, "%*d", size, val);	      else		sprintf (bp, "%d", val);	      inc_bp ();	    }	    break;	  case 'r': 	    {	      /* Register.  */	      int val = va_arg (ap, int);	    #define REG2NAME(num, name) case num: sprintf (bp, ""name); \  regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;	      	      switch (val) 		{		  REG2NAME (26, "gp");		  REG2NAME (27, "fp");		  REG2NAME (28, "sp");		  REG2NAME (29, "ilink1");		  REG2NAME (30, "ilink2");		  REG2NAME (31, "blink");		  REG2NAME (60, "lp_count");		default:		  {		    const char * ext;		    ext = core_reg_name (state, val);		    if (ext)		      sprintf (bp, "%s", ext);		    else		      sprintf (bp,"r%d",val);		  }		  break;		}	      inc_bp ();	    } break;	  	  case 'a': 	    {	      /* Aux Register.  */	      int val = va_arg (ap, int);#define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;	      switch (val) 		{		  AUXREG2NAME (0x0, "status");		  AUXREG2NAME (0x1, "semaphore");		  AUXREG2NAME (0x2, "lp_start");		  AUXREG2NAME (0x3, "lp_end");		  AUXREG2NAME (0x4, "identity");		  AUXREG2NAME (0x5, "debug");		default:		  {		    const char *ext;		    ext = aux_reg_name (state, val);		    if (ext)		      sprintf (bp, "%s", ext);		    else		      my_sprintf (state, bp, "%h", val);		  }		  break;		}	      inc_bp ();	    }	    break;	    	  case 's': 	    {	      sprintf (bp, "%s", va_arg (ap, char *));	      inc_bp ();	    }	    break;	    	  default:	    fprintf (stderr, "?? format %c\n", p[-1]);	    break;	  }      } DOCOMM: *bp = 0;}static void write_comments_(state, shimm, is_limm, limm_value)     struct arcDisState * state;     int shimm;     int is_limm;     long limm_value;{  if (state->commentBuffer != 0)     {      int i;      if (is_limm) 	{	  const char *name = post_address (state, limm_value + shimm);	  if (*name != 0)	    WRITE_COMMENT (name);	}      for (i = 0; i < state->commNum; i++) 	{	  if (i == 0)	    strcpy (state->commentBuffer, comment_prefix);	  else	    strcat (state->commentBuffer, ", ");		  strncat (state->commentBuffer, state->comm[i], sizeof (state->commentBuffer));	}    }}#define write_comments2(x) write_comments_(state, x, is_limm, limm_value)#define write_comments() write_comments2(0)static const char *condName[] = {  /* 0..15.  */  ""   , "z"  , "nz" , "p"  , "n"  , "c"  , "nc" , "v"  ,   "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"};static void write_instr_name_(state, instrName, cond, condCodeIsPartOfName, flag, signExtend, addrWriteBack, directMem)     struct arcDisState * state;     const char * instrName;     int cond;     int condCodeIsPartOfName;     int flag;     int signExtend;     int addrWriteBack;     int directMem;{  strcpy (state->instrBuffer, instrName);  if (cond > 0)     {      const char *cc = 0;      if (!condCodeIsPartOfName)	strcat (state->instrBuffer, ".");      if (cond < 16)	cc = condName[cond];      else	cc = cond_code_name (state, cond);      if (!cc)	cc = "???";      strcat (state->instrBuffer, cc);    }  if (flag)    strcat (state->instrBuffer, ".f");  switch (state->nullifyMode)     {    case BR_exec_always:      strcat (state->instrBuffer, ".d");      break;    case BR_exec_when_jump:      strcat (state->instrBuffer, ".jd");      break;    }  if (signExtend)    strcat (state->instrBuffer, ".x");  if (addrWriteBack)    strcat (state->instrBuffer, ".a");  if (directMem)    strcat (state->instrBuffer, ".di");}#define write_instr_name()						\  do									\    {									\      write_instr_name_(state, instrName,cond, condCodeIsPartOfName,	\			flag, signExtend, addrWriteBack, directMem);	\      formatString[0] = '\0';						\    }									\  while (0)enum {   op_LD0 = 0, op_LD1 = 1, op_ST  = 2, op_3   = 3,   op_BC  = 4, op_BLC = 5, op_LPC = 6, op_JC  = 7,  op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,   op_AND = 12, op_OR  = 13, op_BIC = 14, op_XOR = 15};extern disassemble_info tm_print_insn_info;static int dsmOneArcInst (addr, state)     bfd_vma              addr;     struct arcDisState * state;{  int condCodeIsPartOfName = 0;  int decodingClass;  const char * instrName;  int repeatsOp = 0;  int fieldAisReg = 1;  int fieldBisReg = 1;  int fieldCisReg = 1;  int fieldA;  int fieldB;  int fieldC = 0;  int flag = 0;  int cond = 0;  int is_shimm = 0;  int is_limm = 0;  long limm_value = 0;  int signExtend = 0;  int addrWriteBack = 0;  int directMem = 0;  int is_linked = 0;  int offset = 0;  int usesAuxReg = 0;  int flags;  int ignoreFirstOpd;  char formatString[60];    state->instructionLen = 4;  state->nullifyMode = BR_exec_when_no_jump;  state->opWidth = 12;  state->isBranch = 0;    state->_mem_load = 0;  state->_ea_present = 0;  state->_load_len = 0;  state->ea_reg1 = no_reg;  state->ea_reg2 = no_reg;  state->_offset = 0;    if (! NEXT_WORD (0))    return 0;    state->_opcode = OPCODE (state->words[0]);  instrName = 0;  decodingClass = 0; /* default!  */  repeatsOp = 0;  condCodeIsPartOfName=0;  state->commNum = 0;  state->tcnt = 0;  state->acnt = 0;  state->flow = noflow;  ignoreFirstOpd = 0;  if (state->commentBuffer)    state->commentBuffer[0] = '\0';  switch (state->_opcode)     {    case op_LD0:       switch (BITS (state->words[0],1,2)) 	{	case 0:	  instrName = "ld";	  state->_load_len = 4;	  break;	case 1:	  instrName = "ldb";	  state->_load_len = 1;	  break;	case 2:	  instrName = "ldw";	  state->_load_len = 2;	  break;	default:	  instrName = "??? (0[3])"; 	  state->flow = invalid_instr;	  break;	}      decodingClass = 5;       break;        case op_LD1:       if (BIT (state->words[0],13)) 	{	  instrName = "lr"; 	  decodingClass = 10;	}      else 	{	  switch (BITS (state->words[0],10,11)) 	    {	    case 0:	      instrName = "ld";	      state->_load_len = 4;	      break;	    case 1:	      instrName = "ldb";	      state->_load_len = 1;	      break;

⌨️ 快捷键说明

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