Commit refs/heads/wip/sreg-inline wip/sreg-inline
authorMichel Pollet <buserror@gmail.com>
Wed, 23 Nov 2016 10:57:42 +0000 (10:57 +0000)
committerMichel Pollet <buserror@gmail.com>
Wed, 10 Jan 2018 10:06:12 +0000 (10:06 +0000)
Disable the old 8 bytes array, let the compiler sort it out. This
simplified the core rather nicely.

Signed-off-by: Michel Pollet <buserror@gmail.com>
7 files changed:
simavr/sim/avr_extint.c
simavr/sim/sim_avr.c
simavr/sim/sim_avr.h
simavr/sim/sim_core.c
simavr/sim/sim_core.h
simavr/sim/sim_interrupts.c
tests/tests.c

index e8dd9bcfe1b0f69202084f4a2469c966ac6fdd3f..18fb9d5522b74c396ed8c3c568521ecf1c6a47e4 100644 (file)
@@ -25,6 +25,7 @@
 #include <string.h>
 #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);
index d33400abe397f72493cc818eee620c1c7a8aa061..42bac95d97b5edc72e238f17c9222c246bb9ff7e 100644 (file)
@@ -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;
index 35539761b040fd1a0a3de88a551c6f71b20cec6c..ee9e6ad85d7df4de34d7a4c106f2db1f9b6b519e 100644 (file)
@@ -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
index 7be739b49b8555dabf4665b2d7531f5d908448bb..b96f74c5deda8e2fa0ce31ab0a44a03bfdc1000c 100644 (file)
@@ -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) &&
index 403c119a63d596f1f82b19d573d60c0bde7c57df..406eae59d6d7f7e2a3902c59e3224d1da3097588 100644 (file)
@@ -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);
 }
 
 /**
index b689a94ea9ef75797f7bb91497bf1587ccef84f4..091d0234b511c5b935801d1ab7dabb5a6c0cf722 100644 (file)
@@ -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) {
index 579b562d326725a9915d5b1feca19271b8767ca4..660ae278529ac775e49b6a0e093c9f10723311f4 100644 (file)
@@ -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?");