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

📄 disass.c

📁 AT91所有开发板的资料 AT91所有开发板的资料
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * disass.c - single instruction disassembler * Copyright (C) ARM Limited, 1991-1998. All rights reserved. *//* * RCS $Revision: 1.1 $ * Checkin $Date: 1999/03/11 11:53:37 $ * Revising $Author: rivimey $ */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>/* #include "host.h" */#include "disass.h"#include "distool.h"/* ---------------- Local variables ---------------------- */static char const **regnames, **fregnames;static dis_cb *cb_proc;static void *cb_arg;char const *hexprefix = "0x";void Dis_AddNote(char *notes, char const *fmt, ...) {  va_list ap;  va_start(ap, fmt);  if (notes[0] != 0) {    notes += strlen(notes);    strcpy(notes, ", ");    notes += 2;  }  _vsprintf(notes, fmt, ap);  va_end(ap);}void Dis_CheckValue(unsigned32 field, unsigned32 val, char const *s, char *notes) {  if (field != val) Dis_AddNote(notes, "%s = %s%lx", s, hexprefix, field);}void Dis_CheckZero(unsigned32 field, char const *s, char *notes) {  Dis_CheckValue(field, 0, s, notes);}char *Dis_OutF(char *o, char const *fmt, ...) {  va_list ap;  va_start(ap, fmt);  _vsprintf(o, fmt, ap);  va_end(ap);  return o + strlen(o);}char *Dis_OutS(const char *s, char *o) { /* All strings are very short: no point to any cleverness which a library    strcpy might give us.  */    char ch;    for (; (ch = *s++) != 0;)      o = Dis_OutC(ch, o);    return o;}char *Dis_cond(unsigned32 instr, char *o) {    const char *ccnames = "EQ\0\0NE\0\0CS\0\0CC\0\0MI\0\0PL\0\0VS\0\0VC\0\0\HI\0\0LS\0\0GE\0\0LT\0\0GT\0\0LE\0\0\0\0\0\0NV";    return Dis_OutS(ccnames+4*(int)bits(28,31), o);}char *Dis_ArmReg(unsigned32 rno, int ch, char *o) {    if (regnames == NULL)       if (rno == 15)          o = Dis_OutS("pc", o);       else          o = Dis_OutF(o, "r%ld", rno);    else       o = Dis_OutS(regnames[rno], o);    if (ch != 0)       o = Dis_OutC(ch, o);    return o;}static char *FP_Reg(unsigned32 rno, int ch, char *o) {    if (fregnames == NULL)       o = Dis_OutF(o, "f%ld", rno);    else       o = Dis_OutS(fregnames[rno], o);    if (ch != 0)       o = Dis_OutC(ch, o);    return o;}static char *shiftedreg(unsigned32 instr, char *o) {    const char *shiftname = "LSL\0LSR\0ASR\0ROR" + 4*(int)bits(5,6);    o = Dis_ArmReg(bits(0,3), 0, o); /* offset is a (shifted) reg */    if (bit(4)) { /* register shift */       o = Dis_OutF(o, ",%s ", shiftname);       o = Dis_ArmReg(bits(8,11), 0, o);    }    else if (bits(5,11)!=0) { /* immediate shift */       if (bits(5,11)==3)          o = Dis_OutS(",RRX", o);       else {          o = Dis_OutF(o, ",%s ", shiftname);          if (bits(5,11)==1 || bits(5,11)==2)             o = Dis_OutI(32L, o);          else             o = Dis_OutI(bits(7,11), o);       }    }    return o;}static char *outn(unsigned32 n, unsigned32 pos, char *o){    if (!pos) o = Dis_OutC('-', o);    if (n < 10)        o = Dis_OutF(o, "%ld", n);    else        o = Dis_OutX(n, o);    return o;}static char *outh(unsigned32 n, unsigned32 pos, char *o) {    o = Dis_OutC('#', o);    o = outn(n, pos, o);    return o;}char *Dis_spacetocol9(char *start, char *o) {  /* Ensure at least one space output */    int k = 9 - (o - start);    do        o = Dis_OutC(' ', o);    while (--k > 0);    return o;}static char *t_opcode(const char *op, char *o){    char *start = o;    o = Dis_OutS(op, o);    return Dis_spacetocol9(start, o);}char *Dis_ArmOpCode(unsigned32 instr, const char *op, int ch, char *o) {    char *start = o;    o = Dis_OutS(op, o);    o = Dis_cond(instr, o);    if (ch != 0) o = Dis_OutC(ch, o);    return Dis_spacetocol9(start, o);}char *Dis_ArmOpCodeF(char *o, unsigned32 instr, const char *fmt, ...) {  /* fmt is of the form "<string>$<printf-format>", where $ is   * where to insert the condition code   */    va_list ap;    char *start = o;    const char *dollar;    va_start(ap, fmt);    dollar = strchr(fmt, '$');    if (dollar == NULL) return Dis_ArmOpCode(instr, fmt, 0, o);    memcpy(o, fmt, dollar-fmt); /* copy part of string */    o = Dis_cond(instr, o + (dollar-fmt));    _vsprintf(o, dollar+1, ap);    va_end(ap);    return Dis_spacetocol9(start, o+strlen(o));}static char *ArmOutAddress(    unsigned32 instr, unsigned32 address, int32 offset, int w, char *o, bool fromCPDT) {    char *oldo = o;    if (bits(16,19)==15 && bit(24) && !bit(25)) { /* pc based, pre, imm */       if (!bit(23)) offset = -offset;       address = address+offset+8;       if (cb_proc != NULL)          o = cb_proc((bit(20) ? D_LOADPCREL : D_STOREPCREL),                      offset, address, w, cb_arg, o);       if (oldo == o) o = Dis_OutX(address, o);    } else {       if (bit(24) && !bit(25) && cb_proc != NULL) /* pre, imm */          o = cb_proc((bit(20) ? D_LOAD : D_STORE),                      (bit(23) ? offset : -offset),                      bits(16,19), w, cb_arg, o);       if (oldo == o) {          o = Dis_OutC('[', o);          o = Dis_ArmReg(bits(16,19), (bit(24) ? 0 : ']'), o);          o = Dis_OutC(',', o);          if (!bit(25)) { /* offset is an immediate */              /* there's a special case for CPDT's of the 'options' field */              if (fromCPDT && !bit(24) && !bit(21) && bit(23)) {                o = Dis_OutC('{', o);                o = outn(offset/4, bit(23), o);                o = Dis_OutC('}', o);              } else {                  o = outh(offset, bit(23), o);              }          } else {             if (!bit(23)) o = Dis_OutC('-', o);             o = shiftedreg(instr, o);          }          if (bit(24)) {             o = Dis_OutC(']', o);             if (bit(21)) o = Dis_OutC('!', o);          }       }    }    return o;}char *Dis_ArmOutAddress(unsigned32 instr, unsigned32 address, int32 offset, int w, char *o){  return ArmOutAddress(instr, address, offset, w, o, FALSE);}static char *outregset(unsigned32 instr, char *o) {    bool started = NO,         string = NO;    unsigned32 i,               first = 0,               last = 0;    o = Dis_OutC('{', o);    for (i=0; i<16; i++) {       if (bit(i)) {          if (!started) {             o = Dis_ArmReg(i, 0, o);             started=YES;             first=last=i;          }          else if (i==last+1) {             string=YES;             last=i;          }          else {             if (i>last+1 && string) {                o = Dis_OutC((first == last-1) ? ',' : '-', o);                o = Dis_ArmReg(last, 0, o);                string=NO;             }             o = Dis_OutC(',', o); o = Dis_ArmReg(i, 0, o);             first=last=i;          }       }    }    if (string) {       o = Dis_OutC((first == last-1) ? ',' : '-', o);       o = Dis_ArmReg(last, 0, o);    }    o = Dis_OutC('}', o);    return o;}static char *generic_cpdo(int cpno, unsigned32 instr, char *o) {    o = Dis_ArmOpCode(instr, "CDP", 0, o);    o = Dis_OutF(o, "p%d,", cpno);    o = Dis_OutX(bits(20,23), o); o = Dis_OutC(',', o);    o = Dis_OutF(o, "c%ld,", bits(12,15));   /* CRd */    o = Dis_OutF(o, "c%ld,", bits(16,19));   /* CRn */    o = Dis_OutF(o, "c%ld,", bits(0,3));     /* CRm */    o = Dis_OutF(o, "%ld", bits(5,7));    return o;}static char *generic_cprt(int cpno, unsigned32 instr, char *o) {    o = Dis_ArmOpCode(instr, (bit(20) ? "MRC" : "MCR"), 0, o);    o = Dis_OutF(o, "p%d,", cpno);    o = Dis_OutX(bits(21,23), o); o = Dis_OutC(',', o);    o = Dis_ArmReg(bits(12,15), ',', o);    o = Dis_OutF(o, "c%ld,", bits(16,19));   /* CRn */    o = Dis_OutF(o, "c%ld,", bits(0,3));     /* CRm */    o = Dis_OutF(o, "%ld", bits(5,7));    return o;}static char *generic_cpdt(int cpno, unsigned32 instr, unsigned32 address, char *o, char *notes) {    o = Dis_ArmOpCode(instr, (bit(20) ? "LDC" : "STC"), (bit(22) ? 'L' : 0), o);    o = Dis_OutF(o, "p%d,", cpno);    o = Dis_OutF(o, "c%ld,", bits(12,15));    if (!bit(24) && !bit(21)) {      if (bit(23)) {      } else        Dis_AddNote(notes, "Postindexed, Down, no WB");    }    return ArmOutAddress(instr, address, 4*bits(0,7), 0, o, TRUE);}static char *HandleGenericCoPro(int cpno, Disass_CPOpType type, unsigned32 instr, unsigned32 address, char *o, char *notes) {    IGNORE(notes);    switch (type) {    case CP_DP: return generic_cpdo(cpno, instr, o);    case CP_RT: return generic_cprt(cpno, instr, o);    case CP_DT: return generic_cpdt(cpno, instr, address, o, notes);    }    return NULL;  /* can't be reached*/}static char fp_dt_widthname(unsigned32 instr) {    return "SDEP"[bit(15) + 2*bit(22)];}static char fp_widthname(unsigned32 instr) {    return "SDEP"[bit(7) + 2*bit(19)];}static const char *fp_rounding(unsigned32 instr) {    return "\0\0P\0M\0Z" + 2*bits(5,6);}static char *fp_mfield(unsigned32 instr, char *o) {   unsigned32 r = bits(0,2);   if (bit(3)) {      if (r < 6)         o = Dis_OutI(r, o);      else         o = Dis_OutS((r == 6 ? "#0.5" : "#10"), o);   }   else      o = FP_Reg(r, 0, o);   return o;}static char *fp_cpdo(unsigned32 instr, char *o, char *notes) {    const char *opset;    char *start = o;    if (bit(15))  /* unary */        opset = "\MVF\0MNF\0ABS\0RND\0SQT\0LOG\0LGN\0EXP\0\SIN\0COS\0TAN\0ASN\0ACS\0ATN\0URD\0NRM";     else        opset = "\ADF\0MUF\0SUF\0RSF\0DVF\0RDF\0POW\0RPW\0\RMF\0FML\0FDV\0FRD\0POL\0XX1\0XX2\0XX3";    o = Dis_OutS(opset + 4*bits(20,23), o);    o = Dis_cond(instr, o);    o = Dis_OutC(fp_widthname(instr), o);    o = Dis_OutS(fp_rounding(instr), o);    o = Dis_spacetocol9(start, o);    o = FP_Reg(bits(12,14), ',', o);  /* Fd */    if (!bit(15))        o = FP_Reg(bits(16,18), ',', o);  /* Fn */    else if (bits(16,18) != 0)        Dis_CheckZero(bits(16,18), "Fn", notes);    return fp_mfield(instr, o);}static char *fp_cprt(unsigned32 instr, char *o, char *notes) {    int op = (int)bits(20,23);    IGNORE(notes);    if (bits(12,15)==15) {       /* ARM register = pc */        if ((op & 9) != 9) return NULL;  /* Invalid: decode as generic */       else         op = (op>>1)-4;       o = Dis_ArmOpCode(instr, "CMF\0\0CNF\0\0CMFE\0CNFE" + 5*op, 0, o);       o = FP_Reg(bits(16,18), ',', o);       return fp_mfield(instr, o);    } else {       char *start = o;       if (op > 5)         return NULL;       o = Dis_OutS("FLT\0FIX\0WFS\0RFS\0WFC\0RFC" + 4*op, o);       o = Dis_cond(instr, o);       if (op == 0)

⌨️ 快捷键说明

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