From a1ab5f8775617d80235821cdaa5aac465a3122cc Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Wed, 23 Nov 2016 10:57:42 +0000 Subject: [PATCH] core: switch SREG to bitfield Disable the old 8 bytes array, let the compiler sort it out. This simplified the core rather nicely. Signed-off-by: Michel Pollet --- simavr/sim/avr_extint.c | 7 +- simavr/sim/sim_avr.c | 8 +- simavr/sim/sim_avr.h | 5 - simavr/sim/sim_core.c | 407 ++++++++++++++++++------------------ simavr/sim/sim_core.h | 27 ++- simavr/sim/sim_interrupts.c | 8 +- tests/tests.c | 3 +- 7 files changed, 234 insertions(+), 231 deletions(-) diff --git a/simavr/sim/avr_extint.c b/simavr/sim/avr_extint.c index e8dd9bc..18fb9d5 100644 --- a/simavr/sim/avr_extint.c +++ b/simavr/sim/avr_extint.c @@ -25,6 +25,7 @@ #include #include "avr_extint.h" #include "avr_ioport.h" +#include "sim_core.h" // for SREG bit access typedef struct avr_extint_poll_context_t { uint32_t eint_no; // index of particular interrupt source we are monitoring @@ -38,6 +39,7 @@ static avr_cycle_count_t avr_extint_poll_level_trig( { avr_extint_poll_context_t *poll = (avr_extint_poll_context_t *)param; avr_extint_t * p = (avr_extint_t *)poll->extint; + SREG_START(avr); char port = p->eint[poll->eint_no].port_ioctl & 0xFF; avr_ioport_state_t iostate; @@ -47,7 +49,7 @@ static avr_cycle_count_t avr_extint_poll_level_trig( if (bit) goto terminate_poll; // Only poll while pin level remains low - if (avr->sreg[S_I]) { + if (SREG_BIT(S_I)) { uint8_t raised = avr_regbit_get(avr, p->eint[poll->eint_no].vector.raised) || p->eint[poll->eint_no].vector.pending; if (!raised) avr_raise_interrupt(avr, &p->eint[poll->eint_no].vector); @@ -140,7 +142,8 @@ static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void * to turn this feature off. In this case bahaviour will be similar to the falling edge interrupt. */ if (!value) { - if (avr->sreg[S_I]) { + SREG_START(avr); + if (SREG_BIT(S_I)) { uint8_t raised = avr_regbit_get(avr, p->eint[irq->irq].vector.raised) || p->eint[irq->irq].vector.pending; if (!raised) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); diff --git a/simavr/sim/sim_avr.c b/simavr/sim/sim_avr.c index d33400a..42bac95 100644 --- a/simavr/sim/sim_avr.c +++ b/simavr/sim/sim_avr.c @@ -166,8 +166,6 @@ avr_reset( avr->data[i] = 0; _avr_sp_set(avr, avr->ramend); avr->pc = avr->reset_pc; // Likely to be zero - for (int i = 0; i < 8; i++) - avr->sreg[i] = 0; avr_interrupt_reset(avr); avr_cycle_timer_reset(avr); if (avr->reset) @@ -311,7 +309,8 @@ avr_callback_run_gdb( avr->pc = new_pc; if (avr->state == cpu_Sleeping) { - if (!avr->sreg[S_I]) { + SREG_START(avr); + if (!SREG_BIT(S_I)) { if (avr->log) AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n"); avr->state = cpu_Done; @@ -374,7 +373,8 @@ avr_callback_run_raw( avr->pc = new_pc; if (avr->state == cpu_Sleeping) { - if (!avr->sreg[S_I]) { + SREG_START(avr); + if (!SREG_BIT(S_I)) { if (avr->log) AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n"); avr->state = cpu_Done; diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 3553976..ee9e6ad 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -239,11 +239,6 @@ typedef struct avr_t { */ avr_irq_pool_t irq_pool; - // Mirror of the SREG register, to facilitate the access to bits - // in the opcode decoder. - // This array is re-synthesized back/forth when SREG changes - uint8_t sreg[8]; - /* Interrupt state: 00: idle (no wait, no pending interrupts) or disabled <0: wait till zero diff --git a/simavr/sim/sim_core.c b/simavr/sim/sim_core.c index 7be739b..b96f74c 100644 --- a/simavr/sim/sim_core.c +++ b/simavr/sim/sim_core.c @@ -30,7 +30,8 @@ #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. @@ -80,7 +81,7 @@ int donttrace = 0; #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");\ } @@ -181,17 +182,20 @@ uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr) * 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); @@ -204,27 +208,20 @@ static inline void _avr_set_r(avr_t * avr, uint16_t r, uint8_t v) } } 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 @@ -236,18 +233,21 @@ inline uint16_t _avr_sp_get(avr_t * avr) 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; } /* @@ -255,14 +255,7 @@ static inline void _avr_set_ram(avr_t * avr, uint16_t addr, uint8_t v) */ 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) @@ -284,7 +277,7 @@ static inline uint8_t _avr_get_ram(avr_t * avr, uint16_t addr) 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); } @@ -301,7 +294,7 @@ int _avr_push_addr(avr_t * avr, avr_flashaddr_t addr) 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; @@ -493,100 +486,106 @@ void avr_dump_state(avr_t * avr) * \****************************************************************************/ -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) @@ -619,6 +618,7 @@ 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 /* @@ -655,9 +655,9 @@ run_one_again: 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 @@ -668,16 +668,16 @@ run_one_again: } 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: @@ -687,16 +687,16 @@ run_one_again: 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; @@ -733,9 +733,9 @@ run_one_again: } 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); @@ -751,8 +751,8 @@ run_one_again: 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 @@ -771,19 +771,19 @@ run_one_again: 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); @@ -800,8 +800,8 @@ run_one_again: } 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 @@ -812,23 +812,23 @@ run_one_again: } 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); } @@ -838,16 +838,16 @@ run_one_again: 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; @@ -855,8 +855,8 @@ run_one_again: 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; @@ -864,8 +864,8 @@ run_one_again: 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; @@ -873,8 +873,8 @@ run_one_again: 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; @@ -895,10 +895,10 @@ run_one_again: 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; @@ -908,10 +908,10 @@ run_one_again: 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; @@ -924,7 +924,7 @@ run_one_again: 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 @@ -933,7 +933,7 @@ run_one_again: * 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 @@ -949,11 +949,11 @@ run_one_again: } 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" @@ -973,11 +973,13 @@ run_one_again: 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" : ""); @@ -988,14 +990,14 @@ run_one_again: 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: { @@ -1005,7 +1007,7 @@ run_one_again: 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: @@ -1014,10 +1016,10 @@ run_one_again: 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; @@ -1029,11 +1031,11 @@ run_one_again: 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; @@ -1056,8 +1058,8 @@ run_one_again: 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: @@ -1068,9 +1070,9 @@ run_one_again: 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 @@ -1082,8 +1084,8 @@ run_one_again: 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 @@ -1093,9 +1095,9 @@ run_one_again: 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); @@ -1103,7 +1105,7 @@ run_one_again: 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 @@ -1115,8 +1117,8 @@ run_one_again: 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 @@ -1126,13 +1128,13 @@ run_one_again: 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++; @@ -1148,69 +1150,69 @@ run_one_again: 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: @@ -1242,10 +1244,10 @@ run_one_again: 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; @@ -1253,10 +1255,10 @@ run_one_again: 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; @@ -1264,7 +1266,7 @@ run_one_again: 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 @@ -1283,7 +1285,7 @@ run_one_again: 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 @@ -1305,9 +1307,9 @@ run_one_again: 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); @@ -1324,12 +1326,12 @@ run_one_again: 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); } @@ -1358,7 +1360,7 @@ run_one_again: 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: { @@ -1377,11 +1379,11 @@ run_one_again: 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 { @@ -1395,15 +1397,15 @@ run_one_again: 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: @@ -1428,6 +1430,7 @@ run_one_again: } avr->cycle += cycle; + SREG_END(avr); if ((avr->state == cpu_Running) && (avr->run_cycle_count > cycle) && diff --git a/simavr/sim/sim_core.h b/simavr/sim/sim_core.h index 403c119..406eae5 100644 --- a/simavr/sim/sim_core.h +++ b/simavr/sim/sim_core.h @@ -90,20 +90,18 @@ void avr_dump_state(avr_t * avr); #endif -/** - * Reconstructs the SREG value from avr->sreg into dst. - */ -#define READ_SREG_INTO(avr, dst) { \ - dst = 0; \ - for (int i = 0; i < 8; i++) \ - if (avr->sreg[i] > 1) { \ - printf("** Invalid SREG!!\n"); \ - } else if (avr->sreg[i]) \ - dst |= (1 << i); \ - } +#define SREG_BIT(_b) (_sreg & (1 << (_b))) +#define SREG_SETBIT(_b, _v) _sreg = (_sreg & ~(1 << (_b))) | (!!(_v) << (_b)) + +#define READ_SREG_INTO(_avr, _dst) \ + (_dst) = (_avr)->data[R_SREG] + +#define SREG_START(_avr) uint8_t _sreg; READ_SREG_INTO(_avr, _sreg) +#define SREG_END(_avr) (_avr)->data[R_SREG] = _sreg -static inline void avr_sreg_set(avr_t * avr, uint8_t flag, uint8_t ival) +static inline uint8_t avr_sreg_set(avr_t * avr, uint8_t flag, uint8_t ival) { + SREG_START(avr); /* * clear interrupt_state if disabling interrupts. * set wait if enabling interrupts. @@ -112,13 +110,14 @@ static inline void avr_sreg_set(avr_t * avr, uint8_t flag, uint8_t ival) if (flag == S_I) { if (ival) { - if (!avr->sreg[S_I]) + if (!SREG_BIT(S_I)) avr->interrupt_state = -2; } else avr->interrupt_state = 0; } - avr->sreg[flag] = ival; + SREG_SETBIT(flag, ival); + return SREG_END(avr); } /** diff --git a/simavr/sim/sim_interrupts.c b/simavr/sim/sim_interrupts.c index b689a94..091d023 100644 --- a/simavr/sim/sim_interrupts.c +++ b/simavr/sim/sim_interrupts.c @@ -112,12 +112,13 @@ avr_raise_interrupt( avr_t * avr, avr_int_vector_t * vector) { + SREG_START(avr); if (!vector || !vector->vector) return 0; if (vector->pending) { if (vector->trace) printf("IRQ%d:I=%d already raised (enabled %d) (cycle %lld pc 0x%x)\n", - vector->vector, !!avr->sreg[S_I], avr_regbit_get(avr, vector->enable), + vector->vector, !!SREG_BIT(S_I), avr_regbit_get(avr, vector->enable), (long long int)avr->cycle, avr->pc); return 0; } @@ -142,7 +143,7 @@ avr_raise_interrupt( avr_int_pending_write(&table->pending, vector); - if (avr->sreg[S_I] && avr->interrupt_state == 0) + if (SREG_BIT(S_I) && avr->interrupt_state == 0) avr->interrupt_state = 1; if (avr->state == cpu_Sleeping) { if (vector->trace) @@ -232,7 +233,8 @@ void avr_service_interrupts( avr_t * avr) { - if (!avr->sreg[S_I] || !avr->interrupt_state) + SREG_START(avr); + if (!SREG_BIT(S_I) || !avr->interrupt_state) return; if (avr->interrupt_state < 0) { diff --git a/tests/tests.c b/tests/tests.c index 579b562..660ae27 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -76,7 +76,8 @@ static int my_avr_run(avr_t * avr) avr->pc = new_pc; if (avr->state == cpu_Sleeping) { - if (!avr->sreg[S_I]) { + SREG_START(avr); + if (!SREG_BIT(S_I)) { printf("simavr: sleeping with interrupts off, quitting gracefully\n"); avr_terminate(avr); fail("Test case error: special_deinit() returned?"); -- 2.39.5