i960-dis.c

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

C
917
字号
/* Disassemble i80960 instructions.   Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000   Free Software Foundation, Inc.This program 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.This program 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 this program; see the file COPYING.  If not, write to theFree Software Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA.  */#include "sysdep.h"#include "dis-asm.h"static const char *const reg_names[] = {/*  0 */	"pfp", "sp",  "rip", "r3",  "r4",  "r5",  "r6",  "r7", /*  8 */	"r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",/* 16 */	"g0",  "g1",  "g2",  "g3",  "g4",  "g5",  "g6",  "g7", /* 24 */	"g8",  "g9",  "g10", "g11", "g12", "g13", "g14", "fp", /* 32 */	"pc",  "ac",  "ip",  "tc",  "fp0", "fp1", "fp2", "fp3" };static FILE *stream;		/* Output goes here */static struct disassemble_info *info;static void print_addr();static void ctrl();static void cobr();static void reg();static int mem();static void ea();static void dstop();static void regop();static void invalid();static int pinsn();static void put_abs();/* Print the i960 instruction at address 'memaddr' in debugged memory,   on INFO->STREAM.  Returns length of the instruction, in bytes.  */intprint_insn_i960 (memaddr, info_arg)    bfd_vma memaddr;    struct disassemble_info *info_arg;{  unsigned int word1, word2 = 0xdeadbeef;  bfd_byte buffer[8];  int status;  info = info_arg;  stream = info->stream;  /* Read word1.  Only read word2 if the instruction     needs it, to prevent reading past the end of a section.  */  status = (*info->read_memory_func) (memaddr, (bfd_byte *) buffer, 4, info);  if (status != 0)    {      (*info->memory_error_func) (status, memaddr, info);      return -1;    }  word1 = bfd_getl32 (buffer);  /* Divide instruction set into classes based on high 4 bits of opcode.  */  switch ( (word1 >> 28) & 0xf )    {    default:      break;    case 0x8:    case 0x9:    case 0xa:    case 0xb:    case 0xc:      /* Read word2.  */      status = (*info->read_memory_func)	(memaddr + 4, (bfd_byte *) (buffer + 4), 4, info);      if (status != 0)	{	  (*info->memory_error_func) (status, memaddr, info);	  return -1;	}      word2 = bfd_getl32 (buffer + 4);      break;    }  return pinsn( memaddr, word1, word2 );}#define IN_GDB/***************************************************************************** *	All code below this point should be identical with that of *	the disassembler in gdmp960. A noble sentiment, but at least in cosmetic ways (info->fprintf_func), it just ain't so. -kingdon, 31 Mar 93 *****************************************************************************/struct tabent {  char *name;  short numops;};struct sparse_tabent {  int opcode;  char *name;  short numops;};static intpinsn( memaddr, word1, word2 )    bfd_vma memaddr;    unsigned long word1, word2;{	int instr_len;	instr_len = 4;	put_abs( word1, word2 );	/* Divide instruction set into classes based on high 4 bits of opcode*/	switch ( (word1 >> 28) & 0xf ){	case 0x0:	case 0x1:		ctrl( memaddr, word1, word2 );		break;	case 0x2:	case 0x3:		cobr( memaddr, word1, word2 );		break;	case 0x5:	case 0x6:	case 0x7:		reg( word1 );		break;	case 0x8:	case 0x9:	case 0xa:	case 0xb:	case 0xc:		instr_len = mem( memaddr, word1, word2, 0 );		break;	default:		/* invalid instruction, print as data word */ 		invalid( word1 );		break;	}	return instr_len;}/****************************************//* CTRL format				*//****************************************/static voidctrl( memaddr, word1, word2 )    bfd_vma memaddr;    unsigned long word1, word2;{	int i;	static const struct tabent ctrl_tab[] = {	  { NULL,		0, },	/* 0x00 */	  { NULL,		0, },	/* 0x01 */	  { NULL,		0, },	/* 0x02 */	  { NULL,		0, },	/* 0x03 */	  { NULL,		0, },	/* 0x04 */	  { NULL,		0, },	/* 0x05 */	  { NULL,		0, },	/* 0x06 */	  { NULL,		0, },	/* 0x07 */	  { "b",		1, },	/* 0x08 */	  { "call",		1, },	/* 0x09 */	  { "ret",		0, },	/* 0x0a */	  { "bal",		1, },	/* 0x0b */	  { NULL,		0, },	/* 0x0c */	  { NULL,		0, },	/* 0x0d */	  { NULL,		0, },	/* 0x0e */	  { NULL,		0, },	/* 0x0f */	  { "bno",		1, },	/* 0x10 */	  { "bg",		1, },	/* 0x11 */	  { "be",		1, },	/* 0x12 */	  { "bge",		1, },	/* 0x13 */	  { "bl",		1, },	/* 0x14 */	  { "bne",		1, },	/* 0x15 */	  { "ble",		1, },	/* 0x16 */	  { "bo",		1, },	/* 0x17 */	  { "faultno",		0, },	/* 0x18 */	  { "faultg",		0, },	/* 0x19 */	  { "faulte",		0, },	/* 0x1a */	  { "faultge",		0, },	/* 0x1b */	  { "faultl",		0, },	/* 0x1c */	  { "faultne",		0, },	/* 0x1d */	  { "faultle",		0, },	/* 0x1e */	  { "faulto",		0, },	/* 0x1f */	};	i = (word1 >> 24) & 0xff;	if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){		invalid( word1 );		return;	}	(*info->fprintf_func) ( stream, ctrl_tab[i].name );	if ( word1 & 2 ){		/* Predicts branch not taken */		(*info->fprintf_func) ( stream, ".f" );	}	if ( ctrl_tab[i].numops == 1 ){		/* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */		word1 &= 0x00ffffff;		if ( word1 & 0x00800000 ){		/* Sign bit is set */			word1 |= (-1 & ~0xffffff);	/* Sign extend */		}		(*info->fprintf_func)( stream, "\t" );		print_addr( word1 + memaddr );	}}/****************************************//* COBR format				*//****************************************/static voidcobr( memaddr, word1, word2 )    bfd_vma memaddr;    unsigned long word1, word2;{	int src1;	int src2;	int i;	static const struct tabent cobr_tab[] = {	  { "testno",	1, },	/* 0x20 */	  { "testg",	1, },	/* 0x21 */	  { "teste",	1, },	/* 0x22 */	  { "testge",	1, },	/* 0x23 */	  { "testl",	1, },	/* 0x24 */	  { "testne",	1, },	/* 0x25 */	  { "testle",	1, },	/* 0x26 */	  { "testo",	1, },	/* 0x27 */	  { NULL,	0, },	/* 0x28 */	  { NULL,	0, },	/* 0x29 */	  { NULL,	0, },	/* 0x2a */	  { NULL,	0, },	/* 0x2b */	  { NULL,	0, },	/* 0x2c */	  { NULL,	0, },	/* 0x2d */	  { NULL,	0, },	/* 0x2e */	  { NULL,	0, },	/* 0x2f */	  { "bbc",	3, },	/* 0x30 */	  { "cmpobg",	3, },	/* 0x31 */	  { "cmpobe",	3, },	/* 0x32 */	  { "cmpobge",	3, },	/* 0x33 */	  { "cmpobl",	3, },	/* 0x34 */	  { "cmpobne",	3, },	/* 0x35 */	  { "cmpoble",	3, },	/* 0x36 */	  { "bbs",	3, },	/* 0x37 */	  { "cmpibno",	3, },	/* 0x38 */	  { "cmpibg",	3, },	/* 0x39 */	  { "cmpibe",	3, },	/* 0x3a */	  { "cmpibge",	3, },	/* 0x3b */	  { "cmpibl",	3, },	/* 0x3c */	  { "cmpibne",	3, },	/* 0x3d */	  { "cmpible",	3, },	/* 0x3e */	  { "cmpibo",	3, },	/* 0x3f */	};	i = ((word1 >> 24) & 0xff) - 0x20;	if ( cobr_tab[i].name == NULL ){		invalid( word1 );		return;	}	(*info->fprintf_func) ( stream, cobr_tab[i].name );	if ( word1 & 2 ){		/* Predicts branch not taken */		(*info->fprintf_func) ( stream, ".f" );	}	(*info->fprintf_func)( stream, "\t" );	src1 = (word1 >> 19) & 0x1f;	src2 = (word1 >> 14) & 0x1f;	if ( word1 & 0x02000 ){		/* M1 is 1 */		(*info->fprintf_func)( stream, "%d", src1 );	} else {			/* M1 is 0 */		(*info->fprintf_func)( stream, reg_names[src1] );	}	if ( cobr_tab[i].numops > 1 ){		if ( word1 & 1 ){		/* S2 is 1 */			(*info->fprintf_func)( stream, ",sf%d,", src2 );		} else {			/* S1 is 0 */			(*info->fprintf_func)( stream, ",%s,", reg_names[src2] );		}		/* Extract displacement and convert to address		 */		word1 &= 0x00001ffc;		if ( word1 & 0x00001000 ){	/* Negative displacement */			word1 |= (-1 & ~0x1fff);	/* Sign extend */		}		print_addr( memaddr + word1 );	}}/****************************************//* MEM format				*//****************************************/static int				/* returns instruction length: 4 or 8 */mem( memaddr, word1, word2, noprint )    bfd_vma memaddr;    unsigned long word1, word2;    int noprint;		/* If TRUE, return instruction length, but				 * don't output any text.				 */{	int i, j;	int len;	int mode;	int offset;	const char *reg1, *reg2, *reg3;	/* This lookup table is too sparse to make it worth typing in, but not	   so large as to make a sparse array necessary.  We create the table	   at runtime.  */	/*	 * NOTE: In this table, the meaning of 'numops' is:	 *	 1: single operand	 *	 2: 2 operands, load instruction	 *	-2: 2 operands, store instruction	 */	static struct tabent *mem_tab;/* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table.  */#define MEM_MIN	0x80#define MEM_MAX	0xcf#define MEM_SIZ	( * sizeof(struct tabent))	static const struct sparse_tabent mem_init[] = {	  { 0x80,	"ldob",	 2 },	  { 0x82,	"stob",	-2 },	  { 0x84,	"bx",	 1 },	  { 0x85,	"balx",	 2 },	  { 0x86,	"callx", 1 },	  { 0x88,	"ldos",	 2 },	  { 0x8a,	"stos",	-2 },	  { 0x8c,	"lda",	 2 },	  { 0x90,	"ld",	 2 },	  { 0x92,	"st",	-2 },	  { 0x98,	"ldl",	 2 },	  { 0x9a,	"stl",	-2 },	  { 0xa0,	"ldt",	 2 },	  { 0xa2,	"stt",	-2 },	  { 0xac,	"dcinva", 1 },	  { 0xb0,	"ldq",	 2 },	  { 0xb2,	"stq",	-2 },	  { 0xc0,	"ldib",	 2 },	  { 0xc2,	"stib",	-2 },	  { 0xc8,	"ldis",	 2 },	  { 0xca,	"stis",	-2 },	  { 0,		NULL,	0 }	};	static struct tabent mem_tab_buf[MEM_MAX - MEM_MIN + 1];	if ( mem_tab == NULL ){		mem_tab = mem_tab_buf;		for ( i = 0; mem_init[i].opcode != 0; i++ ){			j = mem_init[i].opcode - MEM_MIN;			mem_tab[j].name = mem_init[i].name;			mem_tab[j].numops = mem_init[i].numops;		}	}	i = ((word1 >> 24) & 0xff) - MEM_MIN;	mode = (word1 >> 10) & 0xf;	if ( (mem_tab[i].name != NULL)		/* Valid instruction */	&&   ((mode == 5) || (mode >=12)) ){	/* With 32-bit displacement */		len = 8;	} else {		len = 4;	}	if ( noprint ){		return len;	}	if ( (mem_tab[i].name == NULL) || (mode == 6) ){		invalid( word1 );		return len;	}	(*info->fprintf_func)( stream, "%s\t", mem_tab[i].name );	reg1 = reg_names[ (word1 >> 19) & 0x1f ];	/* MEMB only */	reg2 = reg_names[ (word1 >> 14) & 0x1f ];	reg3 = reg_names[ word1 & 0x1f ];		/* MEMB only */	offset = word1 & 0xfff;				/* MEMA only  */	switch ( mem_tab[i].numops ){	case 2: /* LOAD INSTRUCTION */		if ( mode & 4 ){			/* MEMB FORMAT */			ea( memaddr, mode, reg2, reg3, word1, word2 );			(*info->fprintf_func)( stream, ",%s", reg1 );		} else {				/* MEMA FORMAT */			(*info->fprintf_func)( stream, "0x%x", (unsigned) offset );			if (mode & 8) {				(*info->fprintf_func)( stream, "(%s)", reg2 );			}			(*info->fprintf_func)( stream, ",%s", reg1 );		}		break;	case -2: /* STORE INSTRUCTION */		if ( mode & 4 ){			/* MEMB FORMAT */			(*info->fprintf_func)( stream, "%s,", reg1 );			ea( memaddr, mode, reg2, reg3, word1, word2 );		} else {				/* MEMA FORMAT */			(*info->fprintf_func)( stream, "%s,0x%x", reg1, (unsigned) offset );			if (mode & 8) {				(*info->fprintf_func)( stream, "(%s)", reg2 );			}		}		break;	case 1: /* BX/CALLX INSTRUCTION */		if ( mode & 4 ){			/* MEMB FORMAT */			ea( memaddr, mode, reg2, reg3, word1, word2 );		} else {				/* MEMA FORMAT */			(*info->fprintf_func)( stream, "0x%x", (unsigned) offset );			if (mode & 8) {				(*info->fprintf_func)( stream, "(%s)", reg2 );			}		}		break;	}	return len;}/****************************************//* REG format				*//****************************************/static voidreg( word1 )    unsigned long word1;{	int i, j;	int opcode;	int fp;	int m1, m2, m3;	int s1, s2;	int src, src2, dst;

⌨️ 快捷键说明

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