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

📄 dis_arm_instr.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 * dis_arm_instr.c
 *
 * Instruction disassebly code for ARM processors.
 * Supports ARM and THUMB instruction sets.
 *
 * by Nick Patavalis (npat@inaccessnetworks.com)
 * 
 * This code was part of libopcodes which was part of GNU binutils.
 * Distributed under the terms of the GNU GPL v2 or latter version.
 * Copyright (C) Free Software Foundation, Inc. 
 * original code:
 *   contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
 *   modifications by James G. Smith (jsmith@cygnus.co.uk)
 *
 * $Id: dis_arm_instr.c,v 2.0 2006/09/22 05:27:20 lxw Exp $
 */

#include "config.h"
extern int printf(char *fmt, ...);

#if INCLUDE_DISASSEMBLER

#include "dis_arm_opcodes.h"

/*************************************************************************/

char dis_arm_instr_cvsid[] = "$Id";

/*************************************************************************/

#define NOTABS

#ifndef NUM_ELEM
#define NUM_ELEM(a)     (sizeof (a) / sizeof (a)[0])
#endif

/*************************************************************************/

static char * arm_conditional[] = {
	"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
	"hi", "ls", "ge", "lt", "gt", "le", "", "nv"
};

typedef struct {
	const char * name;
	const char * description;
	const char * reg_names[16];
} arm_regname;

static arm_regname regnames[] =
{
  { "raw" , "Select raw register names",
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 
	  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
	}
  },
  { "std",  "Select register names used in ARM's ISA documentation",
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 
	  "r8", "r9", "r10", "r11", "r12", "sp",  "lr",  "pc" 
	}
  },
  { "apcs", "Select register names used in the APCS",
    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", 
	  "v5", "v6", "sl",  "fp",  "ip",  "sp",  "lr",  "pc" 
	}
  },
  { "atpcs", "Select register names used in the ATPCS",
    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", 
	  "v5", "v6", "v7",  "v8",  "IP",  "SP",  "LR",  "PC" 
	}
  },
  { "special-atpcs", "Select special register names used in the ATPCS",
    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", 
	  "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" 
	}
  }
};

/* Default to raw register name set.  */
static unsigned int disarm_regname_selected;

#define NUM_ARM_REGNAMES  NUM_ELEM (regnames)
#define arm_regnames      regnames[disarm_regname_selected].reg_names

static char * arm_fp_const[] = {
	"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"
};

static char * arm_shift[] = {
	"lsl", "lsr", "asr", "ror"
};

/*************************************************************************/

static void arm_decode_shift (unsigned long given);

int disarm_print_arm_instr (unsigned long pc, long given);

int disarm_print_thumb_instr (unsigned long pc, long given);

int disarm_get_regname_num_options (void);
int disarm_set_regname_option (int option);
int disarm_get_regnames (int option, const char **setname,
						 const char **setdescription,
						 const char ***register_names);

/*************************************************************************/

int
disarm_get_regname_num_options (void)
{
  return NUM_ARM_REGNAMES;
}

/*************************************************************************/

int
disarm_set_regname_option (int option)
{
  int old = disarm_regname_selected;
  disarm_regname_selected = option;
  return old;
}

/*************************************************************************/

int
disarm_get_regnames (int option, const char **setname,
					 const char **setdescription,
					 const char ***register_names)
{
  *setname = regnames[option].name;
  *setdescription = regnames[option].description;
  *register_names = regnames[option].reg_names;
  return 16;
}

/*************************************************************************/

static void
arm_decode_shift (unsigned long given)
{
  printf( "%s", arm_regnames[given & 0xf]);
  
  if ((given & 0xff0) != 0)
    {
      if ((given & 0x10) == 0)
	{
	  int amount = (given & 0xf80) >> 7;
	  int shift = (given & 0x60) >> 5;
	  
	  if (amount == 0)
	    {
	      if (shift == 3)
		{
		  printf( ", rrx");
		  return;
		}
	      
	      amount = 32;
	    }
	  
	  printf( ", %s #%d", arm_shift[shift], amount);
	}
      else
	printf( ", %s %s", arm_shift[(given & 0x60) >> 5],
	      arm_regnames[(given & 0xf00) >> 8]);
    }
}

/*************************************************************************/

int
disarm_print_arm_instr (unsigned long pc, long given)
{
	struct arm_opcode *  insn;

	for (insn = arm_opcodes; insn->assembler; insn++) {
		if ((given & insn->mask) == insn->value) {
			char * c;
	  
			for (c = insn->assembler; *c; c++) {
				if (*c == '%') {
					switch (*++c) {
					case '%':
						printf( "%%");
						break;

					case 'a':
						if (((given & 0x000f0000) == 0x000f0000)
							&& ((given & 0x02000000) == 0)) {
							int offset = given & 0xfff;
			  
							printf( "[pc");
 
							if (given & 0x01000000) {
								if ((given & 0x00800000) == 0)
									offset = - offset;
							  
								/* pre-indexed */
								printf( ", #%x]", offset);

								offset += pc + 8;

								/* Cope with the possibility of write-back
								   being used.  Probably a dangerous thing
								   for the programmer, but who are we to
								   argue ?  */
								if (given & 0x00200000)
									printf( "!");
							} else {
								/* Post indexed.  */
								printf( "], #%x", offset);

								offset = pc + 8;  /* ie ignore the offset.  */
							}
			  
							printf( " ; ");
#if 0
							info->print_address_func (offset, info);
#else
							printf( "0x%x", offset);
#endif
						} else {
							printf( "[%s", 
								  arm_regnames[(given >> 16) & 0xf]);
							if ((given & 0x01000000) != 0)
							{
								if ((given & 0x02000000) == 0)
								{
									int offset = given & 0xfff;
									if (offset)
										printf( ", %s#%d",
											  (((given & 0x00800000) == 0)
											   ? "-" : ""), offset);
								} else {
									printf( ", %s",
										  (((given & 0x00800000) == 0)
										   ? "-" : ""));
									arm_decode_shift (given);
								}

								printf( "]%s", 
									  ((given & 0x00200000) != 0) ? "!" : "");
							} else {
								if ((given & 0x02000000) == 0) {
									int offset = given & 0xfff;
									if (offset)
										printf( "], %s#%d",
											  (((given & 0x00800000) == 0)
											   ? "-" : ""), offset);
									else 
										printf( "]");
								} else {
									printf( "], %s",
										  (((given & 0x00800000) == 0) 
										   ? "-" : ""));
									arm_decode_shift (given);
								}
							}
						}
						break;

					case 's':
						if ((given & 0x004f0000) == 0x004f0000) {
							/* PC relative with immediate offset.  */
							int offset = ((given & 0xf00) >> 4) 
								| (given & 0xf);
			  
							if ((given & 0x00800000) == 0)
								offset = -offset;
			  
							printf( "[pc, #%x] ; ", offset);
						  
#if 0
							(*info->print_address_func)
								(offset + pc + 8, info);
#else
							printf( "0x%lx", offset + pc + 8);
#endif
						} else {
							printf( "[%s", 
								  arm_regnames[(given >> 16) & 0xf]);
							if ((given & 0x01000000) != 0) {
								/* Pre-indexed.  */
								if ((given & 0x00400000) == 0x00400000) {
									/* Immediate.  */
									int offset = ((given & 0xf00) >> 4) 
										| (given & 0xf);
									if (offset)
										printf( ", %s#%d",
											  (((given & 0x00800000) == 0)
											   ? "-" : ""), offset);
								} else {
									/* Register.  */
									printf( ", %s%s",
										  (((given & 0x00800000) == 0)
										   ? "-" : ""),
										  arm_regnames[given & 0xf]);
								}

								printf( "]%s", 
									  ((given & 0x00200000) != 0) ? "!" : "");
							} else {
								/* Post-indexed.  */
								if ((given & 0x00400000) == 0x00400000) {
									/* Immediate.  */
									int offset = ((given & 0xf00) >> 4) 
										| (given & 0xf);
									if (offset)
										printf( "], %s#%d",
											  (((given & 0x00800000) == 0)
											   ? "-" : ""), offset);
									else 
										printf( "]");
								} else {
									/* Register.  */
									printf( "], %s%s",
										  (((given & 0x00800000) == 0)
										   ? "-" : ""),
										  arm_regnames[given & 0xf]);
								}
							}
						}
						break;
			  
					case 'b':
#if 0
						(*info->print_address_func)
							(BDISP (given) * 4 + pc + 8, info);
#else
						printf( "0x%lx", BDISP (given) * 4 + pc + 8);
#endif
						break;

					case 'c':
						printf( "%s",
							  arm_conditional [(given >> 28) & 0xf]);
						break;

					case 'm':
					{
						int started = 0;
						int reg;

						printf( "{");
						for (reg = 0; reg < 16; reg++)
							if ((given & (1 << reg)) != 0) {
								if (started)
									printf( ", ");
								started = 1;
								printf( "%s", arm_regnames[reg]);
							}
						printf( "}");
					}
					break;

					case 'o':
						if ((given & 0x02000000) != 0) {
							int rotate = (given & 0xf00) >> 7;
							int immed = (given & 0xff);

							immed = (((immed << (32 - rotate))
									  | (immed >> rotate)) & 0xffffffff);
							printf( "#%d ; 0x%x", immed, immed);
						} else
							arm_decode_shift (given);
						break;

					case 'p':
						if ((given & 0x0000f000) == 0x0000f000)
							printf( "p");
						break;

					case 't':
						if ((given & 0x01200000) == 0x00200000)
							printf( "t");
						break;

					case 'h':
						if ((given & 0x00000020) == 0x00000020)
							printf( "h");
						else
							printf( "b");
						break;

					case 'A':
						printf( "[%s", 
							  arm_regnames [(given >> 16) & 0xf]);
						if ((given & 0x01000000) != 0) {
							int offset = given & 0xff;
							if (offset)
								printf( ", %s#%d]%s",
									  ((given & 0x00800000) == 0 ? "-" : ""),
									  offset * 4,
									  ((given & 0x00200000) != 0 ? "!" : ""));
							else
								printf( "]");
						} else {
							int offset = given & 0xff;
							if (offset)
								printf( "], %s#%d",
									  ((given & 0x00800000) == 0 ? "-" : ""),
									  offset * 4);
							else
								printf( "]");
						}
						break;

					case 'C':
						switch (given & 0x000f0000)
						{
						default:
							printf( "_???");
							break;
						case 0x90000:
							printf( "_all");
							break;
						case 0x10000:
							printf( "_c");
							break;
						case 0x20000:
							printf( "_x");
							break;
						case 0x40000:
							printf( "_s");
							break;
						case 0x80000:
							printf( "_f");
							break;
						}
						break;

⌨️ 快捷键说明

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