Move useful CMDBIT/part functions from developer_opts.c to avrpart.c
This commit is contained in:
parent
62dcc2e6e8
commit
004b46b594
342
src/avrpart.c
342
src/avrpart.c
|
@ -71,6 +71,21 @@ void avr_free_opcode(OPCODE * op)
|
||||||
free(op);
|
free(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns position 0..31 of highest bit set or INT_MIN if no bit is set
|
||||||
|
int intlog2(unsigned int n) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(!n)
|
||||||
|
return INT_MIN;
|
||||||
|
|
||||||
|
for(ret = 0; n >>= 1; ret++)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* avr_set_bits()
|
* avr_set_bits()
|
||||||
*
|
*
|
||||||
|
@ -126,6 +141,101 @@ int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* avr_set_addr_mem()
|
||||||
|
*
|
||||||
|
* Set address bits in the specified command based on the memory, opcode and
|
||||||
|
* address; addr must be a word address for flash or, for all other memories,
|
||||||
|
* a byte address; returns 0 on success and -1 on error (no memory or no
|
||||||
|
* opcode) or, if positive, bn+1 where bn is bit number of the highest
|
||||||
|
* necessary bit that the opcode does not provide.
|
||||||
|
*/
|
||||||
|
int avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr) {
|
||||||
|
int ret, isflash, lo, hi, memsize, pagesize;
|
||||||
|
OPCODE *op;
|
||||||
|
|
||||||
|
if(!mem)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(!(op = mem->op[opnum]))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
isflash = !strcmp(mem->desc, "flash"); // ISP parts have only one flash-like memory
|
||||||
|
memsize = mem->size >> isflash; // word addresses for flash
|
||||||
|
pagesize = mem->page_size >> isflash;
|
||||||
|
|
||||||
|
// compute range lo..hi of needed address bits
|
||||||
|
switch(opnum) {
|
||||||
|
case AVR_OP_READ:
|
||||||
|
case AVR_OP_WRITE:
|
||||||
|
case AVR_OP_READ_LO:
|
||||||
|
case AVR_OP_READ_HI:
|
||||||
|
case AVR_OP_WRITE_LO:
|
||||||
|
case AVR_OP_WRITE_HI:
|
||||||
|
lo = 0;
|
||||||
|
hi = intlog2(memsize-1); // memsize = 1 implies no addr bit is needed
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVR_OP_LOADPAGE_LO:
|
||||||
|
case AVR_OP_LOADPAGE_HI:
|
||||||
|
lo = 0;
|
||||||
|
hi = intlog2(pagesize-1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVR_OP_LOAD_EXT_ADDR:
|
||||||
|
lo = 16;
|
||||||
|
hi = intlog2(memsize-1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVR_OP_WRITEPAGE:
|
||||||
|
lo = intlog2(pagesize);
|
||||||
|
hi = intlog2(memsize-1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVR_OP_CHIP_ERASE:
|
||||||
|
case AVR_OP_PGM_ENABLE:
|
||||||
|
default:
|
||||||
|
lo = 0;
|
||||||
|
hi = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unless it's load extended address, ISP chips only deal with 16 bit addresses
|
||||||
|
if(opnum != AVR_OP_LOAD_EXT_ADDR && hi > 15)
|
||||||
|
hi = 15;
|
||||||
|
|
||||||
|
unsigned char avail[32];
|
||||||
|
memset(avail, 0, sizeof avail);
|
||||||
|
|
||||||
|
for(int i=0; i<32; i++) {
|
||||||
|
if(op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
||||||
|
int bitno, j, bit;
|
||||||
|
unsigned char mask;
|
||||||
|
|
||||||
|
bitno = op->bit[i].bitno & 31;
|
||||||
|
j = 3 - i / 8;
|
||||||
|
bit = i % 8;
|
||||||
|
mask = 1 << bit;
|
||||||
|
avail[bitno] = 1;
|
||||||
|
|
||||||
|
// 'a' bit with number outside bit range [lo, hi] is set to 0
|
||||||
|
if (bitno >= lo && bitno <= hi? (addr >> bitno) & 1: 0)
|
||||||
|
cmd[j] = cmd[j] | mask;
|
||||||
|
else
|
||||||
|
cmd[j] = cmd[j] & ~mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if(lo >= 0 && hi < 32 && lo <= hi)
|
||||||
|
for(int bn=lo; bn <= hi; bn++)
|
||||||
|
if(!avail[bn]) // necessary bit bn misses in opcode
|
||||||
|
ret = bn+1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* avr_set_input()
|
* avr_set_input()
|
||||||
*
|
*
|
||||||
|
@ -239,7 +349,6 @@ static char * bittype(int type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Elementary functions dealing with AVRMEM structures
|
*** Elementary functions dealing with AVRMEM structures
|
||||||
***/
|
***/
|
||||||
|
@ -556,12 +665,10 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Elementary functions dealing with AVRPART structures
|
* Elementary functions dealing with AVRPART structures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
AVRPART * avr_new_part(void)
|
AVRPART * avr_new_part(void)
|
||||||
{
|
{
|
||||||
AVRPART * p;
|
AVRPART * p;
|
||||||
|
@ -819,3 +926,232 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
|
||||||
if (buf)
|
if (buf)
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char cmdbitchar(CMDBIT cb) {
|
||||||
|
switch(cb.type) {
|
||||||
|
case AVR_CMDBIT_IGNORE:
|
||||||
|
return 'x';
|
||||||
|
case AVR_CMDBIT_VALUE:
|
||||||
|
return cb.value? '1': '0';
|
||||||
|
case AVR_CMDBIT_ADDRESS:
|
||||||
|
return 'a';
|
||||||
|
case AVR_CMDBIT_INPUT:
|
||||||
|
return 'i';
|
||||||
|
case AVR_CMDBIT_OUTPUT:
|
||||||
|
return 'o';
|
||||||
|
default:
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *cmdbitstr(CMDBIT cb) {
|
||||||
|
char space[32];
|
||||||
|
|
||||||
|
*space = cmdbitchar(cb);
|
||||||
|
if(*space == 'a')
|
||||||
|
sprintf(space+1, "%d", cb.bitno);
|
||||||
|
else
|
||||||
|
space[1] = 0;
|
||||||
|
|
||||||
|
return strdup(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *opcodename(int opnum) {
|
||||||
|
switch(opnum) {
|
||||||
|
case AVR_OP_READ:
|
||||||
|
return "read";
|
||||||
|
case AVR_OP_WRITE:
|
||||||
|
return "write";
|
||||||
|
case AVR_OP_READ_LO:
|
||||||
|
return "read_lo";
|
||||||
|
case AVR_OP_READ_HI:
|
||||||
|
return "read_hi";
|
||||||
|
case AVR_OP_WRITE_LO:
|
||||||
|
return "write_lo";
|
||||||
|
case AVR_OP_WRITE_HI:
|
||||||
|
return "write_hi";
|
||||||
|
case AVR_OP_LOADPAGE_LO:
|
||||||
|
return "loadpage_lo";
|
||||||
|
case AVR_OP_LOADPAGE_HI:
|
||||||
|
return "loadpage_hi";
|
||||||
|
case AVR_OP_LOAD_EXT_ADDR:
|
||||||
|
return "load_ext_addr";
|
||||||
|
case AVR_OP_WRITEPAGE:
|
||||||
|
return "writepage";
|
||||||
|
case AVR_OP_CHIP_ERASE:
|
||||||
|
return "chip_erase";
|
||||||
|
case AVR_OP_PGM_ENABLE:
|
||||||
|
return "pgm_enable";
|
||||||
|
default:
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Unique string representation of an opcode
|
||||||
|
char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
||||||
|
char cb, space[1024], *sp = space;
|
||||||
|
int compact = 1;
|
||||||
|
|
||||||
|
if(!op)
|
||||||
|
return strdup("NULL");
|
||||||
|
|
||||||
|
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
||||||
|
for(int i=31; i >= 0; i--)
|
||||||
|
if(op->bit[i].type == AVR_CMDBIT_ADDRESS)
|
||||||
|
if(i<8 || i>23 || op->bit[i].bitno != (opnum == AVR_OP_LOAD_EXT_ADDR? i+8: i-8))
|
||||||
|
compact = 0;
|
||||||
|
|
||||||
|
if(detailed)
|
||||||
|
*sp++ = '"';
|
||||||
|
|
||||||
|
for(int i=31; i >= 0; i--) {
|
||||||
|
*sp++ = cb = cmdbitchar(op->bit[i]);
|
||||||
|
if(compact) {
|
||||||
|
if(i && i%8 == 0)
|
||||||
|
*sp++ = '-', *sp++ = '-';
|
||||||
|
else if(i && i%4 == 0)
|
||||||
|
*sp++ = '.';
|
||||||
|
} else {
|
||||||
|
if(cb == 'a') {
|
||||||
|
sprintf(sp, "%d", op->bit[i].bitno);
|
||||||
|
sp += strlen(sp);
|
||||||
|
}
|
||||||
|
if(i) {
|
||||||
|
if(detailed)
|
||||||
|
*sp++ = ' ';
|
||||||
|
if(i%8 == 0)
|
||||||
|
*sp++ = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(detailed)
|
||||||
|
*sp++ = '"';
|
||||||
|
*sp = 0;
|
||||||
|
|
||||||
|
return strdup(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Match STRING against the partname pattern PATTERN, returning 1 if it
|
||||||
|
* matches, 0 if not. NOTE: part_match() is a modified old copy of !fnmatch()
|
||||||
|
* from the GNU C Library (published under GLP v2). Used for portability.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline static int fold(int c) {
|
||||||
|
return (c >= 'A' && c <= 'Z')? c+('a'-'A'): c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int part_match(const char *pattern, const char *string) {
|
||||||
|
unsigned char c;
|
||||||
|
const char *p = pattern, *n = string;
|
||||||
|
|
||||||
|
if(!*n) // AVRDUDE specialty: empty string never matches
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while((c = fold(*p++))) {
|
||||||
|
switch(c) {
|
||||||
|
case '?':
|
||||||
|
if(*n == 0)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
c = fold(*p++);
|
||||||
|
if(fold(*n) != c)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
for(c = *p++; c == '?' || c == '*'; c = *p++)
|
||||||
|
if(c == '?' && *n++ == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(c == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned char c1 = fold(c == '\\'? *p : c); // This char
|
||||||
|
|
||||||
|
for(--p; *n; ++n) // Recursively check reminder of string for *
|
||||||
|
if((c == '[' || fold(*n) == c1) && part_match(p, n) == 1)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
{
|
||||||
|
int negate;
|
||||||
|
|
||||||
|
if(*n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
negate = (*p == '!' || *p == '^');
|
||||||
|
if(negate)
|
||||||
|
++p;
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
for(;;) {
|
||||||
|
unsigned char cstart = c, cend = c;
|
||||||
|
|
||||||
|
if(c == '\\')
|
||||||
|
cstart = cend = *p++;
|
||||||
|
|
||||||
|
cstart = cend = fold(cstart);
|
||||||
|
|
||||||
|
if(c == 0) // [ (unterminated)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
c = fold(c);
|
||||||
|
|
||||||
|
if(c == '-' && *p != ']') {
|
||||||
|
cend = *p++;
|
||||||
|
if(cend == '\\')
|
||||||
|
cend = *p++;
|
||||||
|
if(cend == 0)
|
||||||
|
return 0;
|
||||||
|
cend = fold(cend);
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fold(*n) >= cstart && fold(*n) <= cend)
|
||||||
|
goto matched;
|
||||||
|
|
||||||
|
if(c == ']')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!negate)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
matched:;
|
||||||
|
while(c != ']') { // Skip the rest of the [...] that already matched
|
||||||
|
|
||||||
|
if(c == 0) // [... (unterminated)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if(c == '\\') // XXX 1003.2d11 is unclear if this is right
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
if(negate)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(c != fold(*n))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *n == 0;
|
||||||
|
}
|
||||||
|
|
|
@ -51,114 +51,6 @@
|
||||||
#include "developer_opts.h"
|
#include "developer_opts.h"
|
||||||
#include "developer_opts_private.h"
|
#include "developer_opts_private.h"
|
||||||
|
|
||||||
char cmdbitchar(CMDBIT cb) {
|
|
||||||
switch(cb.type) {
|
|
||||||
case AVR_CMDBIT_IGNORE:
|
|
||||||
return 'x';
|
|
||||||
case AVR_CMDBIT_VALUE:
|
|
||||||
return cb.value? '1': '0';
|
|
||||||
case AVR_CMDBIT_ADDRESS:
|
|
||||||
return 'a';
|
|
||||||
case AVR_CMDBIT_INPUT:
|
|
||||||
return 'i';
|
|
||||||
case AVR_CMDBIT_OUTPUT:
|
|
||||||
return 'o';
|
|
||||||
default:
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *cmdbitstr(CMDBIT cb) {
|
|
||||||
char space[32];
|
|
||||||
|
|
||||||
*space = cmdbitchar(cb);
|
|
||||||
if(*space == 'a')
|
|
||||||
sprintf(space+1, "%d", cb.bitno);
|
|
||||||
else
|
|
||||||
space[1] = 0;
|
|
||||||
|
|
||||||
return strdup(space);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *opcodename(int opnum) {
|
|
||||||
switch(opnum) {
|
|
||||||
case AVR_OP_READ:
|
|
||||||
return "read";
|
|
||||||
case AVR_OP_WRITE:
|
|
||||||
return "write";
|
|
||||||
case AVR_OP_READ_LO:
|
|
||||||
return "read_lo";
|
|
||||||
case AVR_OP_READ_HI:
|
|
||||||
return "read_hi";
|
|
||||||
case AVR_OP_WRITE_LO:
|
|
||||||
return "write_lo";
|
|
||||||
case AVR_OP_WRITE_HI:
|
|
||||||
return "write_hi";
|
|
||||||
case AVR_OP_LOADPAGE_LO:
|
|
||||||
return "loadpage_lo";
|
|
||||||
case AVR_OP_LOADPAGE_HI:
|
|
||||||
return "loadpage_hi";
|
|
||||||
case AVR_OP_LOAD_EXT_ADDR:
|
|
||||||
return "load_ext_addr";
|
|
||||||
case AVR_OP_WRITEPAGE:
|
|
||||||
return "writepage";
|
|
||||||
case AVR_OP_CHIP_ERASE:
|
|
||||||
return "chip_erase";
|
|
||||||
case AVR_OP_PGM_ENABLE:
|
|
||||||
return "pgm_enable";
|
|
||||||
default:
|
|
||||||
return "???";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Unique string representation of an opcode
|
|
||||||
char *opcode2str(OPCODE *op, int opnum, int detailed) {
|
|
||||||
char cb, space[1024], *sp = space;
|
|
||||||
int compact = 1;
|
|
||||||
|
|
||||||
if(!op)
|
|
||||||
return strdup("NULL");
|
|
||||||
|
|
||||||
// Can the opcode be printed in a compact way? Only if address bits are systematic.
|
|
||||||
for(int i=31; i >= 0; i--)
|
|
||||||
if(op->bit[i].type == AVR_CMDBIT_ADDRESS)
|
|
||||||
if(i<8 || i>23 || op->bit[i].bitno != (opnum == AVR_OP_LOAD_EXT_ADDR? i+8: i-8))
|
|
||||||
compact = 0;
|
|
||||||
|
|
||||||
if(detailed)
|
|
||||||
*sp++ = '"';
|
|
||||||
|
|
||||||
for(int i=31; i >= 0; i--) {
|
|
||||||
*sp++ = cb = cmdbitchar(op->bit[i]);
|
|
||||||
if(compact) {
|
|
||||||
if(i && i%8 == 0)
|
|
||||||
*sp++ = '-', *sp++ = '-';
|
|
||||||
else if(i && i%4 == 0)
|
|
||||||
*sp++ = '.';
|
|
||||||
} else {
|
|
||||||
if(cb == 'a') {
|
|
||||||
sprintf(sp, "%d", op->bit[i].bitno);
|
|
||||||
sp += strlen(sp);
|
|
||||||
}
|
|
||||||
if(i) {
|
|
||||||
if(detailed)
|
|
||||||
*sp++ = ' ';
|
|
||||||
if(i%8 == 0)
|
|
||||||
*sp++ = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(detailed)
|
|
||||||
*sp++ = '"';
|
|
||||||
*sp = 0;
|
|
||||||
|
|
||||||
return strdup(space);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return 0 if op code would encode (essentially) the same SPI command
|
// return 0 if op code would encode (essentially) the same SPI command
|
||||||
static int opcodecmp(OPCODE *op1, OPCODE *op2, int opnum) {
|
static int opcodecmp(OPCODE *op1, OPCODE *op2, int opnum) {
|
||||||
char *opstr1, *opstr2, *p;
|
char *opstr1, *opstr2, *p;
|
||||||
|
@ -215,19 +107,6 @@ static void printallopcodes(AVRPART *p, const char *d, OPCODE **opa) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns position 0..31 of highest bit set or INT_MIN if no bit is set
|
|
||||||
int intlog2(unsigned int n) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if(!n)
|
|
||||||
return INT_MIN;
|
|
||||||
|
|
||||||
for(ret = 0; n >>= 1; ret++)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// mnemonic characterisation of flags
|
// mnemonic characterisation of flags
|
||||||
static char *parttype(AVRPART *p) {
|
static char *parttype(AVRPART *p) {
|
||||||
|
@ -295,99 +174,6 @@ static void checkaddr(int memsize, int pagesize, int opnum, OPCODE *op, AVRPART
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* avr_set_addr_mem()
|
|
||||||
*
|
|
||||||
* Set address bits in the specified command based on the memory, opcode and
|
|
||||||
* address; addr must be a word address for flash or, for all other memories,
|
|
||||||
* a byte address; returns 0 on success and -1 on error (no memory or no
|
|
||||||
* opcode) or, if positive, bn+1 where bn is bit number of the highest
|
|
||||||
* necessary bit that the opcode does not provide.
|
|
||||||
*/
|
|
||||||
int avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr) {
|
|
||||||
int ret, isflash, lo, hi, memsize, pagesize;
|
|
||||||
OPCODE *op;
|
|
||||||
|
|
||||||
if(!mem)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(!(op = mem->op[opnum]))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
isflash = !strcmp(mem->desc, "flash"); // ISP parts have only one flash-like memory
|
|
||||||
memsize = mem->size >> isflash; // word addresses for flash
|
|
||||||
pagesize = mem->page_size >> isflash;
|
|
||||||
|
|
||||||
// compute range lo..hi of needed address bits
|
|
||||||
switch(opnum) {
|
|
||||||
case AVR_OP_READ:
|
|
||||||
case AVR_OP_WRITE:
|
|
||||||
case AVR_OP_READ_LO:
|
|
||||||
case AVR_OP_READ_HI:
|
|
||||||
case AVR_OP_WRITE_LO:
|
|
||||||
case AVR_OP_WRITE_HI:
|
|
||||||
lo = 0;
|
|
||||||
hi = intlog2(memsize-1); // memsize = 1 implies no addr bit is needed
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AVR_OP_LOADPAGE_LO:
|
|
||||||
case AVR_OP_LOADPAGE_HI:
|
|
||||||
lo = 0;
|
|
||||||
hi = intlog2(pagesize-1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AVR_OP_LOAD_EXT_ADDR:
|
|
||||||
lo = 16;
|
|
||||||
hi = intlog2(memsize-1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AVR_OP_WRITEPAGE:
|
|
||||||
lo = intlog2(pagesize);
|
|
||||||
hi = intlog2(memsize-1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AVR_OP_CHIP_ERASE:
|
|
||||||
case AVR_OP_PGM_ENABLE:
|
|
||||||
default:
|
|
||||||
lo = 0;
|
|
||||||
hi = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unless it's load extended address, ISP chips only deal with 16 bit addresses
|
|
||||||
if(opnum != AVR_OP_LOAD_EXT_ADDR && hi > 15)
|
|
||||||
hi = 15;
|
|
||||||
|
|
||||||
unsigned char avail[32];
|
|
||||||
memset(avail, 0, sizeof avail);
|
|
||||||
|
|
||||||
for(int i=0; i<32; i++) {
|
|
||||||
if(op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
|
||||||
int bitno, j, bit;
|
|
||||||
unsigned char mask;
|
|
||||||
|
|
||||||
bitno = op->bit[i].bitno & 31;
|
|
||||||
j = 3 - i / 8;
|
|
||||||
bit = i % 8;
|
|
||||||
mask = 1 << bit;
|
|
||||||
avail[bitno] = 1;
|
|
||||||
|
|
||||||
// 'a' bit with number outside bit range [lo, hi] is set to 0
|
|
||||||
if (bitno >= lo && bitno <= hi? (addr >> bitno) & 1: 0)
|
|
||||||
cmd[j] = cmd[j] | mask;
|
|
||||||
else
|
|
||||||
cmd[j] = cmd[j] & ~mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
if(lo >= 0 && hi < 32 && lo <= hi)
|
|
||||||
for(int bn=lo; bn <= hi; bn++)
|
|
||||||
if(!avail[bn]) // necessary bit bn misses in opcode
|
|
||||||
ret = bn+1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *dev_sprintf(const char *fmt, ...) {
|
static char *dev_sprintf(const char *fmt, ...) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
@ -841,126 +627,6 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Match STRING against the partname pattern PATTERN, returning 1 if it
|
|
||||||
* matches, 0 if not. NOTE: part_match() is a modified old copy of !fnmatch()
|
|
||||||
* from the GNU C Library (published under GLP v2). Used for portability.
|
|
||||||
*/
|
|
||||||
|
|
||||||
inline static int fold(int c) {
|
|
||||||
return (c >= 'A' && c <= 'Z')? c+('a'-'A'): c;
|
|
||||||
}
|
|
||||||
|
|
||||||
int part_match(const char *pattern, const char *string) {
|
|
||||||
unsigned char c;
|
|
||||||
const char *p = pattern, *n = string;
|
|
||||||
|
|
||||||
if(!*n) // AVRDUDE specialty: empty string never matches
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while((c = fold(*p++))) {
|
|
||||||
switch(c) {
|
|
||||||
case '?':
|
|
||||||
if(*n == 0)
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\\':
|
|
||||||
c = fold(*p++);
|
|
||||||
if(fold(*n) != c)
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '*':
|
|
||||||
for(c = *p++; c == '?' || c == '*'; c = *p++)
|
|
||||||
if(c == '?' && *n++ == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(c == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned char c1 = fold(c == '\\'? *p : c); // This char
|
|
||||||
|
|
||||||
for(--p; *n; ++n) // Recursively check reminder of string for *
|
|
||||||
if((c == '[' || fold(*n) == c1) && part_match(p, n) == 1)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case '[':
|
|
||||||
{
|
|
||||||
int negate;
|
|
||||||
|
|
||||||
if(*n == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
negate = (*p == '!' || *p == '^');
|
|
||||||
if(negate)
|
|
||||||
++p;
|
|
||||||
|
|
||||||
c = *p++;
|
|
||||||
for(;;) {
|
|
||||||
unsigned char cstart = c, cend = c;
|
|
||||||
|
|
||||||
if(c == '\\')
|
|
||||||
cstart = cend = *p++;
|
|
||||||
|
|
||||||
cstart = cend = fold(cstart);
|
|
||||||
|
|
||||||
if(c == 0) // [ (unterminated)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
c = *p++;
|
|
||||||
c = fold(c);
|
|
||||||
|
|
||||||
if(c == '-' && *p != ']') {
|
|
||||||
cend = *p++;
|
|
||||||
if(cend == '\\')
|
|
||||||
cend = *p++;
|
|
||||||
if(cend == 0)
|
|
||||||
return 0;
|
|
||||||
cend = fold(cend);
|
|
||||||
|
|
||||||
c = *p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fold(*n) >= cstart && fold(*n) <= cend)
|
|
||||||
goto matched;
|
|
||||||
|
|
||||||
if(c == ']')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!negate)
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
matched:;
|
|
||||||
while(c != ']') { // Skip the rest of the [...] that already matched
|
|
||||||
|
|
||||||
if(c == 0) // [... (unterminated)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
c = *p++;
|
|
||||||
if(c == '\\') // XXX 1003.2d11 is unclear if this is right
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
if(negate)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if(c != fold(*n))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *n == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -p */[cdosw*]
|
// -p */[cdosw*]
|
||||||
void dev_output_part_defs(char *partdesc) {
|
void dev_output_part_defs(char *partdesc) {
|
||||||
|
|
Loading…
Reference in New Issue