From: Michel Pollet Date: Wed, 6 Jan 2010 22:45:30 +0000 (+0000) Subject: core: Simplify changes to SREG X-Git-Tag: v1.0a1~8 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=2f67001d8fab0cf3d51100b15e79f53caccc31b0;p=sx%2Fsimavr.git core: Simplify changes to SREG SREG is no longer re-synthetized at every instruction, but only when the firmware reads the register. Signed-off-by: Michel Pollet --- diff --git a/simavr/sim/sim_avr.c b/simavr/sim/sim_avr.c index 0512c2a..e163f36 100644 --- a/simavr/sim/sim_avr.c +++ b/simavr/sim/sim_avr.c @@ -131,9 +131,8 @@ int avr_run(avr_t * avr) // if we are stepping one instruction, we "run" for one.. int step = avr->state == cpu_Step; - if (step) { + if (step) avr->state = cpu_Running; - } uint16_t new_pc = avr->pc; @@ -145,16 +144,21 @@ int avr_run(avr_t * avr) } // if we just re-enabled the interrupts... - if (avr->sreg[S_I] && !(avr->data[R_SREG] & (1 << S_I))) { - // printf("*** %s: Renabling interrupts\n", __FUNCTION__); + // double buffer the I flag, to detect that edge + if (avr->sreg[S_I] && !avr->i_shadow) avr->pending_wait++; - } + avr->i_shadow = avr->sreg[S_I]; + + // run IO modules that wants it avr_io_t * port = avr->io_port; while (port) { if (port->run) port->run(port); port = port->next; } + + // run the cycle timers, get the suggested sleeo time + // until the next timer is due avr_cycle_count_t sleep = avr_cycle_timer_process(avr); avr->pc = new_pc; @@ -177,22 +181,13 @@ int avr_run(avr_t * avr) usleep(usec); avr->cycle += 1 + sleep; } - // Interrupt servicing might change the PC too - if (avr->state == cpu_Running || avr->state == cpu_Sleeping) { + // Interrupt servicing might change the PC too, during 'sleep' + if (avr->state == cpu_Running || avr->state == cpu_Sleeping) avr_service_interrupts(avr); - - avr->data[R_SREG] = 0; - for (int i = 0; i < 8; i++) - if (avr->sreg[i] > 1) { - printf("** Invalid SREG!!\n"); - CRASH(); - } else if (avr->sreg[i]) - avr->data[R_SREG] |= (1 << i); - } - - if (step) { + + // if we were stepping, use this state to inform remote gdb + if (step) avr->state = cpu_StepDone; - } return avr->state; } diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 663a57f..9c2256d 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -99,6 +99,7 @@ typedef struct avr_t { // in the opcode decoder. // This array is re-synthetized back/forth when SREG changes uint8_t sreg[8]; + uint8_t i_shadow; // used to detect edges on I flag /* * ** current PC ** diff --git a/simavr/sim/sim_core.c b/simavr/sim/sim_core.c index a8df91d..31c2ab3 100644 --- a/simavr/sim/sim_core.c +++ b/simavr/sim/sim_core.c @@ -130,10 +130,10 @@ static inline void _avr_set_r(avr_t * avr, uint8_t r, uint8_t v) REG_TOUCH(avr, r); if (r == R_SREG) { - avr->data[r] = v; + avr->data[R_SREG] = v; // unsplit the SREG for (int i = 0; i < 8; i++) - avr->sreg[i] = (avr->data[R_SREG] & (1 << i)) != 0; + avr->sreg[i] = (v & (1 << i)) != 0; SREG(); } if (r > 31) { @@ -181,8 +181,22 @@ 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 > 31 && addr < 256) { + if (addr == R_SREG) { + /* + * SREG is special it's reconstructed when read + * while the core itself uses the "shortcut" array + */ + avr->data[R_SREG] = 0; + for (int i = 0; i < 8; i++) + if (avr->sreg[i] > 1) { + printf("** Invalid SREG!!\n"); + CRASH(); + } else if (avr->sreg[i]) + avr->data[R_SREG] |= (1 << i); + + } else if (addr > 31 && addr < 256) { uint8_t io = AVR_DATA_TO_IO(addr); + if (avr->io[io].r.c) avr->data[addr] = avr->io[io].r.c(avr, addr, avr->io[io].r.param); @@ -301,7 +315,7 @@ void avr_dump_state(avr_t * avr) #define get_r_d_10(o) \ const uint8_t r = ((o >> 5) & 0x10) | (o & 0xf); \ const uint8_t d = (o >> 4) & 0x1f;\ - const uint8_t vd = avr->data[d], vr =avr->data[r]; + const uint8_t vd = avr->data[d], vr = avr->data[r]; #define get_k_r16(o) \ const uint8_t r = 16 + ((o >> 4) & 0xf); \ const uint8_t k = ((o & 0x0f00) >> 4) | (o & 0xf); @@ -1197,15 +1211,12 @@ uint16_t avr_run_one(avr_t * avr) uint8_t r = (opcode >> 4) & 0x1f; uint8_t A = ((((opcode >> 9) & 3) << 4) | ((opcode) & 0xf)) + 32; STATE("out %s, %s[%02x]\n", avr_regname(A), avr_regname(r), avr->data[r]); - // todo: store to IO register _avr_set_ram(avr, A, avr->data[r]); - // avr->data[A] = ; } break; case 0xb000: { // IN Rd,A 1011 0AAr rrrr AAAA uint8_t r = (opcode >> 4) & 0x1f; uint8_t A = ((((opcode >> 9) & 3) << 4) | ((opcode) & 0xf)) + 32; STATE("in %s, %s[%02x]\n", avr_regname(r), avr_regname(A), avr->data[A]); - // todo: get the IO register _avr_set_r(avr, r, _avr_get_ram(avr, A)); } break; default: _avr_invalid_opcode(avr);