Warn when opcodes have undefined results, eg, ld r26, X+

This commit is contained in:
Stefan Rueger
2024-07-22 12:50:46 +01:00
parent d58ad3365c
commit 41c18a2d18
3 changed files with 63 additions and 43 deletions

View File

@@ -312,19 +312,19 @@ const AVR_opcode_data avr_opcodes[164] = {
{OP_ID(ld_1), 0xfe0f, 0x900c, 1, OP_AVR2, "1001 000d dddd 1100", OTY_XFRX|OTY_RALL,
"ld", "Rd, X", "Load Indirect", "Rd <-- (X)", "--------",
{"2", "2", "2", "1/2"}, ""},
{OP_ID(ld_2), 0xfe0f, 0x900d, 1, OP_AVR2, "1001 000d dddd 1101", OTY_XFRX|OTY_RALL,
{OP_ID(ld_2), 0xfe0f, 0x900d, 1, OP_AVR2, "1001 000d dddd 1101", OTY_XFRX|OTY_RALL|OTY_XWRN,
"ld", "Rd, X+", "Load Indirect and Post-Increment", "Rd <-- (X), X <-- X + 1", "--------",
{"2", "2", "2", "2/3"}, ""},
{OP_ID(ld_3), 0xfe0f, 0x900e, 1, OP_AVR2, "1001 000d dddd 1110", OTY_XFRX|OTY_RALL,
{OP_ID(ld_3), 0xfe0f, 0x900e, 1, OP_AVR2, "1001 000d dddd 1110", OTY_XFRX|OTY_RALL|OTY_XWRN,
"ld", "Rd, -X", "Load Indirect and Pre-Decrement", "X <-- X - 1, Rd <-- (X)", "--------",
{"2", "3", "2", "2/3"}, ""},
{OP_ID(ld_4), 0xfe0f, 0x8008, 1, OP_AVR2, "1000 000d dddd 1000", OTY_XFRX|OTY_RALL,
"ld", "Rd, Y", "Load Indirect", "Rd <-- (Y) <-- (Y)", "--------",
{"2", "2", "2", "1/2"}, "alias for ldd Rd, Y+0"},
{OP_ID(ld_5), 0xfe0f, 0x9009, 1, OP_AVR2, "1001 000d dddd 1001", OTY_XFRX|OTY_RALL,
{OP_ID(ld_5), 0xfe0f, 0x9009, 1, OP_AVR2, "1001 000d dddd 1001", OTY_XFRX|OTY_RALL|OTY_YWRN,
"ld", "Rd, Y+", "Load Indirect and Post-Increment", "Rd <-- (Y), Y <-- Y + 1", "--------",
{"2", "2", "2", "2/3"}, ""},
{OP_ID(ld_6), 0xfe0f, 0x900a, 1, OP_AVR2, "1001 000d dddd 1010", OTY_XFRX|OTY_RALL,
{OP_ID(ld_6), 0xfe0f, 0x900a, 1, OP_AVR2, "1001 000d dddd 1010", OTY_XFRX|OTY_RALL|OTY_YWRN,
"ld", "Rd, -Y", "Load Indirect and Pre-Decrement", "Y <-- Y - 1 Rd <-- (Y)", "--------",
{"2", "3", "2", "2/3"}, ""},
{OP_ID(ldd_1), 0xd208, 0x8008, 1, OP_AVR2nRC, "10q0 qq0d dddd 1qqq", OTY_XFRX|OTY_RALL,
@@ -333,10 +333,10 @@ const AVR_opcode_data avr_opcodes[164] = {
{OP_ID(ld_7), 0xfe0f, 0x8000, 1, OP_AVR1, "1000 000d dddd 0000", OTY_XFRX|OTY_RALL,
"ld", "Rd, Z", "Load Indirect", "Rd <-- (Z)", "--------",
{"2", "2", "2", "1/2"}, "alias for ldd Rd, Z+0"},
{OP_ID(ld_8), 0xfe0f, 0x9001, 1, OP_AVR1, "1001 000d dddd 0001", OTY_XFRX|OTY_RALL,
{OP_ID(ld_8), 0xfe0f, 0x9001, 1, OP_AVR1, "1001 000d dddd 0001", OTY_XFRX|OTY_RALL|OTY_ZWRN,
"ld", "Rd, Z+", "Load Indirect and Post-Increment", "Rd <-- (Z), Z <-- Z + 1", "--------",
{"2", "2", "2", "2/3"}, ""},
{OP_ID(ld_9), 0xfe0f, 0x9002, 1, OP_AVR1, "1001 000d dddd 0010", OTY_XFRX|OTY_RALL,
{OP_ID(ld_9), 0xfe0f, 0x9002, 1, OP_AVR1, "1001 000d dddd 0010", OTY_XFRX|OTY_RALL|OTY_ZWRN,
"ld", "Rd, -Z", "Load Indirect and Pre-Decrement", "Z <-- Z - 1, Rd <-- (Z)", "--------",
{"2", "3", "2", "2/3"}, ""},
{OP_ID(ldd_2), 0xd208, 0x8000, 1, OP_AVR2nRC, "10q0 qq0d dddd 0qqq", OTY_XFRX|OTY_RALL,
@@ -348,19 +348,19 @@ const AVR_opcode_data avr_opcodes[164] = {
{OP_ID(st_1), 0xfe0f, 0x920c, 1, OP_AVR2, "1001 001r rrrr 1100", OTY_XFRX|OTY_RALL,
"st", "X, Rr", "Store Indirect", "(X) <-- Rr", "--------",
{"2", "1", "1", "1"}, ""},
{OP_ID(st_2), 0xfe0f, 0x920d, 1, OP_AVR2, "1001 001r rrrr 1101", OTY_XFRX|OTY_RALL,
{OP_ID(st_2), 0xfe0f, 0x920d, 1, OP_AVR2, "1001 001r rrrr 1101", OTY_XFRX|OTY_RALL|OTY_XWRN,
"st", "X+, Rr", "Store Indirect and Post-Increment", "(X) <-- Rr, X <-- X + 1", "--------",
{"2", "1", "1", "1"}, ""},
{OP_ID(st_3), 0xfe0f, 0x920e, 1, OP_AVR2, "1001 001r rrrr 1110", OTY_XFRX|OTY_RALL,
{OP_ID(st_3), 0xfe0f, 0x920e, 1, OP_AVR2, "1001 001r rrrr 1110", OTY_XFRX|OTY_RALL|OTY_XWRN,
"st", "-X, Rr", "Store Indirect and Pre-Decrement", "X <-- X - 1, (X) <-- Rr", "--------",
{"2", "2", "1", "1"}, ""},
{OP_ID(st_4), 0xfe0f, 0x8208, 1, OP_AVR2, "1000 001r rrrr 1000", OTY_XFRX|OTY_RALL,
"st", "Y, Rr", "Store Indirect", "(Y) <-- Rr", "--------",
{"2", "1", "1", "1"}, "alias for std Y+0, Rr"},
{OP_ID(st_5), 0xfe0f, 0x9209, 1, OP_AVR2, "1001 001r rrrr 1001", OTY_XFRX|OTY_RALL,
{OP_ID(st_5), 0xfe0f, 0x9209, 1, OP_AVR2, "1001 001r rrrr 1001", OTY_XFRX|OTY_RALL|OTY_YWRN,
"st", "Y+, Rr", "Store Indirect and Post-Increment", "(Y) <-- Rr, Y <-- Y + 1", "--------",
{"2", "1", "1", "1"}, ""},
{OP_ID(st_6), 0xfe0f, 0x920a, 1, OP_AVR2, "1001 001r rrrr 1010", OTY_XFRX|OTY_RALL,
{OP_ID(st_6), 0xfe0f, 0x920a, 1, OP_AVR2, "1001 001r rrrr 1010", OTY_XFRX|OTY_RALL|OTY_YWRN,
"st", "-Y, Rr", "Store Indirect and Pre-Decrement", "Y <-- Y - 1, (Y) <-- Rr", "--------",
{"2", "2", "1", "1"}, ""},
{OP_ID(std_1), 0xd208, 0x8208, 1, OP_AVR2nRC, "10q0 qq1r rrrr 1qqq", OTY_XFRX|OTY_RALL,
@@ -369,10 +369,10 @@ const AVR_opcode_data avr_opcodes[164] = {
{OP_ID(st_7), 0xfe0f, 0x8200, 1, OP_AVR1, "1000 001r rrrr 0000", OTY_XFRX|OTY_RALL,
"st", "Z, Rr", "Store Indirect", "(Z) <-- Rr", "--------",
{"2", "1", "1", "1"}, "alias for std Z+0, Rr"},
{OP_ID(st_8), 0xfe0f, 0x9201, 1, OP_AVR1, "1001 001r rrrr 0001", OTY_XFRX|OTY_RALL,
{OP_ID(st_8), 0xfe0f, 0x9201, 1, OP_AVR1, "1001 001r rrrr 0001", OTY_XFRX|OTY_RALL|OTY_ZWRN,
"st", "Z+, Rr", "Store Indirect and Post-Increment", "(Z) <-- Rr, Z <-- Z + 1", "--------",
{"2", "1", "1", "1"}, ""},
{OP_ID(st_9), 0xfe0f, 0x9202, 1, OP_AVR1, "1001 001r rrrr 0010", OTY_XFRX|OTY_RALL,
{OP_ID(st_9), 0xfe0f, 0x9202, 1, OP_AVR1, "1001 001r rrrr 0010", OTY_XFRX|OTY_RALL|OTY_ZWRN,
"st", "-Z, Rr", "Store Indirect and Pre-Decrement", "Z <-- Z - 1, (Z) <-- Rr", "--------",
{"2", "2", "1", "1"}, ""},
{OP_ID(std_2), 0xd208, 0x8200, 1, OP_AVR2nRC, "10q0 qq1r rrrr 0qqq", OTY_XFRX|OTY_RALL,
@@ -384,7 +384,7 @@ const AVR_opcode_data avr_opcodes[164] = {
{OP_ID(lpm_2), 0xfe0f, 0x9004, 1, OP_AVR25, "1001 000d dddd 0100", OTY_XFRX|OTY_RALL,
"lpm", "Rd, Z", "Load Program Memory", "Rd <-- (Z)", "--------",
{"3", "3", "3", "n/a"}, ""},
{OP_ID(lpm_3), 0xfe0f, 0x9005, 1, OP_AVR25, "1001 000d dddd 0101", OTY_XFRX|OTY_RALL,
{OP_ID(lpm_3), 0xfe0f, 0x9005, 1, OP_AVR25, "1001 000d dddd 0101", OTY_XFRX|OTY_RALL|OTY_ZWRN,
"lpm", "Rd, Z+", "Load Program Memory and Post- Increment", "Rd <-- (Z), Z <-- Z + 1", "--------",
{"3", "3", "3", "n/a"}, ""},
{OP_ID(elpm_1), 0xffff, 0x95d8, 1, OP_AVR_L, "1001 0101 1101 1000", OTY_XFRX,
@@ -393,7 +393,7 @@ const AVR_opcode_data avr_opcodes[164] = {
{OP_ID(elpm_2), 0xfe0f, 0x9006, 1, OP_AVR_L, "1001 000d dddd 0110", OTY_XFRX|OTY_RALL,
"elpm", "Rd, Z", "Extended Load Program Memory", "Rd <-- (RAMPZ:Z)", "--------",
{"3", "3", "3", "n/a"}, ""},
{OP_ID(elpm_3), 0xfe0f, 0x9007, 1, OP_AVR_L, "1001 000d dddd 0111", OTY_XFRX|OTY_RALL,
{OP_ID(elpm_3), 0xfe0f, 0x9007, 1, OP_AVR_L, "1001 000d dddd 0111", OTY_XFRX|OTY_RALL|OTY_ZWRN,
"elpm", "Rd, Z+", "Extended Load Program Memory and Post-Increment", "Rd <-- (RAMPZ:Z), Z <-- Z + 1", "--------",
{"3", "3", "3", "n/a"}, ""},
{OP_ID(spm), 0xffff, 0x95e8, 1, OP_AVR25, "1001 0101 1110 1000", OTY_XFRX,
@@ -589,7 +589,7 @@ const AVR_opcode_data avr_opcodes[164] = {
{"1-3", "1-3", "1-3", "1/2"}, ""},
};
// Return whether or not the giveb 16-bit opcode has a 16-bit address argument
// Return whether or not the given 16-bit opcode has a 16-bit address argument
int is_opcode32(int op) {
return
(op & 0xfe0e) == 0x940e || // call

View File

@@ -152,7 +152,7 @@ void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo, Disasm
// Apply register formula
int regword = 0;
switch(oc->type & OTY_RMASK) {
switch(oc->type & OTY_REG_MASK) {
case OTY_REVN: // Even registers r0, r2, ..., r30
Rd *= 2, Rr *= 2;
regword = 1; // movw
@@ -175,6 +175,27 @@ void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo, Disasm
Ra = (Ra & 0xf) | ((Ra >> 1) & 0x30) | ((Ra & 0x10) << 2) | (((Ra & 0x10) ^ 0x10) << 3);
}
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) {
case OTY_XWRN:
if(Rd == 26 || Rd == 27 || Rr == 26 || Rr == 27)
add_comment(line, "Warning: the result of this operation is undefined\n");
break;
case OTY_YWRN:
if(Rd == 28 || Rd == 29 || Rr == 28 || Rr == 29)
add_comment(line, "Warning: the result of this operation is undefined\n");
break;
case OTY_ZWRN:
if(Rd == 30 || Rd == 31 || Rr == 30 || Rr == 31)
add_comment(line, "Warning: the result of this operation is undefined\n");
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;
@@ -207,16 +228,8 @@ void disassemble(const char *buf, int addr, int opcode, AVR_opcode mnemo, Disasm
Register_JumpCall(addr, target, mnemo, is_function);
is_jumpcall = 1;
break;
default:
pmsg_warning("OPCODE_%s has an unexpected number %d of k bits\n",
oc->idname, Nk);
}
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;
for(const char *o = oc->operands; *o && c-line->code < 255; o++) {
switch(*o) {
case 'R':
@@ -370,8 +383,7 @@ int disasm(const char *buf, int buflen, int addr, int leadin, int leadout) {
Pos += oplen;
} else {
term_out(".word 0x%02x%02x ; Invalid opcode at 0x%04x\n",
buf[Pos + 1] & 0xff, buf[Pos] & 0xff, disasm_wrap(Pos + addr));
term_out(".word 0x%02x%02x ; Invalid opcode\n", buf[Pos+1] & 0xff, buf[Pos] & 0xff);
Pos += 2;
}
}

View File

@@ -1583,30 +1583,38 @@ typedef enum {
#define PART_ALL (PART_AVR_XM|OP_AVR_L|OP_AVR_XL) // All but RC (the latter conflicts)
// Opcode types
#define OTY_RMASK 7 // Register formula mask
#define OTY_REG_MASK 7 // Register formula mask
#define OTY_RNONE 0 // No registers addressed in this opcode
#define OTY_RALL 1 // Opcode can use all 32 registers (both Rd, Rr)
#define OTY_REVN 2 // Opcode only uses even registers (Rd *= 2, Rr *= 2)
#define OTY_RUPP 3 // Opcode only uses upper registers (Rd += 16, Rr += 16)
#define OTY_RW24 4 // Opcode only uses r24, r26, r28, r30 (Rd = Rd *2 + 24)
#define OTY_EXTERNAL 0x010 // Opcode might r/w either I/O region or memory
#define OTY_ALBI 0x020 // Arithmetic, logic or bitwise operation
#define OTY_ALBX 0x030 // Arithmetic, logic or bitwise operation (external)
#define OTY_XFRI 0x040 // Data transfer (only affecting registers)
#define OTY_XFRX 0x050 // Data transfer (between external I/O or memory and regs)
#define OTY_JMPI 0x080 // Jump to potentially anywhere in flash (jmp, ijmp, eijmp)
#define OTY_JMPX 0x090 // Jump to potentially anywhere in flash (calls and ret/i)
#define OTY_RJMI 0x100 // Relative jump rjmp, range [-4094, 4096] bytes
#define OTY_RJMX 0x110 // Relative call rcall, range [-4094, 4096] bytes
#define OTY_BRAI 0x200 // Conditional branch, range [-126, 128] bytes
#define OTY_SKPI 0x400 // Conditional skip, range [0, 4] bytes (cpse, sbrc, sbrs)
#define OTY_SKPX 0x410 // Conditional skip, range [0, 4] bytes (sbic, sbis)
#define OTY_MCUI 0x800 // nop and wdr
#define OTY_MCUX 0x810 // sleep and break
#define OTY_EXTERNAL 0x008 // Opcode might r/w either I/O region or memory
#define OTY_ALIAS 0x1000 // Opcode is a strict alias for another one, eg, sbr == ori
#define OTY_CONSTRAINT 0x2000 // Opcode has constraints: Rr == Rd (tst, clr, lsl, rol)
#define OTY_TYPE_MASK 0x78 // OPCODE type mask
#define OTY_ITYPE_MASK 0x70 // OPCODE type mask matching OTY_xxxI types
#define OTY_MCUI 0x00 // nop and wdr
#define OTY_MCUX 0x08 // sleep and break
#define OTY_ALBI 0x10 // Arithmetic, logic or bitwise operation
#define OTY_ALBX 0x18 // Arithmetic, logic or bitwise operation (external)
#define OTY_XFRI 0x20 // Data transfer (only affecting registers)
#define OTY_XFRX 0x28 // Data transfer (between external I/O or memory and regs)
#define OTY_JMPI 0x30 // Jump to potentially anywhere in flash (jmp, ijmp, eijmp)
#define OTY_JMPX 0x38 // Jump to potentially anywhere in flash (calls and ret/i)
#define OTY_RJMI 0x40 // Relative jump rjmp, range [-4094, 4096] bytes
#define OTY_RJMX 0x48 // Relative call rcall, range [-4094, 4096] bytes
#define OTY_BRAI 0x50 // Conditional branch, range [-126, 128] bytes
#define OTY_SKPI 0x60 // Conditional skip, range [0, 4] bytes (cpse, sbrc, sbrs)
#define OTY_SKPX 0x68 // Conditional skip, range [0, 4] bytes (sbic, sbis)
#define OTY_ALIAS 0x100 // Opcode is a strict alias for another one, eg, sbr == ori
#define OTY_CONSTRAINT 0x200 // Opcode has constraints: Rr == Rd (tst, clr, lsl, rol)
#define OTY_WARN_MASK 0xc00 // OPCODE warning mask
#define OTY_XWRN 0x400 // Operand register must not be r27/r28
#define OTY_YWRN 0x800 // Operand register must not be r29/r30
#define OTY_ZWRN 0xc00 // Operand register must not be r29/r30
typedef struct {
AVR_opcode mnemo; // Eg, OPCODE_add