// 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;
}
// 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;
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;
}
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) {
*/
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);
#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);
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);