Utilise avr_opcodes.c functions

This commit is contained in:
Stefan Rueger
2026-04-01 19:00:21 +01:00
parent 29f319b38f
commit e7532789af
2 changed files with 14 additions and 26 deletions

View File

@@ -1761,6 +1761,9 @@ extern "C" {
char *avr_cc_buffer(size_t n);
// Shortcut for testing whether a 16-bit opcode is a certain mnemonic (rjmp, ret, ...)
#define isop(op16, code) op16_is_mnemo(op16, MNEMO_ ## code)
int op16_is_mnemo(int op16, AVR_mnemo mnemo);
int is_opcode32(int op16);
int op_width(int op16);

View File

@@ -345,15 +345,6 @@ static int nmeta(int mcode, int flashsize) {
// Need to know a bit about avr opcodes, in particular jmp and rjmp for patching vector table
#define ret_opcode 0x9508
// Is the opcode an rjmp, ie, a relative jump [.-4096, .+4094]
static int isRjmp(uint16_t opcode) {
return (opcode & 0xf000) == 0xc000;
}
/*
* Map distances to [-flashsize/2, flashsize/2) for smaller devices. As rjmp can go +/- 4 kB, so
* smaller flash than 8k (eg, 4k) benefit from wrap around logic.
@@ -415,12 +406,6 @@ int addr_jmp(uint32_t jmp) {
}
// Is the instruction word the lower 16 bit part of a jmp instruction?
static int isJmp(uint16_t opcode) {
return (opcode & 0xfe0e) == 0x940c;
}
// Assemble little endian 32-bit word from buffer
uint32_t buf2uint32(const unsigned char *buf) {
return buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24;
@@ -497,9 +482,9 @@ static int reset2addr(const unsigned char *opcode, int vecsz, int flashsize, int
op16 = buf2uint16(opcode); // First word of the jmp or the full rjmp
op32 = vecsz == 2? op16: buf2uint32(opcode);
if(vecsz == 4 && isJmp(op16)) {
if(vecsz == 4 && isop(op16, jmp)) {
addr = addr_jmp(op32); // Accept compiler's destination (do not normalise)
} else if(isRjmp(op16)) { // rjmp might be generated for larger parts, too
} else if(isop(op16, rjmp)) { // rjmp might be generated for larger parts, too
addr = dist_rjmp(op16, flashsize);
while(addr < 0) // If rjmp was backwards
addr += flashsize; // OK for small parts, likely(!) OK if flashsize is a power of 2
@@ -628,7 +613,7 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
bool llvectors = firstbeg == 0 && firstlen >= ur.uP.ninterrupts*vecsz; // Looks like vector table
for(int i=0; llvectors && i<ur.uP.ninterrupts*vecsz; i+=vecsz) {
uint16_t op16 = buf2uint16(flm->buf+i);
if(!isRjmp(op16) && !(vecsz == 4 && isJmp(op16)))
if(!isop(op16, rjmp) && !(vecsz == 4 && isop(op16, jmp)))
llvectors = 0;
}
@@ -916,7 +901,7 @@ static void urbootPutVersion(const PROGRAMMER *pgm, char *buf, uint16_t ver, uin
if(hi >= 072) { // These are urboot versions
sprintf(buf, "u%d.%d ", hi>>3, hi&7);
buf += strlen(buf);
*buf++ = (hi < 077 && (type & UR_PGMWRITEPAGE)) || (hi >= 077 && rjmpwp != ret_opcode)? 'w': '-';
*buf++ = (hi < 077 && (type & UR_PGMWRITEPAGE)) || (hi >= 077 && !isop(rjmpwp, ret))? 'w': '-';
*buf++ = type & UR_EEPROM? 'e': '-';
if(hi >= 076) {
if(hi > 077) // From version 8.0 it's always urprotocol
@@ -1340,7 +1325,7 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
Return("please specify -x bootsize=<num> and, if needed, %s-x eepromrw",
ur.boothigh? "-x vectornum=<num> or ": "");
uint16_t v16 = 0xffff, rjmpwp = ret_opcode;
uint16_t v16 = 0xffff, rjmpwp = 0x9508; // 0x9508 is the ret opcode
// Sporting chance that we can read top flash to get intell about bootloader?
if(ur.boothigh && (!ur.urprotocol || (ur.urfeatures & UB_READ_FLASH))) {
@@ -1357,7 +1342,7 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
v16 = buf2uint16(spc+4); // Combo word for neatly printed version line of urboot bootloader
// Extensively check this is an urboot bootloader v7.2 .. v12.7 == 0147 and extract properties
if(urver >= 072 && urver <= 0147 && (isRjmp(rjmpwp) || rjmpwp == ret_opcode)) { // Prob urboot
if(urver >= 072 && urver <= 0147 && (isop(rjmpwp, rjmp) || isop(rjmpwp, ret))) { // Prob urboot
if(urver < 075) { // Early urboot versions don't offer many sanity checks
ur.blurversion = urver;
ur.bleepromrw = iseeprom_cap(cap);
@@ -1369,7 +1354,7 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
if(blsize >= 64 && blsize <= 2048 && vectnum <= ur.uP.ninterrupts) { // Within range
int dfromend = dist_rjmp(rjmpwp, ur.uP.flashsize) - 4;
// Further check whether writepage() rjmp opcode jumps backwards into bootloader
if(rjmpwp == ret_opcode || (dfromend >= -blsize && dfromend < -6)) { // Due diligence
if(isop(rjmpwp, ret) || (dfromend >= -blsize && dfromend < -6)) { // Due diligence
if(ur.xbootsize) {
if(flm->size - blsize != ur.blstart) {
pmsg_warning("urboot bootloader size %d explicitly overwritten by -x bootsize=%d\n",
@@ -1419,7 +1404,7 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
uint16_t reset16 = buf2uint16(spc);
if(isRjmp(reset16)) { // rjmp op code (could be from a large or a small part)
if(isop(reset16, rjmp)) { // rjmp op code (could be from a large or a small part)
if((flm->size & (flm->size-1)) == 0) { // Flash size a power of 2? True for small parts
int guess = dist_rjmp(reset16, ur.uP.flashsize); // Relative destination to reset vector
while(guess < 0) // Convert to absolute address
@@ -1431,7 +1416,7 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
ur.pfend = guess - 1;
}
}
} else if(vecsz == 4 && isJmp(reset16)) { // Jmp op code
} else if(vecsz == 4 && isop(reset16, jmp)) { // Jmp op code
int guess = addr_jmp(buf2uint32(spc));
if(guess < flm->size)
if((guess & (flm->page_size-1)) == 0) // Page aligned? Good
@@ -1469,14 +1454,14 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
op16 = 0;
} else if(wasop32) { // Skip opcode evaluation
wasop32 = 0;
} else if(isRjmp(opcode) && toend > 4) { // 4 top bytes of bl are data, not rjmp
} else if(isop(opcode, rjmp) && toend > 4) { // 4 top bytes of bl are data, not rjmp
// Does that rjmp end in the vector table?
if((dist = dist_rjmp(opcode, ur.uP.flashsize)) > toend &&
dist <= toend+ur.uP.ninterrupts*vecsz) { // "<=" for extended vector table
ur.vblvectornum = (dist-toend)/vecsz; // Solve for the vbl vector number
goto vblvecfound;
}
} else if(isJmp(opcode) && toend > 6) { // 4 top bytes are data + 2 the jmp addr
} else if(isop(opcode, jmp) && toend > 6) { // 4 top bytes are data + 2 the jmp addr
op16 = opcode;
wasjmp = 1; // Look at destination address in next loop iteration
} else if(is_opcode32(opcode)) { // Skip next opcode, too