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

📄 rs6000-pinsn.c

📁 早期freebsd实现
💻 C
字号:
/* Print IBM RS/6000 instructions for GNU software.   Copyright 1991 Free Software Foundation, Inc.   Contributed by IBM Corporation.This file is part of GDB and the GNU binutils.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 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 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; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "defs.h"#include "opcode/rs6k.h"/* Print the rs6k instruction at address MEMADDR in debugged memory,   on STREAM.  Returns length of the instruction, in bytes.  */intprint_insn (memaddr, stream)  CORE_ADDR memaddr;  FILE *stream;{	int  pop, eop, probable_eop;	/* primary and extended opcodes */	int  min, max;	int  best = -1;			/* found best opcode index	*/	int  oldbest = -1;	unsigned int the_insn;	read_memory (memaddr, &the_insn, sizeof (the_insn));	pop = (unsigned)(the_insn >> 26);	min = 0, max = NOPCODES-1;	while (min < max) {	  best = (min + max) / 2;	  /* see if we are running in loops */	  if (best == oldbest)	    goto not_found;	  oldbest = best;	  if (pop < rs6k_ops [best].p_opcode)	    max = best;	  else if (pop > rs6k_ops [best].p_opcode)	    min = best;	  else {	    /* Opcode matched, check extended opcode. */	    if (rs6k_ops [best].e_opcode == -1) {	      /* there is no valid extended opcode, what we've got is		 just fine. */	      goto insn_found;	    }	    /* Largest possible value of extended opcode. */	    probable_eop = ((the_insn) >> 1) & 0x3ff;	    eop = probable_eop & eopMask [rs6k_ops [best].format];	    if (eop < rs6k_ops [best].e_opcode) {	      while (pop == rs6k_ops [best].p_opcode) {		if (eop == rs6k_ops [best].e_opcode)	/* found it! */		  goto insn_found;	        --best;	        eop = probable_eop & eopMask [rs6k_ops [best].format];	      }	      goto not_found;	    }	    else if (eop > rs6k_ops [best].e_opcode) {	      while (pop == rs6k_ops [best].p_opcode) {		if (eop == rs6k_ops [best].e_opcode)	/* found it! */		  goto insn_found;	        ++best;	        eop = probable_eop & eopMask [rs6k_ops [best].format];	      }	      goto not_found;	    }	    else /*  eop == rs6k_ops [best].e_opcode */	      goto insn_found;	  }	}		best = min;	if (pop == rs6k_ops [best].p_opcode &&           (rs6k_ops [best].e_opcode == -1 || rs6k_ops [best].e_opcode == eop))	    goto insn_found;	else	  goto not_found;insn_found:	print_operator (stream, memaddr, the_insn, best);	return 4;not_found:	fprintf (stream, "0x%08x", the_insn);	return 4;}/* condition code names */static char *cond_code [] = {  "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", "nl", "ng", "z", "nz" };print_operator (stream, memaddr, insn_word, insn_no)FILE	*stream;long	memaddr;long	insn_word;int	insn_no;{  char buf [20];  char *qq = buf;  char *pp = rs6k_ops[insn_no].opr_ext;  int tmp;  int nocomma = 0;			/* true if no comma needed */  if (pp) {    while (*pp) {      switch ( *pp ) {	case '.':	  if (insn_word & 0x1)	    *qq++ = '.';	  break;	case 'l':	  if (insn_word & 0x1)	   *qq++ = 'l';	  break;	case 't':	  if ((insn_word & 0x03e00000) == 0x01800000)	   *qq++ = 't';	  break;	case 'f':	  if ((insn_word & 0x03e00000) == 0x00800000)	   *qq++ = 'f';	  break;	case 'a':	  if (insn_word & 0x2)	   *qq++ = 'a';	  break;	case 'o':	  if (insn_word & 0x4000)	   *qq++ = 'o';	  break;	case '1':		/* exception #1 for bb/bc ambiguity */	  tmp = (insn_word >> 21) & 0x1f;	/* extract BO	*/	  if (tmp != 0xc && tmp != 0x4) {	    /* you can't use `bb' now. switch to `bc' */	    *(qq-1) = 'c';	    ++insn_no;	    pp = rs6k_ops[insn_no].opr_ext;	    continue;	  }	  break;	default:	  abort ();      }      ++pp;    }  }  *qq = '\0';  fprintf (stream, "%s%s\t", rs6k_ops[insn_no].operator, buf);  /* parse the operand now. */  pp = rs6k_ops[insn_no].oprnd_format;  while (1) {    switch (*pp) {      case TO	:	fprintf (stream, "%d", (insn_word >> 21) & 0x1f);	break;      case RT	:      case RS	:	fprintf (stream, "r%d", (insn_word >> 21) & 0x1f);	break;      case LI	:	tmp  = (insn_word >> 16) & 0x1f;	if (tmp > 11) {	  fprintf (stream, "{unknown cond code: 0x%x}", insn_word);	  tmp = 0;	}	fprintf (stream, "%s", cond_code [tmp]);	break;      case A2	:      case TA14	:	tmp = (insn_word & 0xfffc);	if (tmp & 0x8000)		/* fix sign extension	*/	  tmp -= 0x10000;	if ((insn_word & 0x2) == 0)	/* if AA not set	*/	  tmp += memaddr;        print_address (tmp, stream);	break;      case TA24	:	tmp = insn_word & 0x03fffffc;	if (tmp & 0x2000000)	  tmp -= 0x4000000;		if ((insn_word & 0x2) == 0)		/* if no AA bit set */	  tmp += memaddr;        print_address (tmp, stream);	break;      case LEV	:			/* for svc only */	if (insn_word & 0x2) {		/* SA is set	*/	  nocomma = 1;	}	else          fprintf (stream, "%d", (insn_word >> 5) & 0x7f);	break;      case FL1	:			/* for svc only */	if (insn_word & 0x2) {		/* SA is set	*/	  nocomma = 1;	}	else          fprintf (stream, "%d", (insn_word >> 12) & 0xf);	break;      case FL2	:			/* for svc only	*/	nocomma = 0;	if (insn_word & 0x2)		/* SA is set	*/	  fprintf (stream, "%d", (insn_word >> 2) & 0x3fff);	else          fprintf (stream, "%d", (insn_word >> 2) & 0x7);	break;      case RA	:	if (nocomma) {	  fprintf (stream, "r%d)", (insn_word >> 16) & 0x1f);	  nocomma = 0;	}	else	  fprintf (stream, "r%d", (insn_word >> 16) & 0x1f);	break;      case RB	:	fprintf (stream, "r%d", (insn_word >> 11) & 0x1f);	break;      case SI	:	tmp = insn_word & 0xffff;	if (tmp & 0x8000)	  tmp -= 0x10000;	fprintf (stream, "%d", tmp);	break;      case UI	:	fprintf (stream, "%d", insn_word & 0xffff);	break;      case BF	:	fprintf (stream, "%d", (insn_word >> 23) & 0x7);	break;      case BFA	:	fprintf (stream, "%d", (insn_word >> 18) & 0x7);	break;      case BT	:	fprintf (stream, "%d", (insn_word >> 21) & 0x1f);	break;      case BA	:	fprintf (stream, "%d", (insn_word >> 16) & 0x1f);	break;      case BB	:	fprintf (stream, "%d", (insn_word >> 11) & 0x1f);	break;      case BO	:	fprintf (stream, "%d", (insn_word >> 21) & 0x1f);	break;      case BI	:	fprintf (stream, "%d", (insn_word >> 16) & 0x1f);	break;      case SH	:	fprintf (stream, "%d", (insn_word >> 11) & 0x1f);	break;      case MB	:	fprintf (stream, "0x%x", (insn_word >> 6) & 0x1f);	break;      case ME	:	fprintf (stream, "0x%x", (insn_word >> 1) & 0x1f);	break;      case SPR	:	fprintf (stream, "%d", (insn_word >> 16) & 0x1f);	break;      case DIS	:	nocomma = 1;	tmp = insn_word & 0xffff;	if (tmp & 0x8000)	  tmp -= 0x10000;	fprintf (stream, "%d(", tmp);	break;      case FXM	:	fprintf (stream, "0x%x", (insn_word >> 12) & 0xff);	break;      case FRT	:      case FRS	:	fprintf (stream, "f%d", (insn_word >> 21) & 0x1f);	break;      case FRA	:	fprintf (stream, "f%d", (insn_word >> 16) & 0x1f);	break;      case FRB	:	fprintf (stream, "f%d", (insn_word >> 11) & 0x1f);	break;      case FRC	:	fprintf (stream, "f%d", (insn_word >> 6) & 0x1f);	break;      case FLM	:	fprintf (stream, "0x%x", (insn_word >> 17) & 0xff);	break;      case NB	:	fprintf (stream, "%d", (insn_word >> 11) & 0x1f);	break;      case I	:	fprintf (stream, "%d", (insn_word >> 12) & 0xf);	break;      default	:	fprintf (stream,		 "{Internal error: Unknown operand format identifier %d}",		 *pp);    }    ++pp;    if (*pp == '\0')      break;    else if (!nocomma)      fputc(',', stream);  }}

⌨️ 快捷键说明

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