#include "avr_watchdog.h"
// SREG bit names
-const char * _sreg_bit_name = "cznvshti";
+static const char * _sreg_bit_name __attribute__((unused));
+static const char * _sreg_bit_name = "cznvshti";
/*
* Handle "touching" registers, marking them changed.
#define SREG() if (avr->trace && donttrace == 0) {\
printf("%04x: \t\t\t\t\t\t\t\t\tSREG = ", avr->pc); \
for (int _sbi = 0; _sbi < 8; _sbi++)\
- printf("%c", avr->sreg[_sbi] ? toupper(_sreg_bit_name[_sbi]) : '.');\
+ printf("%c", SREG_BIT(_sbi) ? toupper(_sreg_bit_name[_sbi]) : '.');\
printf("\n");\
}
* if it's an IO register (> 31) also (try to) call any callback that was
* registered to track changes to that register.
*/
-static inline void _avr_set_r(avr_t * avr, uint16_t r, uint8_t v)
+static inline uint8_t _avr_set_r(avr_t * avr, uint8_t _sreg, uint16_t r, uint8_t v)
{
REG_TOUCH(avr, r);
if (r == R_SREG) {
- avr->data[R_SREG] = v;
+ _sreg = avr->data[R_SREG] = v;
// unsplit the SREG
SET_SREG_FROM(avr, v);
SREG();
}
+ avr->data[R_SREG] = _sreg;
if (r > 31) {
+ // flush SREG in case a module requires it.
+
avr_io_addr_t io = AVR_DATA_TO_IO(r);
if (avr->io[io].w.c)
avr->io[io].w.c(avr, r, v, avr->io[io].w.param);
}
} else
avr->data[r] = v;
+ _sreg = avr->data[R_SREG]; // reload
+ return _sreg;
}
-static inline void
-_avr_set_r16le(
- avr_t * avr,
- uint16_t r,
- uint16_t v)
-{
- _avr_set_r(avr, r, v);
- _avr_set_r(avr, r + 1, v >> 8);
-}
+#define _avr_set_r16le(_r, _v) \
+ { uint16_t __r = (_r), __v = (_v); \
+ _sreg = _avr_set_r(avr, _sreg, __r, __v); \
+ _sreg = _avr_set_r(avr, _sreg, __r + 1, __v >> 8); }
+
+#define _avr_set_r16le_hl(_r, _v) \
+ { uint16_t __r = (_r), __v = (_v); \
+ _sreg = _avr_set_r(avr, _sreg, __r + 1, __v >> 8); \
+ _sreg = _avr_set_r(avr, _sreg, __r , __v); }
-static inline void
-_avr_set_r16le_hl(
- avr_t * avr,
- uint16_t r,
- uint16_t v)
-{
- _avr_set_r(avr, r + 1, v >> 8);
- _avr_set_r(avr, r , v);
-}
/*
* Stack pointer access
inline void _avr_sp_set(avr_t * avr, uint16_t sp)
{
- _avr_set_r16le(avr, R_SPL, sp);
+ SREG_START(avr);
+ _avr_set_r16le(R_SPL, sp);
+ SREG_END(avr);
}
/*
* Set any address to a value; split between registers and SRAM
*/
-static inline void _avr_set_ram(avr_t * avr, uint16_t addr, uint8_t v)
+static inline uint8_t _avr_set_ram(avr_t * avr, uint8_t _sreg, uint16_t addr, uint8_t v)
{
if (addr < MAX_IOs + 31)
- _avr_set_r(avr, addr, v);
+ _sreg = _avr_set_r(avr, _sreg, addr, v);
else
avr_core_watch_write(avr, addr, v);
+ return _sreg;
}
/*
*/
static inline uint8_t _avr_get_ram(avr_t * avr, uint16_t addr)
{
- if (addr == R_SREG) {
- /*
- * SREG is special it's reconstructed when read
- * while the core itself uses the "shortcut" array
- */
- READ_SREG_INTO(avr, avr->data[R_SREG]);
-
- } else if (addr > 31 && addr < 31 + MAX_IOs) {
+ if (addr > 31 && addr < 31 + MAX_IOs) {
avr_io_addr_t io = AVR_DATA_TO_IO(addr);
if (avr->io[io].r.c)
static inline void _avr_push8(avr_t * avr, uint16_t v)
{
uint16_t sp = _avr_sp_get(avr);
- _avr_set_ram(avr, sp, v);
+ _avr_set_ram(avr, 0, sp, v);
_avr_sp_set(avr, sp-1);
}
uint16_t sp = _avr_sp_get(avr);
addr >>= 1;
for (int i = 0; i < avr->address_size; i++, addr >>= 8, sp--) {
- _avr_set_ram(avr, sp, addr);
+ _avr_set_ram(avr, 0, sp, addr);
}
_avr_sp_set(avr, sp);
return avr->address_size;
*
\****************************************************************************/
-static void
-_avr_flags_zns (struct avr_t * avr, uint8_t res)
+/* this flushes the caches SREG, call something then reload into the cache */
+#define SREG_FLUSH(__what) { SREG_END(avr); __what ; READ_SREG_INTO(avr, _sreg); }
+
+static uint8_t
+_avr_flags_zns (uint8_t _sreg, uint8_t res)
{
- avr->sreg[S_Z] = res == 0;
- avr->sreg[S_N] = (res >> 7) & 1;
- avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V];
+ SREG_SETBIT(S_Z, res == 0);
+ SREG_SETBIT(S_N, (res >> 7) & 1);
+ SREG_SETBIT(S_S, SREG_BIT(S_N) ^ SREG_BIT(S_V));
+ return _sreg;
}
-static void
-_avr_flags_zns16 (struct avr_t * avr, uint16_t res)
+static uint8_t
+_avr_flags_zns16 (uint8_t _sreg, uint16_t res)
{
- avr->sreg[S_Z] = res == 0;
- avr->sreg[S_N] = (res >> 15) & 1;
- avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V];
+ SREG_SETBIT(S_Z, res == 0);
+ SREG_SETBIT(S_N, (res >> 15) & 1);
+ SREG_SETBIT(S_S, SREG_BIT(S_N) ^ SREG_BIT(S_V));
+ return _sreg;
}
-static void
-_avr_flags_add_zns (struct avr_t * avr, uint8_t res, uint8_t rd, uint8_t rr)
+static uint8_t
+_avr_flags_add_zns (uint8_t _sreg, uint8_t res, uint8_t rd, uint8_t rr)
{
/* carry & half carry */
uint8_t add_carry = (rd & rr) | (rr & ~res) | (~res & rd);
- avr->sreg[S_H] = (add_carry >> 3) & 1;
- avr->sreg[S_C] = (add_carry >> 7) & 1;
+ SREG_SETBIT(S_H, (add_carry >> 3) & 1);
+ SREG_SETBIT(S_C, (add_carry >> 7) & 1);
/* overflow */
- avr->sreg[S_V] = (((rd & rr & ~res) | (~rd & ~rr & res)) >> 7) & 1;
-
+ SREG_SETBIT(S_V, (((rd & rr & ~res) | (~rd & ~rr & res)) >> 7) & 1);
/* zns */
- _avr_flags_zns(avr, res);
+ return _avr_flags_zns(_sreg, res);
}
-static void
-_avr_flags_sub_zns (struct avr_t * avr, uint8_t res, uint8_t rd, uint8_t rr)
+static uint8_t
+_avr_flags_sub_zns (uint8_t _sreg, uint8_t res, uint8_t rd, uint8_t rr)
{
/* carry & half carry */
uint8_t sub_carry = (~rd & rr) | (rr & res) | (res & ~rd);
- avr->sreg[S_H] = (sub_carry >> 3) & 1;
- avr->sreg[S_C] = (sub_carry >> 7) & 1;
+ SREG_SETBIT(S_H, (sub_carry >> 3) & 1);
+ SREG_SETBIT(S_C, (sub_carry >> 7) & 1);
/* overflow */
- avr->sreg[S_V] = (((rd & ~rr & ~res) | (~rd & rr & res)) >> 7) & 1;
+ SREG_SETBIT(S_V, (((rd & ~rr & ~res) | (~rd & rr & res)) >> 7) & 1);
/* zns */
- _avr_flags_zns(avr, res);
+ return _avr_flags_zns(_sreg, res);
}
-static void
-_avr_flags_Rzns (struct avr_t * avr, uint8_t res)
+static uint8_t
+_avr_flags_Rzns (uint8_t _sreg, uint8_t res)
{
if (res)
- avr->sreg[S_Z] = 0;
- avr->sreg[S_N] = (res >> 7) & 1;
- avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V];
+ SREG_SETBIT(S_Z, 0);
+ SREG_SETBIT(S_N, (res >> 7) & 1);
+ SREG_SETBIT(S_S, SREG_BIT(S_N) ^ SREG_BIT(S_V));
+ return _sreg;
}
-static void
-_avr_flags_sub_Rzns (struct avr_t * avr, uint8_t res, uint8_t rd, uint8_t rr)
+static uint8_t
+_avr_flags_sub_Rzns (uint8_t _sreg, uint8_t res, uint8_t rd, uint8_t rr)
{
/* carry & half carry */
uint8_t sub_carry = (~rd & rr) | (rr & res) | (res & ~rd);
- avr->sreg[S_H] = (sub_carry >> 3) & 1;
- avr->sreg[S_C] = (sub_carry >> 7) & 1;
+ SREG_SETBIT(S_H, (sub_carry >> 3) & 1);
+ SREG_SETBIT(S_C, (sub_carry >> 7) & 1);
/* overflow */
- avr->sreg[S_V] = (((rd & ~rr & ~res) | (~rd & rr & res)) >> 7) & 1;
-
- _avr_flags_Rzns(avr, res);
+ SREG_SETBIT(S_V, (((rd & ~rr & ~res) | (~rd & rr & res)) >> 7) & 1);
+ return _avr_flags_Rzns(_sreg, res);
}
-static void
-_avr_flags_zcvs (struct avr_t * avr, uint8_t res, uint8_t vr)
+static uint8_t
+_avr_flags_zcvs (uint8_t _sreg, uint8_t res, uint8_t vr)
{
- avr->sreg[S_Z] = res == 0;
- avr->sreg[S_C] = vr & 1;
- avr->sreg[S_V] = avr->sreg[S_N] ^ avr->sreg[S_C];
- avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V];
+ SREG_SETBIT(S_Z, res == 0);
+ SREG_SETBIT(S_C, vr & 1);
+ SREG_SETBIT(S_V, SREG_BIT(S_N) ^ SREG_BIT(S_C));
+ SREG_SETBIT(S_S, SREG_BIT(S_N) ^ SREG_BIT(S_V));
+ return _sreg;
}
-static void
-_avr_flags_zcnvs (struct avr_t * avr, uint8_t res, uint8_t vr)
+static uint8_t
+_avr_flags_zcnvs (uint8_t _sreg, uint8_t res, uint8_t vr)
{
- avr->sreg[S_Z] = res == 0;
- avr->sreg[S_C] = vr & 1;
- avr->sreg[S_N] = res >> 7;
- avr->sreg[S_V] = avr->sreg[S_N] ^ avr->sreg[S_C];
- avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V];
+ SREG_SETBIT(S_Z, res == 0);
+ SREG_SETBIT(S_C, vr & 1);
+ SREG_SETBIT(S_N, res >> 7);
+ SREG_SETBIT(S_V, SREG_BIT(S_N) ^ SREG_BIT(S_C));
+ SREG_SETBIT(S_S, SREG_BIT(S_N) ^ SREG_BIT(S_V));
+ return _sreg;
}
-static void
-_avr_flags_znv0s (struct avr_t * avr, uint8_t res)
+static uint8_t
+_avr_flags_znv0s (uint8_t _sreg, uint8_t res)
{
- avr->sreg[S_V] = 0;
- _avr_flags_zns(avr, res);
+ SREG_SETBIT(S_V, 0);
+ return _avr_flags_zns(_sreg, res);
}
static inline int _avr_is_instruction_32_bits(avr_t * avr, avr_flashaddr_t pc)
*/
avr_flashaddr_t avr_run_one(avr_t * avr)
{
+ SREG_START(avr);
run_one_again:
#if CONFIG_SIMAVR_TRACE
/*
switch (opcode & 0xfc00) {
case 0x0400: { // CPC -- Compare with carry -- 0000 01rd dddd rrrr
get_vd5_vr5(opcode);
- uint8_t res = vd - vr - avr->sreg[S_C];
+ uint8_t res = vd - vr - SREG_BIT(S_C);
STATE("cpc %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
- _avr_flags_sub_Rzns(avr, res, vd, vr);
+ _sreg = _avr_flags_sub_Rzns(_sreg, res, vd, vr);
SREG();
} break;
case 0x0c00: { // ADD -- Add without carry -- 0000 11rd dddd rrrr
} else {
STATE("add %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
}
- _avr_set_r(avr, d, res);
- _avr_flags_add_zns(avr, res, vd, vr);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_add_zns(_sreg, res, vd, vr);
SREG();
} break;
case 0x0800: { // SBC -- Subtract with carry -- 0000 10rd dddd rrrr
get_vd5_vr5(opcode);
- uint8_t res = vd - vr - avr->sreg[S_C];
+ uint8_t res = vd - vr - SREG_BIT(S_C);
STATE("sbc %s[%02x], %s[%02x] = %02x\n", avr_regname(d), avr->data[d], avr_regname(r), avr->data[r], res);
- _avr_set_r(avr, d, res);
- _avr_flags_sub_Rzns(avr, res, vd, vr);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_sub_Rzns(_sreg, res, vd, vr);
SREG();
} break;
default:
uint8_t r = ((opcode) & 0xf) << 1;
STATE("movw %s:%s, %s:%s[%02x%02x]\n", avr_regname(d), avr_regname(d+1), avr_regname(r), avr_regname(r+1), avr->data[r+1], avr->data[r]);
uint16_t vr = avr->data[r] | (avr->data[r + 1] << 8);
- _avr_set_r16le(avr, d, vr);
+ _avr_set_r16le(d, vr);
} break;
case 0x0200: { // MULS -- Multiply Signed -- 0000 0010 dddd rrrr
int8_t r = 16 + (opcode & 0xf);
int8_t d = 16 + ((opcode >> 4) & 0xf);
int16_t res = ((int8_t)avr->data[r]) * ((int8_t)avr->data[d]);
STATE("muls %s[%d], %s[%02x] = %d\n", avr_regname(d), ((int8_t)avr->data[d]), avr_regname(r), ((int8_t)avr->data[r]), res);
- _avr_set_r16le(avr, 0, res);
- avr->sreg[S_C] = (res >> 15) & 1;
- avr->sreg[S_Z] = res == 0;
+ _avr_set_r16le(0, res);
+ SREG_SETBIT(S_C, (res >> 15) & 1);
+ SREG_SETBIT(S_Z, res == 0);
cycle++;
SREG();
} break;
}
cycle++;
STATE("%s %s[%d], %s[%02x] = %d\n", name, avr_regname(d), ((int8_t)avr->data[d]), avr_regname(r), ((int8_t)avr->data[r]), res);
- _avr_set_r16le(avr, 0, res);
- avr->sreg[S_C] = c;
- avr->sreg[S_Z] = res == 0;
+ _avr_set_r16le(0, res);
+ SREG_SETBIT(S_C, c);
+ SREG_SETBIT(S_Z, res == 0);
SREG();
} break;
default: _avr_invalid_opcode(avr);
get_vd5_vr5(opcode);
uint8_t res = vd - vr;
STATE("sub %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
- _avr_set_r(avr, d, res);
- _avr_flags_sub_zns(avr, res, vd, vr);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_sub_zns(_sreg, res, vd, vr);
SREG();
} break;
case 0x1000: { // CPSE -- Compare, skip if equal -- 0001 00rd dddd rrrr
get_vd5_vr5(opcode);
uint8_t res = vd - vr;
STATE("cp %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
- _avr_flags_sub_zns(avr, res, vd, vr);
+ _sreg = _avr_flags_sub_zns(_sreg, res, vd, vr);
SREG();
} break;
case 0x1c00: { // ADD -- Add with carry -- 0001 11rd dddd rrrr
get_vd5_vr5(opcode);
- uint8_t res = vd + vr + avr->sreg[S_C];
+ uint8_t res = vd + vr + SREG_BIT(S_C);
if (r == d) {
STATE("rol %s[%02x] = %02x\n", avr_regname(d), avr->data[d], res);
} else {
STATE("addc %s[%02x], %s[%02x] = %02x\n", avr_regname(d), avr->data[d], avr_regname(r), avr->data[r], res);
}
- _avr_set_r(avr, d, res);
- _avr_flags_add_zns(avr, res, vd, vr);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_add_zns(_sreg, res, vd, vr);
SREG();
} break;
default: _avr_invalid_opcode(avr);
} else {
STATE("and %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
}
- _avr_set_r(avr, d, res);
- _avr_flags_znv0s(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_znv0s(_sreg, res);
SREG();
} break;
case 0x2400: { // EOR -- Logical Exclusive OR -- 0010 01rd dddd rrrr
} else {
STATE("eor %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
}
- _avr_set_r(avr, d, res);
- _avr_flags_znv0s(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_znv0s(_sreg, res);
SREG();
} break;
case 0x2800: { // OR -- Logical OR -- 0010 10rd dddd rrrr
get_vd5_vr5(opcode);
uint8_t res = vd | vr;
STATE("or %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res);
- _avr_set_r(avr, d, res);
- _avr_flags_znv0s(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_znv0s(_sreg, res);
SREG();
} break;
case 0x2c00: { // MOV -- 0010 11rd dddd rrrr
get_d5_vr5(opcode);
uint8_t res = vr;
STATE("mov %s, %s[%02x] = %02x\n", avr_regname(d), avr_regname(r), vr, res);
- _avr_set_r(avr, d, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
} break;
default: _avr_invalid_opcode(avr);
}
get_vh4_k8(opcode);
uint8_t res = vh - k;
STATE("cpi %s[%02x], 0x%02x\n", avr_regname(h), vh, k);
- _avr_flags_sub_zns(avr, res, vh, k);
+ _sreg = _avr_flags_sub_zns(_sreg, res, vh, k);
SREG();
} break;
case 0x4000: { // SBCI -- Subtract Immediate With Carry -- 0100 kkkk hhhh kkkk
get_vh4_k8(opcode);
- uint8_t res = vh - k - avr->sreg[S_C];
+ uint8_t res = vh - k - SREG_BIT(S_C);
STATE("sbci %s[%02x], 0x%02x = %02x\n", avr_regname(h), vh, k, res);
- _avr_set_r(avr, h, res);
- _avr_flags_sub_Rzns(avr, res, vh, k);
+ _sreg = _avr_set_r(avr, _sreg, h, res);
+ _sreg = _avr_flags_sub_Rzns(_sreg, res, vh, k);
SREG();
} break;
get_vh4_k8(opcode);
uint8_t res = vh - k;
STATE("subi %s[%02x], 0x%02x = %02x\n", avr_regname(h), vh, k, res);
- _avr_set_r(avr, h, res);
- _avr_flags_sub_zns(avr, res, vh, k);
+ _sreg = _avr_set_r(avr, _sreg, h, res);
+ _sreg = _avr_flags_sub_zns(_sreg, res, vh, k);
SREG();
} break;
get_vh4_k8(opcode);
uint8_t res = vh | k;
STATE("ori %s[%02x], 0x%02x\n", avr_regname(h), vh, k);
- _avr_set_r(avr, h, res);
- _avr_flags_znv0s(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, h, res);
+ _sreg = _avr_flags_znv0s(_sreg, res);
SREG();
} break;
get_vh4_k8(opcode);
uint8_t res = vh & k;
STATE("andi %s[%02x], 0x%02x\n", avr_regname(h), vh, k);
- _avr_set_r(avr, h, res);
- _avr_flags_znv0s(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, h, res);
+ _sreg = _avr_flags_znv0s(_sreg, res);
SREG();
} break;
get_d5_q6(opcode);
if (opcode & 0x0200) {
STATE("st (Z+%d[%04x]), %s[%02x]\n", q, v+q, avr_regname(d), avr->data[d]);
- _avr_set_ram(avr, v+q, avr->data[d]);
+ _sreg = _avr_set_ram(avr, _sreg, v+q, avr->data[d]);
} else {
STATE("ld %s, (Z+%d[%04x])=[%02x]\n", avr_regname(d), q, v+q, avr->data[v+q]);
- _avr_set_r(avr, d, _avr_get_ram(avr, v+q));
+ _sreg = _avr_set_r(avr, _sreg, d, _avr_get_ram(avr, v+q));
}
cycle += 1; // 2 cycles, 3 for tinyavr
} break;
get_d5_q6(opcode);
if (opcode & 0x0200) {
STATE("st (Y+%d[%04x]), %s[%02x]\n", q, v+q, avr_regname(d), avr->data[d]);
- _avr_set_ram(avr, v+q, avr->data[d]);
+ _sreg = _avr_set_ram(avr, _sreg, v+q, avr->data[d]);
} else {
STATE("ld %s, (Y+%d[%04x])=[%02x]\n", avr_regname(d), q, v+q, avr->data[d+q]);
- _avr_set_r(avr, d, _avr_get_ram(avr, v+q));
+ _sreg = _avr_set_r(avr, _sreg, d, _avr_get_ram(avr, v+q));
}
cycle += 1; // 2 cycles, 3 for tinyavr
} break;
if ((opcode & 0xff0f) == 0x9408) {
get_sreg_bit(opcode);
STATE("%s%c\n", opcode & 0x0080 ? "cl" : "se", _sreg_bit_name[b]);
- avr_sreg_set(avr, b, (opcode & 0x0080) == 0);
+ SREG_SETBIT(b, (opcode & 0x0080) == 0);
SREG();
} else switch (opcode) {
case 0x9588: { // SLEEP -- 1001 0101 1000 1000
* Without this check, it was possible to incorrectly enter a state
* in which the cpu was sleeping and interrupts were disabled. For more
* details, see the commit message. */
- if (!avr_has_pending_interrupts(avr) || !avr->sreg[S_I])
+ if (!avr_has_pending_interrupts(avr) || !SREG_BIT(S_I))
avr->state = cpu_Sleeping;
} break;
case 0x9598: { // BREAK -- 1001 0101 1001 1000
} break;
case 0x95a8: { // WDR -- Watchdog Reset -- 1001 0101 1010 1000
STATE("wdr\n");
- avr_ioctl(avr, AVR_IOCTL_WATCHDOG_RESET, 0);
+ SREG_FLUSH(avr_ioctl(avr, AVR_IOCTL_WATCHDOG_RESET, 0));
} break;
case 0x95e8: { // SPM -- Store Program Memory -- 1001 0101 1110 1000
STATE("spm\n");
- avr_ioctl(avr, AVR_IOCTL_FLASH_SPM, 0);
+ SREG_FLUSH(avr_ioctl(avr, AVR_IOCTL_FLASH_SPM, 0));
} break;
case 0x9409: // IJMP -- Indirect jump -- 1001 0100 0000 1001
case 0x9419: // EIJMP -- Indirect jump -- 1001 0100 0001 1001 bit 4 is "indirect"
cycle++;
TRACE_JUMP();
} break;
- case 0x9518: // RETI -- Return from Interrupt -- 1001 0101 0001 1000
- avr_sreg_set(avr, S_I, 1);
- avr_interrupt_reti(avr);
- FALLTHROUGH
- case 0x9508: { // RET -- Return -- 1001 0101 0000 1000
+ case 0x9508: // RET -- Return -- 1001 0101 0000 1000
+ case 0x9518: { // RETI -- Return from Interrupt -- 1001 0101 0001 1000
+ if (opcode == 0x9518) {
+ SREG_FLUSH(
+ avr_sreg_set(avr, S_I, 1);
+ avr_interrupt_reti(avr) );
+ }
new_pc = _avr_pop_addr(avr);
cycle += 1 + avr->address_size;
STATE("ret%s\n", opcode & 0x10 ? "i" : "");
uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8);
STATE("lpm %s, (Z[%04x])\n", avr_regname(0), z);
cycle += 2; // 3 cycles
- _avr_set_r(avr, 0, avr->flash[z]);
+ _sreg = _avr_set_r(avr, _sreg, 0, avr->flash[z]);
} break;
case 0x95d8: { // ELPM -- Load Program Memory R0 <- (Z) -- 1001 0101 1101 1000
if (!avr->rampz)
_avr_invalid_opcode(avr);
uint32_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8) | (avr->data[avr->rampz] << 16);
STATE("elpm %s, (Z[%02x:%04x])\n", avr_regname(0), z >> 16, z & 0xffff);
- _avr_set_r(avr, 0, avr->flash[z]);
+ _sreg = _avr_set_r(avr, _sreg, 0, avr->flash[z]);
cycle += 2; // 3 cycles
} break;
default: {
uint16_t x = _avr_flash_read16le(avr, new_pc);
new_pc += 2;
STATE("lds %s[%02x], 0x%04x\n", avr_regname(d), avr->data[d], x);
- _avr_set_r(avr, d, _avr_get_ram(avr, x));
+ _sreg = _avr_set_r(avr, _sreg, d, _avr_get_ram(avr, x));
cycle++; // 2 cycles
} break;
case 0x9005:
uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8);
int op = opcode & 1;
STATE("lpm %s, (Z[%04x]%s)\n", avr_regname(d), z, op ? "+" : "");
- _avr_set_r(avr, d, avr->flash[z]);
+ _sreg = _avr_set_r(avr, _sreg, d, avr->flash[z]);
if (op) {
z++;
- _avr_set_r16le_hl(avr, R_ZL, z);
+ _avr_set_r16le_hl( R_ZL, z);
}
cycle += 2; // 3 cycles
} break;
get_d5(opcode);
int op = opcode & 1;
STATE("elpm %s, (Z[%02x:%04x]%s)\n", avr_regname(d), z >> 16, z & 0xffff, op ? "+" : "");
- _avr_set_r(avr, d, avr->flash[z]);
+ _sreg = _avr_set_r(avr, _sreg, d, avr->flash[z]);
if (op) {
z++;
- _avr_set_r(avr, avr->rampz, z >> 16);
- _avr_set_r16le_hl(avr, R_ZL, z);
+ _sreg = _avr_set_r(avr, _sreg, avr->rampz, z >> 16);
+ _avr_set_r16le_hl( R_ZL, z);
}
cycle += 2; // 3 cycles
} break;
if (op == 2) x--;
uint8_t vd = _avr_get_ram(avr, x);
if (op == 1) x++;
- _avr_set_r16le_hl(avr, R_XL, x);
- _avr_set_r(avr, d, vd);
+ _avr_set_r16le_hl( R_XL, x);
+ _sreg = _avr_set_r(avr, _sreg, d, vd);
} break;
case 0x920c:
case 0x920d:
STATE("st %sX[%04x]%s, %s[%02x] \n", op == 2 ? "--" : "", x, op == 1 ? "++" : "", avr_regname(d), vd);
cycle++; // 2 cycles, except tinyavr
if (op == 2) x--;
- _avr_set_ram(avr, x, vd);
+ _sreg = _avr_set_ram(avr, _sreg, x, vd);
if (op == 1) x++;
- _avr_set_r16le_hl(avr, R_XL, x);
+ _avr_set_r16le_hl( R_XL, x);
} break;
case 0x9009:
case 0x900a: { // LD -- Load Indirect from Data using Y -- 1001 000d dddd 10oo
if (op == 2) y--;
uint8_t vd = _avr_get_ram(avr, y);
if (op == 1) y++;
- _avr_set_r16le_hl(avr, R_YL, y);
- _avr_set_r(avr, d, vd);
+ _avr_set_r16le_hl( R_YL, y);
+ _sreg = _avr_set_r(avr, _sreg, d, vd);
} break;
case 0x9209:
case 0x920a: { // ST -- Store Indirect Data Space Y -- 1001 001d dddd 10oo
STATE("st %sY[%04x]%s, %s[%02x]\n", op == 2 ? "--" : "", y, op == 1 ? "++" : "", avr_regname(d), vd);
cycle++;
if (op == 2) y--;
- _avr_set_ram(avr, y, vd);
+ _sreg = _avr_set_ram(avr, _sreg, y, vd);
if (op == 1) y++;
- _avr_set_r16le_hl(avr, R_YL, y);
+ _avr_set_r16le_hl( R_YL, y);
} break;
case 0x9200: { // STS -- Store Direct to Data Space, 32 bits -- 1001 0010 0000 0000
get_vd5(opcode);
new_pc += 2;
STATE("sts 0x%04x, %s[%02x]\n", x, avr_regname(d), vd);
cycle++;
- _avr_set_ram(avr, x, vd);
+ _sreg = _avr_set_ram(avr, _sreg, x, vd);
} break;
case 0x9001:
case 0x9002: { // LD -- Load Indirect from Data using Z -- 1001 000d dddd 00oo
if (op == 2) z--;
uint8_t vd = _avr_get_ram(avr, z);
if (op == 1) z++;
- _avr_set_r16le_hl(avr, R_ZL, z);
- _avr_set_r(avr, d, vd);
+ _avr_set_r16le_hl( R_ZL, z);
+ _sreg = _avr_set_r(avr, _sreg, d, vd);
} break;
case 0x9201:
case 0x9202: { // ST -- Store Indirect Data Space Z -- 1001 001d dddd 00oo
STATE("st %sZ[%04x]%s, %s[%02x] \n", op == 2 ? "--" : "", z, op == 1 ? "++" : "", avr_regname(d), vd);
cycle++; // 2 cycles, except tinyavr
if (op == 2) z--;
- _avr_set_ram(avr, z, vd);
+ _sreg = _avr_set_ram(avr, _sreg, z, vd);
if (op == 1) z++;
- _avr_set_r16le_hl(avr, R_ZL, z);
+ _avr_set_r16le_hl( R_ZL, z);
} break;
case 0x900f: { // POP -- 1001 000d dddd 1111
get_d5(opcode);
- _avr_set_r(avr, d, _avr_pop8(avr));
+ _sreg = _avr_set_r(avr, _sreg, d, _avr_pop8(avr));
T(uint16_t sp = _avr_sp_get(avr);)
STATE("pop %s (@%04x)[%02x]\n", avr_regname(d), sp, avr->data[sp]);
cycle++;
get_vd5(opcode);
uint8_t res = 0xff - vd;
STATE("com %s[%02x] = %02x\n", avr_regname(d), vd, res);
- _avr_set_r(avr, d, res);
- _avr_flags_znv0s(avr, res);
- avr->sreg[S_C] = 1;
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_znv0s(_sreg, res);
+ SREG_SETBIT(S_C, 1);
SREG();
} break;
case 0x9401: { // NEG -- Two's Complement -- 1001 010d dddd 0001
get_vd5(opcode);
uint8_t res = 0x00 - vd;
STATE("neg %s[%02x] = %02x\n", avr_regname(d), vd, res);
- _avr_set_r(avr, d, res);
- avr->sreg[S_H] = ((res >> 3) | (vd >> 3)) & 1;
- avr->sreg[S_V] = res == 0x80;
- avr->sreg[S_C] = res != 0;
- _avr_flags_zns(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ SREG_SETBIT(S_H, ((res >> 3) | (vd >> 3)) & 1);
+ SREG_SETBIT(S_V, res == 0x80);
+ SREG_SETBIT(S_C, res != 0);
+ _sreg = _avr_flags_zns(_sreg, res);
SREG();
} break;
case 0x9402: { // SWAP -- Swap Nibbles -- 1001 010d dddd 0010
get_vd5(opcode);
uint8_t res = (vd >> 4) | (vd << 4) ;
STATE("swap %s[%02x] = %02x\n", avr_regname(d), vd, res);
- _avr_set_r(avr, d, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
} break;
case 0x9403: { // INC -- Increment -- 1001 010d dddd 0011
get_vd5(opcode);
uint8_t res = vd + 1;
STATE("inc %s[%02x] = %02x\n", avr_regname(d), vd, res);
- _avr_set_r(avr, d, res);
- avr->sreg[S_V] = res == 0x80;
- _avr_flags_zns(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ SREG_SETBIT(S_V, res == 0x80);
+ _sreg = _avr_flags_zns(_sreg, res);
SREG();
} break;
case 0x9405: { // ASR -- Arithmetic Shift Right -- 1001 010d dddd 0101
get_vd5(opcode);
uint8_t res = (vd >> 1) | (vd & 0x80);
STATE("asr %s[%02x]\n", avr_regname(d), vd);
- _avr_set_r(avr, d, res);
- _avr_flags_zcnvs(avr, res, vd);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_zcnvs(_sreg, res, vd);
SREG();
} break;
case 0x9406: { // LSR -- Logical Shift Right -- 1001 010d dddd 0110
get_vd5(opcode);
uint8_t res = vd >> 1;
STATE("lsr %s[%02x]\n", avr_regname(d), vd);
- _avr_set_r(avr, d, res);
- avr->sreg[S_N] = 0;
- _avr_flags_zcvs(avr, res, vd);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ SREG_SETBIT(S_N, 0);
+ _sreg = _avr_flags_zcvs(_sreg, res, vd);
SREG();
} break;
case 0x9407: { // ROR -- Rotate Right -- 1001 010d dddd 0111
get_vd5(opcode);
- uint8_t res = (avr->sreg[S_C] ? 0x80 : 0) | vd >> 1;
+ uint8_t res = (SREG_BIT(S_C) ? 0x80 : 0) | vd >> 1;
STATE("ror %s[%02x]\n", avr_regname(d), vd);
- _avr_set_r(avr, d, res);
- _avr_flags_zcnvs(avr, res, vd);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ _sreg = _avr_flags_zcnvs(_sreg, res, vd);
SREG();
} break;
case 0x940a: { // DEC -- Decrement -- 1001 010d dddd 1010
get_vd5(opcode);
uint8_t res = vd - 1;
STATE("dec %s[%02x] = %02x\n", avr_regname(d), vd, res);
- _avr_set_r(avr, d, res);
- avr->sreg[S_V] = res == 0x7f;
- _avr_flags_zns(avr, res);
+ _sreg = _avr_set_r(avr, _sreg, d, res);
+ SREG_SETBIT(S_V, res == 0x7f);
+ _sreg = _avr_flags_zns(_sreg, res);
SREG();
} break;
case 0x940c:
get_vp2_k6(opcode);
uint16_t res = vp + k;
STATE("adiw %s:%s[%04x], 0x%02x\n", avr_regname(p), avr_regname(p + 1), vp, k);
- _avr_set_r16le_hl(avr, p, res);
- avr->sreg[S_V] = ((~vp & res) >> 15) & 1;
- avr->sreg[S_C] = ((~res & vp) >> 15) & 1;
- _avr_flags_zns16(avr, res);
+ _avr_set_r16le_hl( p, res);
+ SREG_SETBIT(S_V, ((~vp & res) >> 15) & 1);
+ SREG_SETBIT(S_C, ((~res & vp) >> 15) & 1);
+ _sreg = _avr_flags_zns16(_sreg, res);
SREG();
cycle++;
} break;
get_vp2_k6(opcode);
uint16_t res = vp - k;
STATE("sbiw %s:%s[%04x], 0x%02x\n", avr_regname(p), avr_regname(p + 1), vp, k);
- _avr_set_r16le_hl(avr, p, res);
- avr->sreg[S_V] = ((vp & ~res) >> 15) & 1;
- avr->sreg[S_C] = ((res & ~vp) >> 15) & 1;
- _avr_flags_zns16(avr, res);
+ _avr_set_r16le_hl( p, res);
+ SREG_SETBIT(S_V, ((vp & ~res) >> 15) & 1);
+ SREG_SETBIT(S_C, ((res & ~vp) >> 15) & 1);
+ _sreg = _avr_flags_zns16(_sreg, res);
SREG();
cycle++;
} break;
get_io5_b3mask(opcode);
uint8_t res = _avr_get_ram(avr, io) & ~mask;
STATE("cbi %s[%04x], 0x%02x = %02x\n", avr_regname(io), avr->data[io], mask, res);
- _avr_set_ram(avr, io, res);
+ _sreg = _avr_set_ram(avr, _sreg, io, res);
cycle++;
} break;
case 0x9900: { // SBIC -- Skip if Bit in I/O Register is Cleared -- 1001 1001 AAAA Abbb
get_io5_b3mask(opcode);
uint8_t res = _avr_get_ram(avr, io) | mask;
STATE("sbi %s[%04x], 0x%02x = %02x\n", avr_regname(io), avr->data[io], mask, res);
- _avr_set_ram(avr, io, res);
+ _sreg = _avr_set_ram(avr, _sreg, io, res);
cycle++;
} break;
case 0x9b00: { // SBIS -- Skip if Bit in I/O Register is Set -- 1001 1011 AAAA Abbb
uint16_t res = vd * vr;
STATE("mul %s[%02x], %s[%02x] = %04x\n", avr_regname(d), vd, avr_regname(r), vr, res);
cycle++;
- _avr_set_r16le(avr, 0, res);
- avr->sreg[S_Z] = res == 0;
- avr->sreg[S_C] = (res >> 15) & 1;
+ _avr_set_r16le(0, res);
+ SREG_SETBIT(S_Z, res == 0);
+ SREG_SETBIT(S_C, (res >> 15) & 1);
SREG();
} break;
default: _avr_invalid_opcode(avr);
case 0xb800: { // OUT A,Rr -- 1011 1AAd dddd AAAA
get_d5_a6(opcode);
STATE("out %s, %s[%02x]\n", avr_regname(A), avr_regname(d), avr->data[d]);
- _avr_set_ram(avr, A, avr->data[d]);
+ _sreg = _avr_set_ram(avr, _sreg, A, avr->data[d]);
} break;
case 0xb000: { // IN Rd,A -- 1011 0AAd dddd AAAA
get_d5_a6(opcode);
STATE("in %s, %s[%02x]\n", avr_regname(d), avr_regname(A), avr->data[A]);
- _avr_set_r(avr, d, _avr_get_ram(avr, A));
+ _sreg = _avr_set_r(avr, _sreg, d, _avr_get_ram(avr, A));
} break;
default: _avr_invalid_opcode(avr);
}
case 0xe000: { // LDI Rd, K aka SER (LDI r, 0xff) -- 1110 kkkk dddd kkkk
get_h4_k8(opcode);
STATE("ldi %s, 0x%02x\n", avr_regname(h), k);
- _avr_set_r(avr, h, k);
+ _sreg = _avr_set_r(avr, _sreg, h, k);
} break;
case 0xf000: {
int16_t o = ((int16_t)(opcode << 6)) >> 9; // offset
uint8_t s = opcode & 7;
int set = (opcode & 0x0400) == 0; // this bit means BRXC otherwise BRXS
- int branch = (avr->sreg[s] && set) || (!avr->sreg[s] && !set);
const char *names[2][8] = {
{ "brcc", "brne", "brpl", "brvc", NULL, "brhc", "brtc", "brid"},
{ "brcs", "breq", "brmi", "brvs", NULL, "brhs", "brts", "brie"},
};
+ int branch = (SREG_BIT(s) && set) || (!SREG_BIT(s) && !set);
if (names[set][s]) {
STATE("%s .%d [%04x]\t; Will%s branch\n", names[set][s], o, new_pc + (o << 1), branch ? "":" not");
} else {
case 0xf800:
case 0xf900: { // BLD -- Bit Store from T into a Bit in Register -- 1111 100d dddd 0bbb
get_vd5_s3_mask(opcode);
- uint8_t v = (vd & ~mask) | (avr->sreg[S_T] ? mask : 0);
+ uint8_t v = (vd & ~mask) | (SREG_BIT(S_T) ? mask : 0);
STATE("bld %s[%02x], 0x%02x = %02x\n", avr_regname(d), vd, mask, v);
- _avr_set_r(avr, d, v);
+ _sreg = _avr_set_r(avr, _sreg, d, v);
} break;
case 0xfa00:
case 0xfb00:{ // BST -- Bit Store into T from bit in Register -- 1111 101d dddd 0bbb
get_vd5_s3(opcode)
STATE("bst %s[%02x], 0x%02x\n", avr_regname(d), vd, 1 << s);
- avr->sreg[S_T] = (vd >> s) & 1;
+ SREG_SETBIT(S_T, (vd >> s) & 1);
SREG();
} break;
case 0xfc00:
}
avr->cycle += cycle;
+ SREG_END(avr);
if ((avr->state == cpu_Running) &&
(avr->run_cycle_count > cycle) &&