Make list of jumpable addresses a bitfield

This commit is contained in:
Stefan Rueger
2024-07-25 17:40:19 +01:00
parent fec6e842df
commit 32ca573b71
2 changed files with 97 additions and 106 deletions

View File

@@ -77,13 +77,9 @@ static int find_symbol(int type, int address) {
}
static void add_symbol(int address, int type, int subtype, int count, const char *name, const char *comment) {
int N = find_symbol(0, -1); // Do we have a recycled symbol?
if(N < 0) { // No, increase symbol table
N = cx->dis_symbolN++;
if(N%1024 == 0)
cx->dis_symbols = (Disasm_symbol *) mmt_realloc(cx->dis_symbols, sizeof(Disasm_symbol) * (N+1024));
}
int N = cx->dis_symbolN++;
if(N % 1024 == 0)
cx->dis_symbols = (Disasm_symbol *) mmt_realloc(cx->dis_symbols, sizeof(Disasm_symbol) * (N+1024));
cx->dis_symbols[N].address = address;
cx->dis_symbols[N].type = type;
cx->dis_symbols[N].subtype = subtype;
@@ -101,7 +97,7 @@ static int line_error(const char *token, const char *message, int lineno) {
return 0;
}
static int Tagfile_Readline(char *line, int lineno) {
static int tagfile_readline(char *line, int lineno) {
char *token, type, subtype, *name;
int address, count;
const char *errptr;
@@ -250,7 +246,7 @@ int disasm_init_tagfile(const AVRPART *p, const char *fname) {
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) {
@@ -267,14 +263,6 @@ error:
return -1;
}
static char *get_symbol_name(int index) {
return cx->dis_symbols[index].name;
}
static char *get_symbol_comment(int index) {
return cx->dis_symbols[index].comment;
}
static const char *resolve_mem_address(int address) {
for(int i = 0; i < cx->dis_symbolN; i++) {
if(cx->dis_symbols[i].type != 'M')
@@ -321,8 +309,8 @@ static const char *get_label_name(int destination, char **comment) {
int index = find_symbol('L', destination);
if(index >= 0) {
if(comment)
*comment = get_symbol_comment(index);
return str_ccprintf("%s", get_symbol_name(index));
*comment = cx->dis_symbols[index].comment;
return cx->dis_symbols[index].name;
}
for(int i = 0; i < cx->dis_jumpcallN; i++)
@@ -343,9 +331,9 @@ static int disasm_wrap(int addr) {
#define disasm_out(...) do { \
if(cx->dis_pass != 2) \
break; \
if(cx->dis_para && cx->dis_written) \
if(cx->dis_para) \
term_out("\n"); \
cx->dis_para = 0, cx->dis_written = 1; \
cx->dis_para = 0; \
term_out(__VA_ARGS__); \
} while(0)
@@ -354,7 +342,6 @@ typedef struct {
char label[LINE_N], code[LINE_N], comment[LINE_N];
} Disasm_line;
// Column where opcode starts
static int codecol() {
int ret = 0;
@@ -370,13 +357,24 @@ static int codecol() {
return ret? ret+1: 2;
}
static int is_jumpable(int address) {
if(!cx->dis_jumpable || address < cx->dis_start || address > cx->dis_end)
return 0;
int n = sizeof(int)*8, idx = (address - cx->dis_start)/2;
return cx->dis_jumpable[idx/n] & (1<<(idx%n));
}
// Unified printing of a line
static void lineout(const char *code, const char *comment,
int mnemo, int oplen, const char *buf, int pos, int addr, int labellable) {
int mnemo, int oplen, const char *buf, int pos, int addr, int showlabel) {
if(cx->dis_pass == 1)
return;
int here = disasm_wrap(pos + addr), codewidth = 27;
if(cx->dis_opts.process_labels && labellable) {
if(cx->dis_opts.process_labels && showlabel) {
int match = 0;
for(int i = 0; i < cx->dis_jumpcallN; i++) {
@@ -396,8 +394,6 @@ static void lineout(const char *code, const char *comment,
else
disasm_out("%-*s ; %s\n", codecol() + codewidth, str_ccprintf("%s:", name), comment);
}
if(cx->dis_pass == 1) // Mark this position as one that can be label destination
add_symbol(here, 'l', 0, 0, NULL, NULL);
}
if(cx->dis_opts.show_addresses)
@@ -538,10 +534,8 @@ void emit_used_io_registers() {
}
void disasm_zap_jumpcalls() {
if(cx->dis_jumpcalls) {
mmt_free(cx->dis_jumpcalls);
cx->dis_jumpcalls = NULL;
}
mmt_free(cx->dis_jumpcalls);
cx->dis_jumpcalls = NULL;
cx->dis_jumpcallN = 0;
}
@@ -555,7 +549,7 @@ static void register_jumpcall(int from, int to, int mnemo, unsigned char is_func
if(jc[i].from == from && jc[N].to == to && jc[N].mnemo == mnemo)
return;
if(N%1024 == 0)
if(N % 1024 == 0)
jc = mmt_realloc(jc, sizeof(Disasm_jumpcall) * (N+1024));
jc[N].from = from;
jc[N].to = to;
@@ -568,27 +562,14 @@ static void register_jumpcall(int from, int to, int mnemo, unsigned char is_func
}
}
static int JC_Comparison(const void *Element1, const void *Element2) {
Disasm_jumpcall *JC1, *JC2;
JC1 = (Disasm_jumpcall *) Element1;
JC2 = (Disasm_jumpcall *) Element2;
if((JC1->to) > (JC2->to))
return 1;
else if((JC1->to) == (JC2->to))
return 0;
return -1;
}
static void correct_is_funct(void) {
int i, j;
int last_idx = 0;
int last_dest = cx->dis_jumpcalls[0].to;
char cur_is_func = cx->dis_jumpcalls[0].is_func;
int cur_is_func = cx->dis_jumpcalls[0].is_func;
for(i = 1; i < cx->dis_jumpcallN; i++) {
for(int i = 1; i < cx->dis_jumpcallN; i++) {
if(cx->dis_jumpcalls[i].to != last_dest) {
for(j = last_idx; j < i; j++)
for(int j = last_idx; j < i; j++)
cx->dis_jumpcalls[j].is_func = cur_is_func;
last_idx = i;
last_dest = cx->dis_jumpcalls[i].to;
@@ -596,30 +577,31 @@ static void correct_is_funct(void) {
}
cur_is_func = cur_is_func || cx->dis_jumpcalls[i].is_func;
}
for(j = last_idx; j < cx->dis_jumpcallN; j++)
for(int j = last_idx; j < cx->dis_jumpcallN; j++)
cx->dis_jumpcalls[j].is_func = cur_is_func;
}
static int jumpcall_sort(const void *p1, const void *p2) {
return ((Disasm_jumpcall *) p1)->to - ((Disasm_jumpcall *) p2)->to;
}
static void enumerate_labels(void) {
int i, dest, cur_labelno = 0, cur_funcno = 0;
if(cx->dis_jumpcallN > 1) {
qsort(cx->dis_jumpcalls, cx->dis_jumpcallN, sizeof(Disasm_jumpcall), jumpcall_sort);
correct_is_funct();
if(cx->dis_jumpcallN < 2)
return;
qsort(cx->dis_jumpcalls, cx->dis_jumpcallN, sizeof(Disasm_jumpcall), JC_Comparison);
correct_is_funct();
dest = 987654321;
for(i = 0; i < cx->dis_jumpcallN; i++) {
if(find_symbol('l', cx->dis_jumpcalls[i].to) < 0)
continue;
cx->dis_jumpcalls[i].labelno = cx->dis_jumpcalls[i].is_func? cur_funcno: cur_labelno;
if(dest != cx->dis_jumpcalls[i].to) {
if(cx->dis_jumpcalls[i].is_func)
cur_funcno++;
else
cur_labelno++;
dest = cx->dis_jumpcalls[i].to;
int dest = 987654321, cur_labelno = 0, cur_funcno = 0;
for(int i = 0; i < cx->dis_jumpcallN; i++) {
if(!is_jumpable(cx->dis_jumpcalls[i].to))
continue;
cx->dis_jumpcalls[i].labelno = cx->dis_jumpcalls[i].is_func? cur_funcno: cur_labelno;
if(dest != cx->dis_jumpcalls[i].to) {
if(cx->dis_jumpcalls[i].is_func)
cur_funcno++;
else
cur_labelno++;
dest = cx->dis_jumpcalls[i].to;
}
}
}
}
@@ -747,6 +729,12 @@ static void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo,
break;
}
int awd = cx->dis_addrwidth, swd = cx->dis_sramwidth;
int target = 0, offset = 0, is_jumpcall = 0, is_relative = 0;
int is_function = !!(oc->type & OTY_EXTERNAL); // call/rcall affects stack memory
const char *kmemaddr = NULL, *amemaddr = NULL, *regname = NA? resolve_io_register(RA): NULL;
if(Na) {
/*
* Address is limited to 0x40...0xbf for the reduced-core (TPI part)
@@ -754,33 +742,9 @@ static void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo,
* ADDR[7:0] ← (/a[4], a[4], a[6], a[5], a[3], a[2], a[1], a[0])
*/
Ra = (Ra & 0xf) | ((Ra >> 1) & 0x30) | ((Ra & 0x10) << 2) | (((Ra & 0x10) ^ 0x10) << 3);
amemaddr = resolve_mem_address(Ra);
}
int awd = cx->dis_addrwidth, swd = cx->dis_sramwidth;
snprintf(line->code, LINE_N, "%-7s ", oc->opcode);
char *lc = line->code + strlen(line->code);
#define add_operand(lc, ...) snprintf((lc), LINE_N - ((lc) - line->code), __VA_ARGS__)
// Check for opcodes with undefined results
switch(oc->type & OTY_WARN_MASK) {
case OTY_XWRN:
if(Rd == 26 || Rd == 27 || Rr == 26 || Rr == 27)
add_comment(line, "Warning: the result of this operation is undefined");
break;
case OTY_YWRN:
if(Rd == 28 || Rd == 29 || Rr == 28 || Rr == 29)
add_comment(line, "Warning: the result of this operation is undefined");
break;
case OTY_ZWRN:
if(Rd == 30 || Rd == 31 || Rr == 30 || Rr == 31)
add_comment(line, "Warning: the result of this operation is undefined");
break;
}
int target = 0, offset = 0, is_jumpcall = 0, is_relative = 0;
int is_function = !!(oc->type & OTY_EXTERNAL); // call/rcall affects stack memory
const char *kmemaddr = NULL, *memaddr, *regname;
switch(Nk) {
case 0:
break;
@@ -814,6 +778,29 @@ static void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo,
break;
}
if(cx->dis_pass == 1)
return;
snprintf(line->code, LINE_N, "%-7s ", oc->opcode);
char *lc = line->code + strlen(line->code);
#define add_operand(lc, ...) snprintf((lc), LINE_N - ((lc) - line->code), __VA_ARGS__)
// Check for opcodes with undefined results
switch(oc->type & OTY_WARN_MASK) {
case OTY_XWRN:
if(Rd == 26 || Rd == 27 || Rr == 26 || Rr == 27)
add_comment(line, "Warning: the result of this operation is undefined");
break;
case OTY_YWRN:
if(Rd == 28 || Rd == 29 || Rr == 28 || Rr == 29)
add_comment(line, "Warning: the result of this operation is undefined");
break;
case OTY_ZWRN:
if(Rd == 30 || Rd == 31 || Rr == 30 || Rr == 31)
add_comment(line, "Warning: the result of this operation is undefined");
break;
}
for(const char *o = oc->operands; *o && lc-line->code < LINE_N - 1; o++) {
switch(*o) {
case 'R':
@@ -823,7 +810,7 @@ static void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo,
*lc++ = *o, *lc = 0;
break;
case 'A':
if((regname = resolve_io_register(RA)))
if(regname)
add_operand(lc, "%s", regname);
else
add_operand(lc, "0x%02x", RA);
@@ -831,13 +818,13 @@ static void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo,
break;
case 'a':
add_operand(lc, "0x%02x", Ra);
if((memaddr = resolve_mem_address(Ra)))
add_comment(line, str_ccprintf("%s", memaddr));
if(amemaddr)
add_comment(line, str_ccprintf("%s", amemaddr));
break;
case 'k':
if(is_jumpcall) {
const char *name = get_label_name(target, NULL);
if(cx->dis_opts.process_labels && find_symbol('l', target) >= 0) {
if(cx->dis_opts.process_labels && is_jumpable(target)) {
add_operand(lc, "%s", name);
add_comment(line, str_ccprintf("L%0*x", awd, target));
} else {
@@ -900,20 +887,17 @@ int disasm(const char *buf, int buflen, int addr, int leadin, int leadout) {
int pos, opcode, mnemo, oplen;
Disasm_line line;
// Clear info that symbol has been used and recycle labellable marker 'l'
int recycled = 0;
for(int i = 0; i < cx->dis_symbolN; i++) {
for(int i = 0; i < cx->dis_symbolN; i++) // Clear used-state of symbols
if(cx->dis_symbols[i].type == 'I')
cx->dis_symbols[i].used = 0;
if(cx->dis_symbols[i].type == 'l')
recycled = 1, cx->dis_symbols[i].type = 0, cx->dis_symbols[i].address = -1;
}
if(recycled)
qsort(cx->dis_symbols, cx->dis_symbolN, sizeof(Disasm_symbol), symbol_sort);
cx->dis_jumpable = mmt_malloc((buflen+1)/2/8); // Allocate one bit per word address
cx->dis_start = addr, cx->dis_end = addr + buflen - 1;
// Make two passes: the first gathers labels, the second outputs the assembler code
for(cx->dis_pass = 1; cx->dis_pass < 3; cx->dis_pass++) {
if(cx->dis_pass == 2) {
cx->dis_para = 0;
enumerate_labels();
if(cx->dis_opts.avrgcc_style)
emit_used_io_registers();
@@ -924,8 +908,10 @@ int disasm(const char *buf, int buflen, int addr, int leadin, int leadout) {
}
for(pos = 0; pos < buflen; pos += oplen) {
// Check if this is actually code or maybe only data from tagfile
if((oplen = process_data(buf, buflen, pos, addr)))
if((oplen = process_data(buf, buflen, pos, addr))) {
cx->dis_para = 1;
continue;
}
if(pos & 1) { // Last of PGM data items left off at odd address
oplen = process_num(buf, buflen, 1, pos, addr);
@@ -938,9 +924,14 @@ int disasm(const char *buf, int buflen, int addr, int leadin, int leadout) {
disassemble(buf + pos, disasm_wrap(pos + addr), opcode, mnemo, &line);
lineout(line.code, line.comment, mnemo, oplen, buf, pos, addr, 1);
if(cx->dis_pass == 1) { // Mark this position as one that can be a jump/call destination
int n = sizeof(int)*8, idx = pos/2;
cx->dis_jumpable[idx/n] |= (1<<(idx%n));
}
}
}
mmt_free(cx->dis_jumpable); cx->dis_jumpable = NULL;
return 0;
}

View File

@@ -1829,9 +1829,9 @@ typedef struct {
// Static variables from disasm.c
int dis_initopts, dis_flashsz, dis_flashsz2, dis_addrwidth, dis_sramwidth;
int dis_pass, dis_para, dis_written, dis_cycle_index;
int dis_pass, dis_para, dis_cycle_index;
Disasm_options dis_opts;
int dis_jumpcallN, dis_symbolN;
int dis_jumpcallN, dis_symbolN, *dis_jumpable, dis_start, dis_end;
Disasm_jumpcall *dis_jumpcalls;
Disasm_symbol *dis_symbols;