📄 dis_arm_instr.c
字号:
/* * 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 1.1 2001/03/28 16:30:01 npat Exp $ */#include "config.h"#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_namesstatic 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 (*func)(), void *stream);int disarm_print_arm_instr (unsigned long pc, long given, void *funcA, void *stream);int disarm_print_thumb_instr (unsigned long pc, long given, void *funcA, void *stream);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);/*************************************************************************/intdisarm_get_regname_num_options (void){ return NUM_ARM_REGNAMES;}/*************************************************************************/intdisarm_set_regname_option (int option){ int old = disarm_regname_selected; disarm_regname_selected = option; return old;}/*************************************************************************/intdisarm_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 voidarm_decode_shift (unsigned long given, int (*func)(), void *stream){ func (stream, "%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) { func (stream, ", rrx"); return; } amount = 32; } func (stream, ", %s #%d", arm_shift[shift], amount); } else func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5], arm_regnames[(given & 0xf00) >> 8]); }}/*************************************************************************/intdisarm_print_arm_instr (unsigned long pc, long given, void *funcA, void *stream){ int (*func)() = funcA; 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 '%': func (stream, "%%"); break; case 'a': if (((given & 0x000f0000) == 0x000f0000) && ((given & 0x02000000) == 0)) { int offset = given & 0xfff; func (stream, "[pc"); if (given & 0x01000000) { if ((given & 0x00800000) == 0) offset = - offset; /* pre-indexed */ func (stream, ", #%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) func (stream, "!"); } else { /* Post indexed. */ func (stream, "], #%x", offset); offset = pc + 8; /* ie ignore the offset. */ } func (stream, " ; ");#if 0 info->print_address_func (offset, info);#else func (stream, "0x%x", offset);#endif } else { func (stream, "[%s", arm_regnames[(given >> 16) & 0xf]); if ((given & 0x01000000) != 0) { if ((given & 0x02000000) == 0) { int offset = given & 0xfff; if (offset) func (stream, ", %s#%d", (((given & 0x00800000) == 0) ? "-" : ""), offset); } else { func (stream, ", %s", (((given & 0x00800000) == 0) ? "-" : "")); arm_decode_shift (given, func, stream); } func (stream, "]%s", ((given & 0x00200000) != 0) ? "!" : ""); } else { if ((given & 0x02000000) == 0) { int offset = given & 0xfff; if (offset) func (stream, "], %s#%d", (((given & 0x00800000) == 0) ? "-" : ""), offset); else func (stream, "]"); } else { func (stream, "], %s", (((given & 0x00800000) == 0) ? "-" : "")); arm_decode_shift (given, func, stream); } } } 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; func (stream, "[pc, #%x] ; ", offset); #if 0 (*info->print_address_func) (offset + pc + 8, info);#else func (stream, "0x%x", offset + pc + 8);#endif } else { func (stream, "[%s", arm_regnames[(given >> 16) & 0xf]); if ((given & 0x01000000) != 0) { /* Pre-indexed. */ if ((given & 0x00400000) == 0x00400000) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -