mirror of
https://github.com/avrdudes/avrdude.git
synced 2026-09-24 01:56:25 +03:00
Consolidate CodeLabel, PGMLabel, MemLabel and IO_Register into one symbols struct
This commit is contained in:
98
src/disasm.c
98
src/disasm.c
@@ -21,7 +21,6 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -98,9 +97,14 @@ static unsigned bitcount(unsigned n) {
|
||||
}
|
||||
|
||||
void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo, Disasm_line *line, int pass) {
|
||||
const AVR_opcode_data *oc = avr_opcodes+mnemo;
|
||||
memset(line, 0, sizeof*line);
|
||||
if(mnemo < 0) {
|
||||
add_comment(line, "Invalid opcode");
|
||||
snprintf(line->code, 256, ".word 0x%02x%02x", buf[1] & 0xff, buf[0] & 0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
const AVR_opcode_data *oc = avr_opcodes+mnemo;
|
||||
int regs[128] = {0}, bits[128] = {0};
|
||||
unsigned bmask = 0x8000;
|
||||
for(const char *p = oc->bits; *p && bmask; p++) {
|
||||
@@ -178,7 +182,6 @@ void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo, Disasm
|
||||
int awd = cx->dis_addrwidth, swd = cx->dis_sramwidth;
|
||||
snprintf(line->code, 256, "%-7s ", oc->opcode);
|
||||
char *c = line->code + strlen(line->code);
|
||||
*line->comment = 0;
|
||||
|
||||
// Check for opcodes with undefined results
|
||||
switch(oc->type & OTY_WARN_MASK) {
|
||||
@@ -309,81 +312,66 @@ void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo, Disasm
|
||||
* After the location buf+readlen there are leadout bytes available (0 -4)
|
||||
*/
|
||||
int disasm(const char *buf, int buflen, int addr, int leadin, int leadout) {
|
||||
int Pos;
|
||||
int opcode, mnemo, oplen;
|
||||
int i;
|
||||
int pos, opcode, mnemo, oplen;
|
||||
Disasm_line line;
|
||||
int awd = cx->dis_addrwidth;
|
||||
|
||||
Pos = 0;
|
||||
|
||||
for(int i = 0; i < cx->dis_IORegisterN; i++)
|
||||
cx->dis_IORegisters[i].used = 0;
|
||||
pos = 0;
|
||||
for(int i = 0; i < cx->dis_symbolN; i++)
|
||||
if(cx->dis_symbols[i].type == 'I')
|
||||
cx->dis_symbols[i].used = 0;
|
||||
|
||||
if(cx->dis_opts.Process_Labels || cx->dis_opts.avrgcc_style) {
|
||||
// Preprocess to gather jump labels or to gain knowledge about registers which are being used
|
||||
while(Pos < buflen) {
|
||||
opcode = (buf[Pos] & 0xff) | (buf[Pos+1] & 0xff)<<8;
|
||||
while(pos < buflen) {
|
||||
opcode = (buf[pos] & 0xff) | (buf[pos+1] & 0xff)<<8;
|
||||
mnemo = opcode_mnemo(opcode, cx->dis_opts.avrlevel);
|
||||
oplen = 2*avr_opcodes[mnemo].nwords;
|
||||
if(mnemo == -1) {
|
||||
Pos += 2;
|
||||
} else {
|
||||
disassemble(buf + Pos, disasm_wrap(Pos + addr), opcode, mnemo, &line, 1);
|
||||
Pos += oplen;
|
||||
}
|
||||
disassemble(buf + pos, disasm_wrap(pos + addr), opcode, mnemo, &line, 1);
|
||||
pos += mnemo < 0? 2: 2*avr_opcodes[mnemo].nwords;
|
||||
}
|
||||
Enumerate_Labels();
|
||||
Pos = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
if(cx->dis_opts.avrgcc_style)
|
||||
Emit_Used_IO_Registers();
|
||||
|
||||
while(Pos < buflen) {
|
||||
while(pos < buflen) {
|
||||
// Check if this is actually code or maybe only data from tagfile
|
||||
int Added = Tagfile_Process_Data(buf, Pos, addr);
|
||||
if(Added) {
|
||||
Pos += Added;
|
||||
int added = Tagfile_Process_Data(buf, pos, addr);
|
||||
if(added) {
|
||||
pos += added;
|
||||
continue;
|
||||
}
|
||||
|
||||
opcode = (buf[Pos] & 0xff) | (buf[Pos+1] & 0xff)<<8;
|
||||
opcode = (buf[pos] & 0xff) | (buf[pos+1] & 0xff)<<8;
|
||||
mnemo = opcode_mnemo(opcode, cx->dis_opts.avrlevel);
|
||||
oplen = 2*avr_opcodes[mnemo].nwords;
|
||||
oplen = mnemo < 0? 2: 2*avr_opcodes[mnemo].nwords;
|
||||
|
||||
if(mnemo != -1) {
|
||||
disassemble(buf + Pos, disasm_wrap(Pos + addr), opcode, mnemo, &line, 2);
|
||||
disassemble(buf + pos, disasm_wrap(pos + addr), opcode, mnemo, &line, 2);
|
||||
|
||||
if(cx->dis_opts.Process_Labels)
|
||||
Print_JumpCalls(disasm_wrap(Pos + addr));
|
||||
if(cx->dis_opts.Process_Labels)
|
||||
Print_JumpCalls(disasm_wrap(pos + addr));
|
||||
|
||||
if(cx->dis_opts.Show_Addresses)
|
||||
term_out("%4x: ", disasm_wrap(Pos + addr));
|
||||
if(cx->dis_opts.Show_Cycles)
|
||||
term_out("[%-3s] ", avr_opcodes[mnemo].clock[cx->dis_cycle_index]);
|
||||
if(cx->dis_opts.Show_Addresses)
|
||||
term_out("%*x: ", awd, disasm_wrap(pos + addr));
|
||||
if(cx->dis_opts.Show_Cycles)
|
||||
term_out("[%-3s] ", mnemo < 0? "---": avr_opcodes[mnemo].clock[cx->dis_cycle_index]);
|
||||
|
||||
if(cx->dis_opts.Show_Opcodes) {
|
||||
// Now display the Opcode
|
||||
for(i = 0; i < oplen; i++)
|
||||
term_out("%02x ", buf[Pos + i] & 0xff);
|
||||
term_out(" ");
|
||||
for(i = 0; i < 5 - oplen; i++)
|
||||
term_out(" ");
|
||||
}
|
||||
|
||||
if(!*line.comment || !cx->dis_opts.Show_Comments)
|
||||
term_out("%s\n", line.code);
|
||||
else
|
||||
term_out("%-23s ; %s\n", line.code, line.comment);
|
||||
if(mnemo == OPCODE_ret || mnemo == OPCODE_u_ret || mnemo == OPCODE_ret || mnemo == OPCODE_u_ret)
|
||||
term_out("\n");
|
||||
|
||||
Pos += oplen;
|
||||
} else {
|
||||
term_out("%-23s ; Invalid opcode\n",
|
||||
str_ccprintf(".word 0x%02x%02x", buf[Pos+1] & 0xff, buf[Pos] & 0xff));
|
||||
Pos += 2;
|
||||
if(cx->dis_opts.Show_Opcodes) {
|
||||
for(int i = 0; i < 5; i++)
|
||||
term_out(i < oplen? "%02x ": " ", buf[pos + i] & 0xff);
|
||||
term_out(" ");
|
||||
}
|
||||
|
||||
if(!*line.comment || !cx->dis_opts.Show_Comments)
|
||||
term_out("%s\n", line.code);
|
||||
else
|
||||
term_out("%-23s ; %s\n", line.code, line.comment);
|
||||
if(mnemo == OPCODE_ret || mnemo == OPCODE_u_ret || mnemo == OPCODE_ret || mnemo == OPCODE_u_ret)
|
||||
term_out("\n");
|
||||
|
||||
pos += oplen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -127,21 +127,19 @@ void Enumerate_Labels(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const char *Get_Label_Name(int Destination, char **LabelComment) {
|
||||
int TagIndex;
|
||||
|
||||
TagIndex = Tagfile_FindLabelAddress(Destination);
|
||||
if(TagIndex != -1) {
|
||||
if(LabelComment)
|
||||
*LabelComment = Tagfile_GetLabelComment(TagIndex);
|
||||
return str_ccprintf("%s", Tagfile_GetLabel(TagIndex));
|
||||
const char *Get_Label_Name(int destination, char **comment) {
|
||||
int index = disasm_find_symbol('L', destination);
|
||||
if(index >= 0) {
|
||||
if(comment)
|
||||
*comment = Tagfile_GetLabelComment(index);
|
||||
return str_ccprintf("%s", Tagfile_GetLabel(index));
|
||||
}
|
||||
|
||||
for(int i = 0; i < cx->dis_JumpCallN; i++)
|
||||
if(cx->dis_JumpCalls[i].To == Destination)
|
||||
if(cx->dis_JumpCalls[i].To == destination)
|
||||
return str_ccprintf("%s%d", cx->dis_JumpCalls[i].FunctionCall? "Function": "Label", cx->dis_JumpCalls[i].LabelNumber);
|
||||
|
||||
return "UNKNOWN";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
// Show all references which refer to "Position" as destination
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
|
||||
void disasm_init_regfile(const AVRPART *p);
|
||||
int disasm_wrap(int addr);
|
||||
int Tagfile_FindLabelAddress(int address);
|
||||
char *Tagfile_GetLabel(int TagIndex);
|
||||
char *Tagfile_GetLabelComment(int TagIndex);
|
||||
int disasm_find_symbol(int type, int address);
|
||||
char *Tagfile_GetLabel(int index);
|
||||
char *Tagfile_GetLabelComment(int index);
|
||||
int Tagfile_FindPGMAddress(int address);
|
||||
const char *Tagfile_Resolve_Mem_Address(int address);
|
||||
int Tagfile_Process_Data(const char *Bitstream, int Position, int offset);
|
||||
|
||||
@@ -34,246 +34,172 @@
|
||||
#include "libavrdude.h"
|
||||
#include "disasm_private.h"
|
||||
|
||||
static int LineError(const char *Token, const char *Message, int LineNo) {
|
||||
if((Token == NULL) || (strlen(Token) == 0)) {
|
||||
pmsg_error("%s in tagfile, line %d\n", Message, LineNo);
|
||||
static void zap_symbols() {
|
||||
if(cx->dis_symbols) {
|
||||
for(int i = 0; i < cx->dis_symbolN; i++) {
|
||||
mmt_free(cx->dis_symbols[i].comment);
|
||||
mmt_free(cx->dis_symbols[i].name);
|
||||
}
|
||||
mmt_free(cx->dis_symbols);
|
||||
cx->dis_symbols = NULL;
|
||||
}
|
||||
cx->dis_symbolN = 0;
|
||||
}
|
||||
|
||||
static int symbol_sort(const void *v1, const void *v2) {
|
||||
const Disasm_symbol *p1 = v1, *p2 = v2;
|
||||
int diff;
|
||||
|
||||
if((diff = p1->type - p2->type))
|
||||
return diff;
|
||||
return p1->address - p2->address;
|
||||
}
|
||||
|
||||
int disasm_find_symbol(int type, int address) {
|
||||
Disasm_symbol key, *found;
|
||||
|
||||
key.type = type;
|
||||
key.address = address;
|
||||
found = bsearch(&key, cx->dis_symbols, cx->dis_symbolN, sizeof(Disasm_symbol), symbol_sort);
|
||||
|
||||
return found? found - cx->dis_symbols: -1;
|
||||
}
|
||||
|
||||
static void add_symbol(int address, int type, int subtype, int count, const char *name, const char *comment) {
|
||||
int N = cx->dis_symbolN++;
|
||||
|
||||
cx->dis_symbols = (Disasm_symbol *) mmt_realloc(cx->dis_symbols, sizeof(Disasm_symbol) * (N+1));
|
||||
cx->dis_symbols[N].address = address;
|
||||
cx->dis_symbols[N].type = type;
|
||||
cx->dis_symbols[N].subtype = subtype;
|
||||
cx->dis_symbols[N].count = count;
|
||||
cx->dis_symbols[N].used = 0;
|
||||
cx->dis_symbols[N].name = name? mmt_strdup(name): NULL;
|
||||
cx->dis_symbols[N].comment = comment? mmt_strdup(comment): NULL;
|
||||
}
|
||||
|
||||
static int LineError(const char *token, const char *message, int lineno) {
|
||||
if((token == NULL) || (strlen(token) == 0)) {
|
||||
pmsg_error("%s in tagfile, line %d\n", message, lineno);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zap_IORegisters() {
|
||||
if(cx->dis_IORegisters) {
|
||||
for(int i = 0; i < cx->dis_IORegisterN; i++)
|
||||
mmt_free(cx->dis_IORegisters[i].name);
|
||||
mmt_free(cx->dis_IORegisters);
|
||||
cx->dis_IORegisters = NULL;
|
||||
}
|
||||
cx->dis_IORegisterN = 0;
|
||||
}
|
||||
|
||||
static void zap_CodeLabels() {
|
||||
if(cx->dis_CodeLabels) {
|
||||
for(int i = 0; i < cx->dis_CodeLabelN; i++) {
|
||||
mmt_free(cx->dis_CodeLabels[i].comment);
|
||||
mmt_free(cx->dis_CodeLabels[i].name);
|
||||
}
|
||||
mmt_free(cx->dis_CodeLabels);
|
||||
cx->dis_CodeLabels = NULL;
|
||||
}
|
||||
cx->dis_CodeLabelN = 0;
|
||||
}
|
||||
|
||||
static void zap_PGMLabels() {
|
||||
if(cx->dis_PGMLabels) {
|
||||
for(int i = 0; i < cx->dis_PGMLabelN; i++)
|
||||
mmt_free(cx->dis_PGMLabels[i].name);
|
||||
mmt_free(cx->dis_PGMLabels);
|
||||
cx->dis_PGMLabels = NULL;
|
||||
}
|
||||
cx->dis_PGMLabelN = 0;
|
||||
}
|
||||
|
||||
static void zap_MemLabels() {
|
||||
if(cx->dis_MemLabels) {
|
||||
for(int i = 0; i < cx->dis_MemLabelN; i++)
|
||||
mmt_free(cx->dis_MemLabels[i].name);
|
||||
mmt_free(cx->dis_MemLabels);
|
||||
cx->dis_MemLabels = NULL;
|
||||
}
|
||||
cx->dis_MemLabelN = 0;
|
||||
}
|
||||
|
||||
|
||||
static void Add_Code_Tag(int address, const char *name, const char *comment) {
|
||||
cx->dis_CodeLabelN++;
|
||||
|
||||
cx->dis_CodeLabels = (Disasm_CodeLabel *) mmt_realloc(cx->dis_CodeLabels, sizeof(Disasm_CodeLabel) * cx->dis_CodeLabelN);
|
||||
cx->dis_CodeLabels[cx->dis_CodeLabelN - 1].address = address;
|
||||
cx->dis_CodeLabels[cx->dis_CodeLabelN - 1].name = name? mmt_strdup(name): NULL;
|
||||
cx->dis_CodeLabels[cx->dis_CodeLabelN - 1].comment = comment? mmt_strdup(comment): NULL;
|
||||
}
|
||||
|
||||
static void Add_PGM_Tag(int address, char subtype, unsigned int Count, const char *name) {
|
||||
cx->dis_PGMLabelN++;
|
||||
|
||||
cx->dis_PGMLabels = (Disasm_PGMLabel *) mmt_realloc(cx->dis_PGMLabels, sizeof(Disasm_PGMLabel) * cx->dis_PGMLabelN);
|
||||
cx->dis_PGMLabels[cx->dis_PGMLabelN - 1].address = address;
|
||||
cx->dis_PGMLabels[cx->dis_PGMLabelN - 1].subtype = subtype;
|
||||
cx->dis_PGMLabels[cx->dis_PGMLabelN - 1].Count = Count;
|
||||
cx->dis_PGMLabels[cx->dis_PGMLabelN - 1].name = name? mmt_strdup(name): NULL;
|
||||
}
|
||||
|
||||
static void Add_Mem_Tag(int address, char subtype, unsigned int Count, const char *name) {
|
||||
cx->dis_MemLabelN++;
|
||||
|
||||
cx->dis_MemLabels = (Disasm_MemLabel *) mmt_realloc(cx->dis_MemLabels, sizeof(Disasm_MemLabel) * cx->dis_MemLabelN);
|
||||
cx->dis_MemLabels[cx->dis_MemLabelN - 1].address = address;
|
||||
cx->dis_MemLabels[cx->dis_MemLabelN - 1].subtype = subtype;
|
||||
cx->dis_MemLabels[cx->dis_MemLabelN - 1].Count = Count;
|
||||
cx->dis_MemLabels[cx->dis_MemLabelN - 1].name = name? mmt_strdup(name): NULL;
|
||||
}
|
||||
|
||||
static int Tagfile_Readline(char *Line, int LineNo) {
|
||||
char *Token, Type, Subtype, *Name;
|
||||
int address, Count;
|
||||
static int Tagfile_Readline(char *line, int lineno) {
|
||||
char *token, type, subtype, *name;
|
||||
int address, count;
|
||||
const char *errptr;
|
||||
|
||||
if(Line[0] == '#' || strlen(Line) <= 1)
|
||||
if(line[0] == '#' || strlen(line) <= 1)
|
||||
return 0;
|
||||
|
||||
Token = strtok(Line, " \t\n");
|
||||
if(LineError(Token, "nonempty line", LineNo))
|
||||
token = strtok(line, " \t\n");
|
||||
if(LineError(token, "nonempty line", lineno))
|
||||
return -1;
|
||||
address = str_int(Token, STR_INT32, &errptr);
|
||||
address = str_int(token, STR_INT32, &errptr);
|
||||
if(errptr) {
|
||||
pmsg_error("address %s: %s\n", Token, errptr);
|
||||
pmsg_error("address %s: %s\n", token, errptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Token = strtok(NULL, " \t\n");
|
||||
if(LineError(Token, "no second argument", LineNo))
|
||||
token = strtok(NULL, " \t\n");
|
||||
if(LineError(token, "no second argument", lineno))
|
||||
return -1;
|
||||
if(strlen(Token) != 1) {
|
||||
LineError(NULL, "second argument should be a type (L, P or M)", LineNo);
|
||||
if(strlen(token) != 1) {
|
||||
LineError(NULL, "second argument should be a type (L, P or M)", lineno);
|
||||
return -1;
|
||||
}
|
||||
Type = Token[0];
|
||||
type = token[0];
|
||||
|
||||
Token = strtok(NULL, " \t\n");
|
||||
if(LineError(Token, "no third argument", LineNo))
|
||||
token = strtok(NULL, " \t\n");
|
||||
if(LineError(token, "no third argument", lineno))
|
||||
return -1;
|
||||
|
||||
if(Type == 'L') {
|
||||
Name = Token; // Name, comment is optional
|
||||
Add_Code_Tag(address, Name, strtok(NULL, "\t\n"));
|
||||
if(type == 'L') {
|
||||
name = token; // Name, comment is optional
|
||||
add_symbol(address, 'L', 0, 0, name, strtok(NULL, "\t\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(LineError(Token, "no fourth argument", LineNo))
|
||||
if(LineError(token, "no fourth argument", lineno))
|
||||
return -1;
|
||||
if(strlen(Token) != 1) {
|
||||
LineError(NULL, "fourth argument should be a subtype (B, W, A or S)", LineNo);
|
||||
if(strlen(token) != 1) {
|
||||
LineError(NULL, "fourth argument should be a subtype (B, W, A or S)", lineno);
|
||||
return -1;
|
||||
}
|
||||
Subtype = Token[0];
|
||||
subtype = token[0];
|
||||
|
||||
// Either B(yte), W(ord), A(utoterminated string) or S(tring)
|
||||
switch (Subtype) {
|
||||
switch(subtype) {
|
||||
case 'B':
|
||||
Subtype = TYPE_BYTE;
|
||||
subtype = TYPE_BYTE;
|
||||
break;
|
||||
case 'W':
|
||||
Subtype = TYPE_WORD;
|
||||
subtype = TYPE_WORD;
|
||||
break;
|
||||
case 'A':
|
||||
Subtype = TYPE_ASTRING;
|
||||
subtype = TYPE_ASTRING;
|
||||
break;
|
||||
case 'S':
|
||||
Subtype = TYPE_STRING;
|
||||
subtype = TYPE_STRING;
|
||||
break;
|
||||
default:
|
||||
LineError(NULL, "invalid subtype (expected one of B, W, A or S)", LineNo);
|
||||
LineError(NULL, "invalid subtype (expected one of B, W, A or S)", lineno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((Type == 'M') && ((Subtype != TYPE_BYTE) && (Subtype != TYPE_WORD))) {
|
||||
LineError(NULL, "memory labels can only be of type B or W", LineNo);
|
||||
if((type == 'M') && ((subtype != TYPE_BYTE) && (subtype != TYPE_WORD))) {
|
||||
LineError(NULL, "memory labels can only be of type B or W", lineno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Token = strtok(NULL, " \t\n");
|
||||
Count = str_int(Token, STR_INT32, &errptr);
|
||||
token = strtok(NULL, " \t\n");
|
||||
count = str_int(token, STR_INT32, &errptr);
|
||||
if(errptr) {
|
||||
pmsg_error("count %s: %s\n", Token, errptr);
|
||||
pmsg_error("count %s: %s\n", token, errptr);
|
||||
return -1;
|
||||
}
|
||||
if(Count < 1) {
|
||||
LineError(NULL, str_ccprintf("invalid count %d given", Count), LineNo);
|
||||
if(count < 1) {
|
||||
LineError(NULL, str_ccprintf("invalid count %d given", count), lineno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Name = strtok(NULL, " \t\n");
|
||||
if(Type == 'P') {
|
||||
Add_PGM_Tag(address, Subtype, Count, Name);
|
||||
} else if(Type == 'M') {
|
||||
Add_Mem_Tag(address, Subtype, Count, Name);
|
||||
} else {
|
||||
pmsg_error("invalid tag type %c\n", Type);
|
||||
name = strtok(NULL, " \t\n");
|
||||
if(type != 'P' && type != 'M') {
|
||||
pmsg_error("invalid tag type %c (must be L, P or M)\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
add_symbol(address, type, subtype, count, name, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CodeLabelSort(const void *A, const void *B) {
|
||||
const Disasm_CodeLabel *X, *Y;
|
||||
|
||||
X = (const Disasm_CodeLabel *) A;
|
||||
Y = (const Disasm_CodeLabel *) B;
|
||||
if(X->address == Y->address)
|
||||
return 0;
|
||||
if(X->address < Y->address)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int PGMLabelSort(const void *A, const void *B) {
|
||||
const Disasm_PGMLabel *X, *Y;
|
||||
|
||||
X = (const Disasm_PGMLabel *) A;
|
||||
Y = (const Disasm_PGMLabel *) B;
|
||||
if(X->address == Y->address)
|
||||
return 0;
|
||||
if(X->address < Y->address)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int MemLabelSort(const void *A, const void *B) {
|
||||
const Disasm_MemLabel *X, *Y;
|
||||
|
||||
X = (const Disasm_MemLabel *) A;
|
||||
Y = (const Disasm_MemLabel *) B;
|
||||
if(X->address == Y->address)
|
||||
return 0;
|
||||
if(X->address < Y->address)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void Tagfile_SortLabels() {
|
||||
qsort(cx->dis_CodeLabels, cx->dis_CodeLabelN, sizeof(Disasm_CodeLabel), CodeLabelSort);
|
||||
qsort(cx->dis_PGMLabels, cx->dis_PGMLabelN, sizeof(Disasm_PGMLabel), PGMLabelSort);
|
||||
qsort(cx->dis_MemLabels, cx->dis_MemLabelN, sizeof(Disasm_MemLabel), MemLabelSort);
|
||||
}
|
||||
|
||||
int disasm_init_tagfile(const AVRPART *p, const char *Filename) {
|
||||
FILE *inf = fopen(Filename, "r");
|
||||
int LineNo = 1;
|
||||
int disasm_init_tagfile(const AVRPART *p, const char *fname) {
|
||||
FILE *inf = fopen(fname, "r");
|
||||
int lineno = 1;
|
||||
const char *errstr;
|
||||
|
||||
if(!inf) {
|
||||
pmsg_ext_error("cannot open tagfile %s: %s\n", Filename, strerror(errno));
|
||||
pmsg_ext_error("cannot open tagfile %s: %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
zap_CodeLabels();
|
||||
zap_PGMLabels();
|
||||
zap_MemLabels();
|
||||
zap_symbols();
|
||||
disasm_init_regfile(p);
|
||||
|
||||
for(char *buffer; (buffer = str_fgets(inf, &errstr)); mmt_free(buffer))
|
||||
if(Tagfile_Readline(buffer, LineNo++) < 0)
|
||||
if(Tagfile_Readline(buffer, lineno++) < 0)
|
||||
goto error;
|
||||
|
||||
if(errstr) {
|
||||
pmsg_error("read error in tag file %s: %s\n", Filename, errstr);
|
||||
pmsg_error("read error in tag file %s: %s\n", fname, errstr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
fclose(inf);
|
||||
Tagfile_SortLabels();
|
||||
qsort(cx->dis_symbols, cx->dis_symbolN, sizeof(Disasm_symbol), symbol_sort);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
@@ -281,53 +207,36 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Tagfile_FindLabelAddress(int address) {
|
||||
Disasm_CodeLabel Goal;
|
||||
Disasm_CodeLabel *Result;
|
||||
|
||||
Goal.address = address;
|
||||
Result = bsearch(&Goal, cx->dis_CodeLabels, cx->dis_CodeLabelN, sizeof(Disasm_CodeLabel), CodeLabelSort);
|
||||
if(Result == NULL)
|
||||
return -1;
|
||||
return Result - cx->dis_CodeLabels;
|
||||
char *Tagfile_GetLabel(int index) {
|
||||
return cx->dis_symbols[index].name;
|
||||
}
|
||||
|
||||
char *Tagfile_GetLabel(int TagIndex) {
|
||||
return cx->dis_CodeLabels[TagIndex].name;
|
||||
}
|
||||
|
||||
char *Tagfile_GetLabelComment(int TagIndex) {
|
||||
return cx->dis_CodeLabels[TagIndex].comment;
|
||||
}
|
||||
|
||||
int Tagfile_FindPGMAddress(int address) {
|
||||
Disasm_PGMLabel Goal;
|
||||
Disasm_PGMLabel *Result;
|
||||
|
||||
Goal.address = address;
|
||||
Result = bsearch(&Goal, cx->dis_PGMLabels, cx->dis_PGMLabelN, sizeof(Disasm_PGMLabel), PGMLabelSort);
|
||||
if(Result == NULL)
|
||||
return -1;
|
||||
return Result - cx->dis_PGMLabels;
|
||||
char *Tagfile_GetLabelComment(int index) {
|
||||
return cx->dis_symbols[index].comment;
|
||||
}
|
||||
|
||||
const char *Tagfile_Resolve_Mem_Address(int address) {
|
||||
for(int i = 0; i < cx->dis_MemLabelN && cx->dis_MemLabels[i].address <= address; i++) {
|
||||
int Start = cx->dis_MemLabels[i].address;
|
||||
int Size = cx->dis_MemLabels[i].subtype == TYPE_WORD? 2: 1;
|
||||
int End = cx->dis_MemLabels[i].address + cx->dis_MemLabels[i].Count * Size - 1;
|
||||
for(int i = 0; i < cx->dis_symbolN; i++) {
|
||||
if(cx->dis_symbols[i].type != 'M')
|
||||
continue;
|
||||
if(cx->dis_symbols[i].address > address)
|
||||
break;
|
||||
|
||||
if(address >= Start && address <= End) {
|
||||
if(cx->dis_MemLabels[i].Count == 1) { // Single variable
|
||||
if(Size == 1)
|
||||
return str_ccprintf("%s", cx->dis_MemLabels[i].name);
|
||||
return str_ccprintf("_%s8(%s)", address == Start? "lo": "hi", cx->dis_MemLabels[i].name);
|
||||
int start = cx->dis_symbols[i].address;
|
||||
int size = cx->dis_symbols[i].subtype == TYPE_WORD? 2: 1;
|
||||
int end = cx->dis_symbols[i].address + cx->dis_symbols[i].count * size - 1;
|
||||
|
||||
if(address >= start && address <= end) {
|
||||
if(cx->dis_symbols[i].count == 1) { // Single variable
|
||||
if(size == 1)
|
||||
return str_ccprintf("%s", cx->dis_symbols[i].name);
|
||||
return str_ccprintf("_%s8(%s)", address == start? "lo": "hi", cx->dis_symbols[i].name);
|
||||
}
|
||||
// Array
|
||||
if(Size == 1)
|
||||
return str_ccprintf("%s[%d]", cx->dis_MemLabels[i].name, address - Start);
|
||||
return str_ccprintf("_%s8(%s[%d])", (address-Start)%2? "hi": "lo", cx->dis_MemLabels[i].name,
|
||||
(address - Start)/2);
|
||||
if(size == 1)
|
||||
return str_ccprintf("%s[%d]", cx->dis_symbols[i].name, address - start);
|
||||
return str_ccprintf("_%s8(%s[%d])", (address - start)%2? "hi": "lo",
|
||||
cx->dis_symbols[i].name, (address - start)/2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,15 +297,14 @@ static void Sanitize_String(char *String) {
|
||||
|
||||
int Tagfile_Process_Data(const char *Bitstream, int Position, int offset) {
|
||||
int BytesAdvanced;
|
||||
int Index;
|
||||
int (*ProcessingFunction)(const char *, int, int, int, const char *) = NULL;
|
||||
char Buffer[32];
|
||||
|
||||
Index = Tagfile_FindPGMAddress(disasm_wrap(Position + offset));
|
||||
if(Index == -1)
|
||||
int index = disasm_find_symbol('P', disasm_wrap(Position + offset));
|
||||
if(index < 0)
|
||||
return 0;
|
||||
|
||||
switch (cx->dis_PGMLabels[Index].subtype) {
|
||||
switch(cx->dis_symbols[index].subtype) {
|
||||
case TYPE_BYTE:
|
||||
ProcessingFunction = Tagfile_Process_Byte;
|
||||
break;
|
||||
@@ -411,8 +319,8 @@ int Tagfile_Process_Data(const char *Bitstream, int Position, int offset) {
|
||||
break;
|
||||
}
|
||||
|
||||
term_out("; Inline PGM data: %d ", cx->dis_PGMLabels[Index].Count);
|
||||
switch (cx->dis_PGMLabels[Index].subtype) {
|
||||
term_out("; Inline PGM data: %d ", cx->dis_symbols[index].count);
|
||||
switch(cx->dis_symbols[index].subtype) {
|
||||
case TYPE_BYTE:
|
||||
term_out("byte");
|
||||
break;
|
||||
@@ -426,17 +334,17 @@ int Tagfile_Process_Data(const char *Bitstream, int Position, int offset) {
|
||||
term_out("string");
|
||||
break;
|
||||
}
|
||||
if(cx->dis_PGMLabels[Index].Count != 1)
|
||||
if(cx->dis_symbols[index].count != 1)
|
||||
term_out("s");
|
||||
term_out(" starting at 0x%0*x", cx->dis_addrwidth, disasm_wrap(Position + offset));
|
||||
|
||||
if(cx->dis_PGMLabels[Index].name)
|
||||
term_out(" (%s)", cx->dis_PGMLabels[Index].name);
|
||||
if(cx->dis_symbols[index].name)
|
||||
term_out(" (%s)", cx->dis_symbols[index].name);
|
||||
term_out("\n");
|
||||
|
||||
if((cx->dis_PGMLabels[Index].subtype == TYPE_ASTRING) || (cx->dis_PGMLabels[Index].subtype == TYPE_STRING)) {
|
||||
if(cx->dis_PGMLabels[Index].name != NULL) {
|
||||
snprintf(Buffer, sizeof(Buffer), "%x_%s", disasm_wrap(Position + offset), cx->dis_PGMLabels[Index].name);
|
||||
if((cx->dis_symbols[index].subtype == TYPE_ASTRING) || (cx->dis_symbols[index].subtype == TYPE_STRING)) {
|
||||
if(cx->dis_symbols[index].name != NULL) {
|
||||
snprintf(Buffer, sizeof(Buffer), "%x_%s", disasm_wrap(Position + offset), cx->dis_symbols[index].name);
|
||||
Sanitize_String(Buffer);
|
||||
} else {
|
||||
snprintf(Buffer, sizeof(Buffer), "%x", disasm_wrap(Position + offset));
|
||||
@@ -444,10 +352,10 @@ int Tagfile_Process_Data(const char *Bitstream, int Position, int offset) {
|
||||
}
|
||||
|
||||
BytesAdvanced = 0;
|
||||
for(unsigned i = 0; i < cx->dis_PGMLabels[Index].Count; i++)
|
||||
for(int i = 0; i < cx->dis_symbols[index].count; i++)
|
||||
BytesAdvanced += ProcessingFunction(Bitstream, Position + BytesAdvanced, offset, i, Buffer);
|
||||
|
||||
if(cx->dis_PGMLabels[Index].subtype == TYPE_ASTRING) {
|
||||
if(cx->dis_symbols[index].subtype == TYPE_ASTRING) {
|
||||
// Autoaligned string
|
||||
if((BytesAdvanced % 2) != 0) {
|
||||
// Not yet aligned correctly
|
||||
@@ -465,11 +373,11 @@ int Tagfile_Process_Data(const char *Bitstream, int Position, int offset) {
|
||||
|
||||
|
||||
// Allocate, copy, append a suffix (H, L, 0...8 or nothing), make upper case and return
|
||||
static char *regname(const char *reg, int suf) {
|
||||
static char *regname(const char *pre, const char *reg, int suf) {
|
||||
char *ret =
|
||||
suf <= -1? mmt_strdup(reg):
|
||||
suf == 'h' || suf == 'l'? str_sprintf("%s%c", reg, suf):
|
||||
str_sprintf("%s%d", reg, suf);
|
||||
suf <= -1? str_sprintf("%s%s", pre, reg):
|
||||
suf == 'h' || suf == 'l'? str_sprintf("%s%s%c", pre, reg, suf):
|
||||
str_sprintf("%s%s%d", pre, reg, suf);
|
||||
|
||||
for(char *s = ret; *s; s++)
|
||||
*s = *s == '.'? '_': isascii(*s & 0xff)? toupper(*s & 0xff): *s;
|
||||
@@ -477,64 +385,46 @@ static char *regname(const char *reg, int suf) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Initialise cx->dis_IORegisters and cx->dis_MemLabels from part register file
|
||||
// Initialise cx->dis_symbols from part register file
|
||||
void disasm_init_regfile(const AVRPART *p) {
|
||||
int nr = 0, nio = 0, offset = 0;
|
||||
int nr = 0, offset = 0;
|
||||
const Register_file *rf = avr_locate_register_file(p, &nr);
|
||||
|
||||
if(rf) {
|
||||
zap_MemLabels();
|
||||
zap_IORegisters();
|
||||
|
||||
// Count how many entries are needed
|
||||
for(int i = 0; i< nr; i++)
|
||||
if(rf[i].addr < 0x40 && rf[i].size > 0)
|
||||
nio += rf[i].size;
|
||||
cx->dis_IORegisters = mmt_malloc(nio*sizeof*cx->dis_IORegisters);
|
||||
cx->dis_MemLabels = mmt_malloc(nr*sizeof*cx->dis_MemLabels);
|
||||
|
||||
AVRMEM *mem = avr_locate_io(p);
|
||||
if(mem)
|
||||
offset = mem->offset;
|
||||
nio = 0;
|
||||
const char *mpre = offset? "MEM_": "";
|
||||
const char *ipre = offset? "IO_": "";
|
||||
for(int i = 0; i< nr; i++) {
|
||||
cx->dis_MemLabels[i].address = offset + rf[i].addr;
|
||||
cx->dis_MemLabels[i].subtype = rf[i].size == 2? TYPE_WORD: TYPE_BYTE;
|
||||
cx->dis_MemLabels[i].Count = rf[i].size > 2? rf[i].size: 1;
|
||||
cx->dis_MemLabels[i].name = regname(rf[i].reg, -1);
|
||||
int addr = offset + rf[i].addr;
|
||||
int sub = rf[i].size == 2? TYPE_WORD: TYPE_BYTE;
|
||||
int count = rf[i].size > 2? rf[i].size: 1;
|
||||
add_symbol(addr, 'M', sub, count, regname(mpre, rf[i].reg, -1), NULL);
|
||||
|
||||
if(rf[i].addr < 0x40) {
|
||||
if(rf[i].size == 1) {
|
||||
cx->dis_IORegisters[nio].name = regname(rf[i].reg, -1);
|
||||
cx->dis_IORegisters[nio].address = rf[i].addr;
|
||||
nio++;
|
||||
} else if(rf[i].size == 2) {
|
||||
cx->dis_IORegisters[nio].name = regname(rf[i].reg, 'l');
|
||||
cx->dis_IORegisters[nio].address = rf[i].addr;
|
||||
nio++;
|
||||
cx->dis_IORegisters[nio].name = regname(rf[i].reg, 'h');
|
||||
cx->dis_IORegisters[nio].address = rf[i].addr+1;
|
||||
nio++;
|
||||
if(rf[i].size == 1)
|
||||
add_symbol(rf[i].addr, 'I', TYPE_BYTE, 1, regname(ipre, rf[i].reg, -1), NULL);
|
||||
else if(rf[i].size == 2) {
|
||||
add_symbol(rf[i].addr, 'I', TYPE_BYTE, 1, regname(ipre, rf[i].reg, 'l'), NULL);
|
||||
add_symbol(rf[i].addr+1, 'I', TYPE_BYTE, 1, regname(ipre, rf[i].reg, 'h'), NULL);
|
||||
} else if(rf[i].size > 2) {
|
||||
for(int k = 0; k < rf[i].size; k++) {
|
||||
cx->dis_IORegisters[nio].name = regname(rf[i].reg, k);
|
||||
cx->dis_IORegisters[nio].address = rf[i].addr + k;
|
||||
nio++;
|
||||
}
|
||||
for(int k = 0; k < rf[i].size; k++)
|
||||
add_symbol(rf[i].addr+k, 'I', TYPE_BYTE, 1, regname(ipre, rf[i].reg, k), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
cx->dis_IORegisterN = nio;
|
||||
cx->dis_MemLabelN = nr;
|
||||
qsort(cx->dis_MemLabels, cx->dis_MemLabelN, sizeof(Disasm_MemLabel), MemLabelSort);
|
||||
qsort(cx->dis_symbols, cx->dis_symbolN, sizeof(Disasm_symbol), symbol_sort);
|
||||
}
|
||||
}
|
||||
|
||||
const char *Resolve_IO_Register(int Number) {
|
||||
for(int i = 0; i < cx->dis_IORegisterN; i++) {
|
||||
if(cx->dis_IORegisters[i].address == Number) {
|
||||
cx->dis_IORegisters[i].used = 1;
|
||||
return cx->dis_IORegisters[i].name;
|
||||
for(int i = 0; i < cx->dis_symbolN; i++) {
|
||||
if(cx->dis_symbols[i].type != 'I')
|
||||
continue;
|
||||
if(cx->dis_symbols[i].address == Number) {
|
||||
cx->dis_symbols[i].used = 1;
|
||||
return cx->dis_symbols[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,7 +432,7 @@ const char *Resolve_IO_Register(int Number) {
|
||||
}
|
||||
|
||||
void Emit_Used_IO_Registers() {
|
||||
for(int i = 0; i < cx->dis_IORegisterN; i++)
|
||||
if(cx->dis_IORegisters[i].used)
|
||||
term_out(".equ %s, 0x%02x\n", cx->dis_IORegisters[i].name, cx->dis_IORegisters[i].address);
|
||||
for(int i = 0; i < cx->dis_symbolN; i++)
|
||||
if(cx->dis_symbols[i].used)
|
||||
term_out(".equ %s, 0x%02x\n", cx->dis_symbols[i].name, cx->dis_symbols[i].address);
|
||||
}
|
||||
|
||||
@@ -1473,26 +1473,6 @@ typedef struct {
|
||||
int FunctionCall;
|
||||
} Disasm_JumpCall;
|
||||
|
||||
typedef struct {
|
||||
int address;
|
||||
char *name;
|
||||
char *comment;
|
||||
} Disasm_CodeLabel;
|
||||
|
||||
typedef struct {
|
||||
int address;
|
||||
int subtype;
|
||||
unsigned int Count;
|
||||
char *name;
|
||||
} Disasm_PGMLabel;
|
||||
|
||||
typedef struct {
|
||||
int address;
|
||||
int subtype;
|
||||
unsigned int Count;
|
||||
char *name;
|
||||
} Disasm_MemLabel;
|
||||
|
||||
typedef struct {
|
||||
int address;
|
||||
char *name;
|
||||
@@ -1851,12 +1831,9 @@ typedef struct {
|
||||
// Static variables from disasm*.c
|
||||
int dis_initopts, dis_flashsz, dis_flashsz2, dis_addrwidth, dis_sramwidth, dis_cycle_index;
|
||||
Disasm_options dis_opts;
|
||||
int dis_JumpCallN, dis_CodeLabelN, dis_PGMLabelN, dis_MemLabelN, dis_IORegisterN;
|
||||
int dis_JumpCallN, dis_symbolN;
|
||||
Disasm_JumpCall *dis_JumpCalls;
|
||||
Disasm_CodeLabel *dis_CodeLabels;
|
||||
Disasm_PGMLabel *dis_PGMLabels;
|
||||
Disasm_MemLabel *dis_MemLabels;
|
||||
Disasm_IO_Register *dis_IORegisters;
|
||||
Disasm_symbol *dis_symbols;
|
||||
|
||||
// Static variables from usb_libusb.c
|
||||
#include "usbdevs.h"
|
||||
|
||||
Reference in New Issue
Block a user