diff --git a/.gitattributes b/.gitattributes index fe084b6ee0c..80e35fba3e5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6554,7 +6554,6 @@ src/mess/machine/at_keybc.h svneol=native#text/plain src/mess/machine/ataricrt.c svneol=native#text/plain src/mess/machine/ataridev.h svneol=native#text/plain src/mess/machine/atarifdc.c svneol=native#text/plain -src/mess/machine/avr8.h svneol=native#text/plain src/mess/machine/ay31015.c svneol=native#text/plain src/mess/machine/ay31015.h svneol=native#text/plain src/mess/machine/ay3600.c svneol=native#text/plain diff --git a/src/emu/cpu/avr8/avr8.c b/src/emu/cpu/avr8/avr8.c index 00f87955d90..9c4867b59d5 100644 --- a/src/emu/cpu/avr8/avr8.c +++ b/src/emu/cpu/avr8/avr8.c @@ -21,16 +21,26 @@ #include "debugger.h" #include "avr8.h" -struct avr8_state -{ - UINT32 pc; +#define VERBOSE_LEVEL (0) - legacy_cpu_device *device; - address_space *program; - address_space *io; - int icount; - UINT32 addr_mask; -}; +#define ENABLE_VERBOSE_LOG (1) + +#if ENABLE_VERBOSE_LOG +INLINE void verboselog(UINT16 pc, int n_level, const char *s_fmt, ...) +{ + if( VERBOSE_LEVEL >= n_level ) + { + va_list v; + char buf[ 32768 ]; + va_start( v, s_fmt ); + vsprintf( buf, s_fmt, v ); + va_end( v ); + logerror( "%05x: %s", pc << 1, buf ); + } +} +#else +#define verboselog(x,y,z,...) +#endif enum { @@ -44,17 +54,46 @@ enum AVR8_SREG_I, }; +// I/O Enums enum { - AVR8_IO_SPL = 0x5d, - AVR8_IO_SPH = 0x5e, - AVR8_IO_SREG = 0x5f, + WGM1_NORMAL = 0, + WGM1_PWM_8_PC, + WGM1_PWM_9_PC, + WGM1_PWM_10_PC, + WGM1_CTC_OCR, + WGM1_FAST_PWM_8, + WGM1_FAST_PWM_9, + WGM1_FAST_PWM_10, + WGM1_PWM_PFC_ICR, + WGM1_PWM_PFC_OCR, + WGM1_PWM_PC_ICR, + WGM1_PWM_PC_OCR, + WGM1_CTC_ICR, + WGM1_RESERVED, + WGM1_FAST_PWM_ICR, + WGM1_FAST_PWM_OCR }; -#define SREG_R(b) ((READ_IO_8(cpustate, AVR8_IO_SREG) & (1 << (b))) >> (b)) -#define SREG_W(b,v) WRITE_IO_8(cpustate, AVR8_IO_SREG, (READ_IO_8(cpustate, AVR8_IO_SREG) &~ (1 << (b))) | (((v) ? 1 : 0) << (b))) +enum +{ + WGM2_NORMAL = 0, + WGM2_PWM_PC, + WGM2_CTC_CMP, + WGM2_FAST_PWM, + WGM2_RESERVED0, + WGM2_PWM_PC_CMP, + WGM2_RESERVED1, + WGM2_FAST_PWM_CMP +}; + +static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' }; + +#define SREG_R(b) ((cpustate->status & (1 << (b))) >> (b)) +#define SREG_W(b,v) cpustate->status = (cpustate->status & ~(1 << (b))) | ((v) << (b)) #define NOT(x) (1 - (x)) +// Opcode-Parsing Defines #define RD2(op) (((op) >> 4) & 0x0003) #define RD3(op) (((op) >> 4) & 0x0007) #define RD4(op) (((op) >> 4) & 0x000f) @@ -71,10 +110,119 @@ enum #define ACONST5(op) (((op) >> 3) & 0x001f) #define ACONST6(op) ((((op) >> 5) & 0x0030) | ((op) & 0x000f)) -#define XREG ((READ_IO_8(cpustate, 27) << 8) | READ_IO_8(cpustate, 26)) -#define YREG ((READ_IO_8(cpustate, 29) << 8) | READ_IO_8(cpustate, 28)) -#define ZREG ((READ_IO_8(cpustate, 31) << 8) | READ_IO_8(cpustate, 30)) -#define SPREG ((READ_IO_8(cpustate, AVR8_IO_SPH) << 8) | READ_IO_8(cpustate, AVR8_IO_SPL)) +// Register Defines +#define XREG ((cpustate->r[27] << 8) | cpustate->r[26]) +#define YREG ((cpustate->r[29] << 8) | cpustate->r[28]) +#define ZREG ((cpustate->r[31] << 8) | cpustate->r[30]) +#define SPREG ((cpustate->r[AVR8_REGIDX_SPH] << 8) | cpustate->r[AVR8_REGIDX_SPL]) + +// I/O Defines +#define AVR8_OCR1BH (cpustate->r[AVR8_REGIDX_OCR1BH]) +#define AVR8_OCR1BL (cpustate->r[AVR8_REGIDX_OCR1BL]) +#define AVR8_OCR1AH (cpustate->r[AVR8_REGIDX_OCR1AH]) +#define AVR8_OCR1AL (cpustate->r[AVR8_REGIDX_OCR1AL]) +#define AVR8_ICR1H (cpustate->r[AVR8_REGIDX_ICR1H]) +#define AVR8_ICR1L (cpustate->r[AVR8_REGIDX_ICR1L]) +#define AVR8_TCNT1H (cpustate->r[AVR8_REGIDX_TCNT1H]) +#define AVR8_TCNT1L (cpustate->r[AVR8_REGIDX_TCNT1L]) + +#define AVR8_TCCR1B (cpustate->r[AVR8_REGIDX_TCCR1B]) +#define AVR8_TCCR1B_ICNC1_MASK 0x80 +#define AVR8_TCCR1B_ICNC1_SHIFT 7 +#define AVR8_TCCR1B_ICES1_MASK 0x40 +#define AVR8_TCCR1B_ICES1_SHIFT 6 +#define AVR8_TCCR1B_WGM1_32_MASK 0x18 +#define AVR8_TCCR1B_WGM1_32_SHIFT 3 +#define AVR8_TCCR1B_CS_MASK 0x07 +#define AVR8_TCCR1B_CS_SHIFT 0 +#define AVR8_TIMER1_CLOCK_SELECT (AVR8_TCCR1B & AVR8_TCCR1B_CS_MASK) + +#define AVR8_TCCR1A (cpustate->r[AVR8_REGIDX_TCCR1A]) +#define AVR8_TCCR1A_COM1A_MASK 0xc0 +#define AVR8_TCCR1A_COM1A_SHIFT 6 +#define AVR8_TCCR1A_COM1B_MASK 0x30 +#define AVR8_TCCR1A_COM1B_SHIFT 4 +#define AVR8_TCCR1A_WGM1_10_MASK 0x03 +#define AVR8_TCCR1A_WGM1_10_SHIFT 0 +#define AVR8_TCCR1A_COM1A ((AVR8_TCCR1A & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT) +#define AVR8_TCCR1A_COM1B ((AVR8_TCCR1A & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT) +#define AVR8_TCCR1A_WGM1_10 (AVR8_TCCR1A & AVR8_TCCR1A_WGM1_10_MASK) + +#define AVR8_TIMSK1 (cpustate->r[AVR8_REGIDX_TIMSK1]) +#define AVR8_TIMSK1_ICIE1_MASK 0x20 +#define AVR8_TIMSK1_OCIE1B_MASK 0x04 +#define AVR8_TIMSK1_OCIE1A_MASK 0x02 +#define AVR8_TIMSK1_TOIE1_MASK 0x01 +#define AVR8_TIMSK1_ICIE1 ((AVR8_TIMSK1 & AVR8_TIMSK1_ICIE1_MASK) >> 5) +#define AVR8_TIMSK1_OCIE1B ((AVR8_TIMSK1 & AVR8_TIMSK1_OCIE1B_MASK) >> 2) +#define AVR8_TIMSK1_OCIE1A ((AVR8_TIMSK1 & AVR8_TIMSK1_OCIE1A_MASK) >> 1) +#define AVR8_TIMSK1_TOIE1 (AVR8_TIMSK1 & AVR8_TIMSK1_TOIE1_MASK) + +#define AVR8_TIFR1 (cpustate->r[AVR8_REGIDX_TIFR1]) +#define AVR8_TIFR1_ICF1_MASK 0x20 +#define AVR8_TIFR1_ICF1_SHIFT 5 +#define AVR8_TIFR1_OCF1B_MASK 0x04 +#define AVR8_TIFR1_OCF1B_SHIFT 2 +#define AVR8_TIFR1_OCF1A_MASK 0x02 +#define AVR8_TIFR1_OCF1A_SHIFT 1 +#define AVR8_TIFR1_TOV1_MASK 0x01 +#define AVR8_TIFR1_TOV1_SHIFT 0 +#define AVR8_TIFR1_MASK (AVR8_TIFR1_ICF1_MASK | AVR8_TIFR1_TOV1_MASK | \ + AVR8_TIFR1_OCF1B_MASK | AVR8_TIFR1_OCF1A_MASK) + +#define AVR8_TCCR2B (cpustate->r[AVR8_REGIDX_TCCR1B]) +#define AVR8_TCCR2B_FOC2A_MASK 0x80 +#define AVR8_TCCR2B_FOC2A_SHIFT 7 +#define AVR8_TCCR2B_FOC2B_MASK 0x40 +#define AVR8_TCCR2B_FOC2B_SHIFT 6 +#define AVR8_TCCR2B_WGM2_2_MASK 0x08 +#define AVR8_TCCR2B_WGM2_2_SHIFT 3 +#define AVR8_TCCR2B_CS_MASK 0x07 +#define AVR8_TCCR2B_CS_SHIFT 0 +#define AVR8_TIMER2_CLOCK_SELECT (AVR8_TCCR2B & AVR8_TCCR2B_CS_MASK) + +#define AVR8_TCCR2A (cpustate->r[AVR8_REGIDX_TCCR1A]) +#define AVR8_TCCR2A_COM2A_MASK 0xc0 +#define AVR8_TCCR2A_COM2A_SHIFT 6 +#define AVR8_TCCR2A_COM2B_MASK 0x30 +#define AVR8_TCCR2A_COM2B_SHIFT 4 +#define AVR8_TCCR2A_WGM2_10_MASK 0x03 +#define AVR8_TCCR2A_WGM2_10_SHIFT 0 +#define AVR8_TCCR2A_COM2A ((AVR8_TCCR2A & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT) +#define AVR8_TCCR2A_COM2B ((AVR8_TCCR2A & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT) +#define AVR8_TCCR2A_WGM2_10 (AVR8_TCCR2A & AVR8_TCCR1A_WGM2_10_MASK) + +#define AVR8_TIMSK2 (cpustate->r[AVR8_REGIDX_TIMSK2]) +#define AVR8_TIMSK2_OCIE2B_MASK 0x04 +#define AVR8_TIMSK2_OCIE2A_MASK 0x02 +#define AVR8_TIMSK2_TOIE2_MASK 0x01 +#define AVR8_TIMSK2_OCIE2B ((AVR8_TIMSK2 & AVR8_TIMSK1_OCIE2B_MASK) >> 2) +#define AVR8_TIMSK2_OCIE2A ((AVR8_TIMSK2 & AVR8_TIMSK1_OCIE2A_MASK) >> 1) +#define AVR8_TIMSK2_TOIE2 (AVR8_TIMSK2 & AVR8_TIMSK1_TOIE2_MASK) + +#define AVR8_TIFR2 (cpustate->r[AVR8_REGIDX_TIFR2]) +#define AVR8_TIFR2_OCF2B_MASK 0x04 +#define AVR8_TIFR2_OCF2B_SHIFT 2 +#define AVR8_TIFR2_OCF2A_MASK 0x02 +#define AVR8_TIFR2_OCF2A_SHIFT 1 +#define AVR8_TIFR2_TOV2_MASK 0x01 +#define AVR8_TIFR2_TOV2_SHIFT 0 +#define AVR8_TIFR2_MASK (AVR8_TIFR2_TOV2_MASK | AVR8_TIFR2_OCF2B_MASK | AVR8_TIFR2_OCF2A_MASK) + +#define AVR8_OCR1A ((AVR8_OCR1AH << 8) | AVR8_OCR1AL) +#define AVR8_OCR1B ((AVR8_OCR1BH << 8) | AVR8_OCR1BL) +#define AVR8_ICR1 ((AVR8_ICR1H << 8) | AVR8_ICR1L) +#define AVR8_TCNT1 ((AVR8_TCNT1H << 8) | AVR8_TCNT1L) +#define AVR8_WGM1 (((AVR8_TCCR1B & 0x18) >> 1) | (AVR8_TCCR1A & 0x03)) +#define AVR8_TCNT1_DIR (state->m_tcnt1_direction) + +#define AVR8_OCR2B cpustate->r[AVR8_REGIDX_OCR2B] +#define AVR8_OCR2A cpustate->r[AVR8_REGIDX_OCR2A] +#define AVR8_TCNT2 cpustate->r[AVR8_REGIDX_TCNT2] +#define AVR8_WGM2 (((AVR8_TCCR2B & 0x08) >> 1) | (AVR8_TCCR2A & 0x03)) + +#define AVR8_GTCCR_PSRASY_MASK 0x02 +#define AVR8_GTCCR_PSRASY_SHIFT 1 INLINE avr8_state *get_safe_token(device_t *device) { @@ -84,14 +232,54 @@ INLINE avr8_state *get_safe_token(device_t *device) } /*****************************************************************************/ +// Prototypes + +// - Utility +static void unimplemented_opcode(avr8_state *cpustate, UINT32 op); + +// - Interrupts +static void avr8_set_irq_line(avr8_state *cpustate, UINT16 vector, int state); +static void avr8_update_interrupt_internal(avr8_state *cpustate, int source); +static void avr8_poll_interrupt(avr8_state *cpustate); + +// - Timers +static void avr8_timer_tick(avr8_state *cpustate, int cycles); + +// - Timer 0 +static void avr8_timer0_tick(avr8_state *cpustate); + +// - Timer 1 +static void avr8_timer1_tick(avr8_state *cpustate); +static void avr8_change_timsk1(avr8_state *cpustate, UINT8 data); +static void avr8_update_timer1_waveform_gen_mode(avr8_state *cpustate); +static void avr8_changed_tccr1a(avr8_state *cpustate, UINT8 data); +static void avr8_update_timer1_input_noise_canceler(avr8_state *cpustate); +static void avr8_update_timer1_input_edge_select(avr8_state *cpustate); +static void avr8_update_timer1_clock_source(avr8_state *cpustate); +static void avr8_changed_tccr1b(avr8_state *cpustate, UINT8 data); +static void avr8_update_ocr1(avr8_state *cpustate, UINT16 newval, UINT8 reg); + +// - Timer 2 +static void avr8_timer2_tick(avr8_state *cpustate); +static void avr8_update_timer2_waveform_gen_mode(avr8_state *cpustate); +static void avr8_changed_tccr2a(avr8_state *cpustate, UINT8 data); +static void avr8_update_timer2_clock_source(avr8_state *cpustate); +static void avr8_timer2_force_output_compare(avr8_state *cpustate, int reg); +static void avr8_changed_tccr2b(avr8_state *cpustate, UINT8 data); +static void avr8_update_ocr2(avr8_state *cpustate, UINT8 newval, UINT8 reg); + +// - Register Handling +static bool avr8_io_reg_write(avr8_state *cpustate, UINT16 offset, UINT8 data); +static bool avr8_io_reg_read(avr8_state *cpustate, UINT16 offset, UINT8 *data); + +/*****************************************************************************/ +// Utility Functions static void unimplemented_opcode(avr8_state *cpustate, UINT32 op) { fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, cpustate->pc); } -/*****************************************************************************/ - INLINE bool avr8_is_long_opcode(UINT16 op) { if((op & 0xf000) == 0x9000) @@ -136,34 +324,52 @@ INLINE void WRITE_PRG_16(avr8_state *cpustate, UINT32 address, UINT16 data) INLINE UINT8 READ_IO_8(avr8_state *cpustate, UINT16 address) { + if (address < 0x100) + { + // Allow unhandled internal registers to be handled by external driver + UINT8 data; + if (avr8_io_reg_read(cpustate, address, &data)) + { + return data; + } + } return cpustate->io->read_byte(address); } INLINE void WRITE_IO_8(avr8_state *cpustate, UINT16 address, UINT8 data) { + if (address < 0x100) + { + // Allow unhandled internal registers to be handled by external driver + if (avr8_io_reg_write(cpustate, address, data)) + { + return; + } + } cpustate->io->write_byte(address, data); } INLINE void PUSH(avr8_state *cpustate, UINT8 val) { - UINT16 sp = SPREG; + UINT16 sp = SPREG; WRITE_IO_8(cpustate, sp, val); sp--; - //printf( "PUSH %02x, new SP = %04x\n", val, sp ); - WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff); - WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff); + WRITE_IO_8(cpustate, AVR8_REGIDX_SPL, sp & 0x00ff); + WRITE_IO_8(cpustate, AVR8_REGIDX_SPH, (sp >> 8) & 0x00ff); } INLINE UINT8 POP(avr8_state *cpustate) { - UINT16 sp = SPREG; + UINT16 sp = SPREG; sp++; - WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff); - WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff); - //printf( "POP %02x, new SP = %04x\n", READ_IO_8(cpustate, sp), sp ); + WRITE_IO_8(cpustate, AVR8_REGIDX_SPL, sp & 0x00ff); + WRITE_IO_8(cpustate, AVR8_REGIDX_SPH, (sp >> 8) & 0x00ff); return READ_IO_8(cpustate, sp); } +/*****************************************************************************/ +// Interrupts + static void avr8_set_irq_line(avr8_state *cpustate, UINT16 vector, int state) { // Horrible hack, not accurate @@ -172,13 +378,679 @@ static void avr8_set_irq_line(avr8_state *cpustate, UINT16 vector, int state) if(SREG_R(AVR8_SREG_I)) { SREG_W(AVR8_SREG_I, 0); + //printf("Push: %04x\n", cpustate->pc); PUSH(cpustate, (cpustate->pc >> 8) & 0x00ff); PUSH(cpustate, cpustate->pc & 0x00ff); cpustate->pc = vector; + + //avr8_timer_tick(cpustate, 3); + } + else + { + cpustate->interrupt_pending = true; } } } +class CInterruptCondition +{ + public: + UINT8 m_intindex; + UINT8 m_intreg; + UINT8 m_intmask; + UINT8 m_regindex; + UINT8 m_regmask; +}; + +static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] = +{ + { AVR8_INT_SPI_STC, AVR8_REGIDX_SPCR, AVR8_SPCR_SPIE_MASK, AVR8_REGIDX_SPSR, AVR8_SPSR_SPIF_MASK }, + { AVR8_INT_T1CAPT, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_ICIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK }, + { AVR8_INT_T1COMPB, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1B_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK }, + { AVR8_INT_T1COMPA, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1A_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK }, + { AVR8_INT_T1OVF, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_TOIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_TOV1_MASK }, + { AVR8_INT_T2COMPB, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2B_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2B_MASK }, + { AVR8_INT_T2COMPA, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2A_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2A_MASK }, + { AVR8_INT_T2OVF, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_TOIE2_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_TOV2_MASK } +}; + +static void avr8_update_interrupt_internal(avr8_state *cpustate, int source) +{ + CInterruptCondition condition = s_int_conditions[source]; + + int intstate = (cpustate->r[condition.m_regindex] & condition.m_regmask) ? 1 : 0; + intstate = (cpustate->r[condition.m_intreg] & condition.m_intmask) ? intstate : 0; + + avr8_set_irq_line(cpustate, condition.m_intindex, intstate); + + if (intstate) + { + cpustate->r[condition.m_regindex] &= ~condition.m_regmask; + } +} + +static void avr8_poll_interrupt(avr8_state *cpustate) +{ + for (int idx = 0; idx < AVR8_INTIDX_COUNT; idx++) + { + avr8_update_interrupt_internal(cpustate, idx); + } +} + +void avr8_update_interrupt(device_t *device, int source) +{ + avr8_state *cpustate = get_safe_token(device); + avr8_update_interrupt_internal(cpustate, source); +} + +/*****************************************************************************/ +// Timers + +static void avr8_timer_tick(avr8_state *cpustate, int cycles) +{ + if (cpustate->timer0_prescale != 0) + { + cpustate->timer0_prescale_count += cycles; + while(cpustate->timer0_prescale_count >= cpustate->timer0_prescale) + { + avr8_timer0_tick(cpustate); + cpustate->timer0_prescale_count -= cpustate->timer0_prescale; + } + } + + if (cpustate->timer1_prescale != 0) + { + cpustate->timer1_prescale_count += cycles; + while(cpustate->timer1_prescale_count >= cpustate->timer1_prescale) + { + avr8_timer1_tick(cpustate); + cpustate->timer1_prescale_count -= cpustate->timer1_prescale; + } + } + + if (cpustate->timer2_prescale != 0) + { + cpustate->timer2_prescale_count += cycles; + while(cpustate->timer2_prescale_count >= (cpustate->timer2_prescale)) + { + avr8_timer2_tick(cpustate); + cpustate->timer2_prescale_count -= (cpustate->timer2_prescale); + } + } +} + +// Timer 0 Handling +static void avr8_timer0_tick(avr8_state *cpustate) +{ + // TODO +} + +// Timer 1 Handling + +static void avr8_timer1_tick(avr8_state *cpustate) +{ + /* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */ + + UINT16 count = (cpustate->r[AVR8_REGIDX_TCNT1H] << 8) | cpustate->r[AVR8_REGIDX_TCNT1L]; + INT32 wgm1 = ((cpustate->r[AVR8_REGIDX_TCCR1B] & AVR8_TCCR1B_WGM1_32_MASK) >> 1) | + (cpustate->r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_WGM1_10_MASK); + + // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer + //UINT8 compare_mode[2] = { (cpustate->r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT, + //(cpustate->r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT }; + UINT16 ocr1[2] = { (cpustate->r[AVR8_REGIDX_OCR1AH] << 8) | cpustate->r[AVR8_REGIDX_OCR1AL], + (cpustate->r[AVR8_REGIDX_OCR1BH] << 8) | cpustate->r[AVR8_REGIDX_OCR1BL] }; + UINT8 ocf1[2] = { (1 << AVR8_TIFR1_OCF1A_SHIFT), (1 << AVR8_TIFR1_OCF1B_SHIFT) }; + UINT8 int1[2] = { AVR8_INTIDX_OCF1A, AVR8_INTIDX_OCF1B }; + INT32 increment = cpustate->timer1_increment; + + for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) + { + switch(wgm1) + { + case WGM1_FAST_PWM_OCR: + if(count == ocr1[reg]) + { + if (reg == 0) + { + cpustate->r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK; + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_TOV1); + count = 0; + increment = 0; + } + + cpustate->r[AVR8_REGIDX_TIFR1] |= ocf1[reg]; + avr8_update_interrupt_internal(cpustate, int1[reg]); + } + else if(count == 0) + { + if (reg == 0) + { + cpustate->r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_TOV1); + } + + cpustate->r[AVR8_REGIDX_TIFR1] &= ~ocf1[reg]; + avr8_update_interrupt_internal(cpustate, int1[reg]); + } + break; + + default: + // TODO + break; + } + /* + switch(compare_mode[reg]) + { + case 0: + //verboselog(cpustate->pc, 0, "avr8_update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n"); + break; + + case 1: + case 2: + // TODO + break; + + case 3: + break; + } + */ + } + + count += increment; + cpustate->r[AVR8_REGIDX_TCNT1H] = (count >> 8) & 0xff; + cpustate->r[AVR8_REGIDX_TCNT1L] = count & 0xff; +} + +static void avr8_change_timsk1(avr8_state *cpustate, UINT8 data) +{ + UINT8 oldtimsk = AVR8_TIMSK1; + UINT8 newtimsk = data; + UINT8 changed = newtimsk ^ oldtimsk; + + AVR8_TIMSK1 = newtimsk; + + if(changed & AVR8_TIMSK1_ICIE1_MASK) + { + // Check for Input Capture Interrupt interrupt condition + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_ICF1); + } + + if(changed & AVR8_TIMSK1_OCIE1B_MASK) + { + // Check for Output Compare B Interrupt interrupt condition + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_OCF1B); + } + + if(changed & AVR8_TIMSK1_OCIE1A_MASK) + { + // Check for Output Compare A Interrupt interrupt condition + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_OCF1A); + } + + if(changed & AVR8_TIMSK1_TOIE1_MASK) + { + // Check for Output Compare A Interrupt interrupt condition + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_TOV1); + } +} + +static void avr8_update_timer1_waveform_gen_mode(avr8_state *cpustate) +{ + // TODO + cpustate->timer1_top = 0; + verboselog(cpustate->pc, 0, "avr8_update_timer1_waveform_gen_mode: TODO; WGM1 is %d\n", AVR8_WGM1 ); + switch(AVR8_WGM1) + { + case WGM1_NORMAL: + cpustate->timer1_top = 0xffff; + break; + + case WGM1_PWM_8_PC: + case WGM1_FAST_PWM_8: + cpustate->timer1_top = 0x00ff; + break; + + case WGM1_PWM_9_PC: + case WGM1_FAST_PWM_9: + cpustate->timer1_top = 0x01ff; + break; + + case WGM1_PWM_10_PC: + case WGM1_FAST_PWM_10: + cpustate->timer1_top = 0x03ff; + break; + + case WGM1_PWM_PFC_ICR: + case WGM1_PWM_PC_ICR: + case WGM1_CTC_ICR: + case WGM1_FAST_PWM_ICR: + cpustate->timer1_top = AVR8_ICR1; + break; + + case WGM1_PWM_PFC_OCR: + case WGM1_PWM_PC_OCR: + case WGM1_CTC_OCR: + case WGM1_FAST_PWM_OCR: + cpustate->timer1_top = AVR8_OCR1A; + break; + + default: + verboselog(cpustate->pc, 0, "avr8_update_timer1_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM1); + break; + } +} + +static void avr8_changed_tccr1a(avr8_state *cpustate, UINT8 data) +{ + UINT8 oldtccr = AVR8_TCCR1A; + UINT8 newtccr = data; + UINT8 changed = newtccr ^ oldtccr; + + cpustate->r[AVR8_REGIDX_TCCR1A] = newtccr; + + if(changed & AVR8_TCCR1A_WGM1_10_MASK) + { + // TODO + avr8_update_timer1_waveform_gen_mode(cpustate); + } +} + +static void avr8_update_timer1_input_noise_canceler(avr8_state *cpustate) +{ + // TODO +} + +static void avr8_update_timer1_input_edge_select(avr8_state *cpustate) +{ + // TODO + //verboselog(cpustate->pc, 0, "avr8_update_timer1_input_edge_select: TODO; Clocking edge is %s\n", "test"); +} + +static void avr8_update_timer1_clock_source(avr8_state *cpustate) +{ + switch(AVR8_TIMER1_CLOCK_SELECT) + { + case 0: // Counter stopped + cpustate->timer1_prescale = 0; + break; + case 1: // Clk/1; no prescaling + cpustate->timer1_prescale = 1; + break; + case 2: // Clk/8 + cpustate->timer1_prescale = 8; + break; + case 3: // Clk/32 + cpustate->timer1_prescale = 32; + break; + case 4: // Clk/64 + cpustate->timer1_prescale = 64; + break; + case 5: // Clk/128 + cpustate->timer1_prescale = 128; + break; + case 6: // T1 trigger, falling edge + case 7: // T1 trigger, rising edge + cpustate->timer1_prescale = 0; + verboselog(cpustate->pc, 0, "avr8_update_timer1_clock_source: T1 Trigger mode not implemented yet\n"); + break; + } + + if (cpustate->timer1_prescale_count > cpustate->timer1_prescale) + { + cpustate->timer1_prescale_count = cpustate->timer1_prescale - 1; + } +} + +static void avr8_changed_tccr1b(avr8_state *cpustate, UINT8 data) +{ + UINT8 oldtccr = AVR8_TCCR1B; + UINT8 newtccr = data; + UINT8 changed = newtccr ^ oldtccr; + + cpustate->r[AVR8_REGIDX_TCCR1B] = newtccr; + + if(changed & AVR8_TCCR1B_ICNC1_MASK) + { + // TODO + avr8_update_timer1_input_noise_canceler(cpustate); + } + + if(changed & AVR8_TCCR1B_ICES1_MASK) + { + // TODO + avr8_update_timer1_input_edge_select(cpustate); + } + + if(changed & AVR8_TCCR1B_WGM1_32_MASK) + { + // TODO + avr8_update_timer1_waveform_gen_mode(cpustate); + } + + if(changed & AVR8_TCCR1B_CS_MASK) + { + avr8_update_timer1_clock_source(cpustate); + } +} + +static void avr8_update_ocr1(avr8_state *cpustate, UINT16 newval, UINT8 reg) +{ + UINT8 *p_reg_h = (reg == AVR8_REG_A) ? &cpustate->r[AVR8_REGIDX_OCR1AH] : &cpustate->r[AVR8_REGIDX_OCR1BH]; + UINT8 *p_reg_l = (reg == AVR8_REG_A) ? &cpustate->r[AVR8_REGIDX_OCR1AL] : &cpustate->r[AVR8_REGIDX_OCR1BL]; + *p_reg_h = (UINT8)(newval >> 8); + *p_reg_l = (UINT8)newval; + + // Nothing needs to be done? All handled in timer callback +} + +// Timer 2 Handling + +static void avr8_timer2_tick(avr8_state *cpustate) +{ + UINT16 count = cpustate->r[AVR8_REGIDX_TCNT2]; + INT32 wgm2 = ((cpustate->r[AVR8_REGIDX_TCCR2B] & AVR8_TCCR2B_WGM2_2_MASK) >> 1) | + (cpustate->r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_WGM2_10_MASK); + + // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer + //UINT8 compare_mode[2] = { (cpustate->r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT, + //(cpustate->r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT }; + UINT8 ocr2[2] = { cpustate->r[AVR8_REGIDX_OCR2A], cpustate->r[AVR8_REGIDX_OCR2B] }; + UINT8 ocf2[2] = { (1 << AVR8_TIFR2_OCF2A_SHIFT), (1 << AVR8_TIFR2_OCF2B_SHIFT) }; + INT32 increment = cpustate->timer2_increment; + + for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) + { + switch(wgm2) + { + case WGM2_FAST_PWM_CMP: + if(count == ocr2[reg]) + { + if (reg == 0) + { + cpustate->r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK; + count = 0; + increment = 0; + } + + cpustate->r[AVR8_REGIDX_TIFR2] |= ocf2[reg]; + } + else if(count == 0) + { + if (reg == 0) + { + cpustate->r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK; + } + } + break; + + default: + // TODO + break; + } + /* + switch(compare_mode[reg]) + { + case 0: + //verboselog(cpustate->pc, 0, "avr8_update_timer2_compare_mode: Normal port operation (OC2 disconnected)\n"); + break; + + case 1: + case 2: + // TODO + break; + + case 3: + break; + } + */ + } + + cpustate->r[AVR8_REGIDX_TCNT2] = count + increment; + + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_OCF2A); + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_OCF2B); + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_TOV2); +} + +static void avr8_update_timer2_waveform_gen_mode(avr8_state *cpustate) +{ + cpustate->timer2_top = 0; + switch(AVR8_WGM2) + { + case WGM2_NORMAL: + case WGM2_PWM_PC: + case WGM2_FAST_PWM: + cpustate->timer2_top = 0x00ff; + break; + + case WGM2_CTC_CMP: + case WGM2_PWM_PC_CMP: + case WGM2_FAST_PWM_CMP: + cpustate->timer2_top = AVR8_OCR2A; + break; + + default: + verboselog(cpustate->pc, 0, "avr8_update_timer2_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM2); + break; + } +} + +static void avr8_changed_tccr2a(avr8_state *cpustate, UINT8 data) +{ + UINT8 oldtccr = AVR8_TCCR2A; + UINT8 newtccr = data; + UINT8 changed = newtccr ^ oldtccr; + + if(changed & AVR8_TCCR2A_WGM2_10_MASK) + { + // TODO + avr8_update_timer2_waveform_gen_mode(cpustate); + } +} + +static void avr8_update_timer2_clock_source(avr8_state *cpustate) +{ + switch(AVR8_TIMER2_CLOCK_SELECT) + { + case 0: // Counter stopped + cpustate->timer2_prescale = 0; + break; + case 1: // Clk/1; no prescaling + cpustate->timer2_prescale = 1; + break; + case 2: // Clk/8 + cpustate->timer2_prescale = 8; + break; + case 3: // Clk/32 + cpustate->timer2_prescale = 32; + break; + case 4: // Clk/64 + cpustate->timer2_prescale = 64; + break; + case 5: // Clk/128 + cpustate->timer2_prescale = 128; + break; + case 6: // Clk/256 + cpustate->timer2_prescale = 256; + break; + case 7: // Clk/1024 + cpustate->timer2_prescale = 1024; + break; + } + + if (cpustate->timer2_prescale_count > cpustate->timer2_prescale) + { + cpustate->timer2_prescale_count = cpustate->timer2_prescale - 1; + } +} + +static void avr8_timer2_force_output_compare(avr8_state *cpustate, int reg) +{ + // TODO + verboselog(cpustate->pc, 0, "avr8_force_output_compare: TODO; should be forcing OC2%c\n", avr8_reg_name[reg]); +} + +static void avr8_changed_tccr2b(avr8_state *cpustate, UINT8 data) +{ + UINT8 oldtccr = AVR8_TCCR2B; + UINT8 newtccr = data; + UINT8 changed = newtccr ^ oldtccr; + + if(changed & AVR8_TCCR2B_FOC2A_MASK) + { + // TODO + avr8_timer2_force_output_compare(cpustate, AVR8_REG_A); + } + + if(changed & AVR8_TCCR2B_FOC2B_MASK) + { + // TODO + avr8_timer2_force_output_compare(cpustate, AVR8_REG_B); + } + + if(changed & AVR8_TCCR2B_WGM2_2_MASK) + { + // TODO + avr8_update_timer2_waveform_gen_mode(cpustate); + } + + if(changed & AVR8_TCCR2B_CS_MASK) + { + avr8_update_timer2_clock_source(cpustate); + } +} + +static void avr8_update_ocr2(avr8_state *cpustate, UINT8 newval, UINT8 reg) +{ + cpustate->r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR2A : AVR8_REGIDX_OCR2B] = newval; + + // Nothing needs to be done? All handled in timer callback +} + +/*****************************************************************************/ + +static bool avr8_io_reg_write(avr8_state *cpustate, UINT16 offset, UINT8 data) +{ + switch( offset ) + { + case AVR8_REGIDX_OCR1BH: + verboselog(cpustate->pc, 0, "AVR8: OCR1BH = %02x\n", data ); + avr8_update_ocr1(cpustate, (AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B); + return true; + + case AVR8_REGIDX_OCR1BL: + verboselog(cpustate->pc, 0, "AVR8: OCR1BL = %02x\n", data ); + avr8_update_ocr1(cpustate, (AVR8_OCR1B & 0xff00) | data, AVR8_REG_B); + return true; + + case AVR8_REGIDX_OCR1AH: + verboselog(cpustate->pc, 0, "AVR8: OCR1AH = %02x\n", data ); + avr8_update_ocr1(cpustate, (AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A); + return true; + + case AVR8_REGIDX_OCR1AL: + verboselog(cpustate->pc, 0, "AVR8: OCR1AL = %02x\n", data ); + avr8_update_ocr1(cpustate, (AVR8_OCR1A & 0xff00) | data, AVR8_REG_A); + return true; + + case AVR8_REGIDX_TCCR1B: + verboselog(cpustate->pc, 0, "AVR8: TCCR1B = %02x\n", data ); + avr8_changed_tccr1b(cpustate, data); + return true; + + case AVR8_REGIDX_TCCR1A: + verboselog(cpustate->pc, 0, "AVR8: TCCR1A = %02x\n", data ); + avr8_changed_tccr1a(cpustate, data); + return true; + + case AVR8_REGIDX_TIMSK1: + verboselog(cpustate->pc, 0, "AVR8: TIMSK1 = %02x\n", data ); + avr8_change_timsk1(cpustate, data); + return true; + + case AVR8_REGIDX_TIFR1: + verboselog(cpustate->pc, 0, "AVR8: TIFR1 = %02x\n", data ); + cpustate->r[AVR8_REGIDX_TIFR1] &= ~(data & AVR8_TIFR1_MASK); + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_ICF1); + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_OCF1A); + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_OCF1B); + avr8_update_interrupt_internal(cpustate, AVR8_INTIDX_TOV1); + return true; + + case AVR8_REGIDX_TCCR2B: + verboselog(cpustate->pc, 0, "AVR8: TCCR2B = %02x\n", data ); + avr8_changed_tccr2b(cpustate, data); + return true; + + case AVR8_REGIDX_TCCR2A: + verboselog(cpustate->pc, 0, "AVR8: TCCR2A = %02x\n", data ); + avr8_changed_tccr2a(cpustate, data); + return true; + + case AVR8_REGIDX_OCR2A: + avr8_update_ocr2(cpustate, data, AVR8_REG_A); + return true; + + case AVR8_REGIDX_OCR2B: + avr8_update_ocr2(cpustate, data, AVR8_REG_B); + return true; + + case AVR8_REGIDX_TCNT2: + AVR8_TCNT2 = data; + return true; + + case AVR8_REGIDX_GTCCR: + if (data & AVR8_GTCCR_PSRASY_MASK) + { + data &= ~AVR8_GTCCR_PSRASY_MASK; + cpustate->timer2_prescale_count = 0; + } + //verboselog(cpustate->pc, 0, "AVR8: GTCCR = %02x\n", data ); + // TODO + return true; + + case AVR8_REGIDX_SPL: + case AVR8_REGIDX_SPH: + case AVR8_REGIDX_GPIOR0: + cpustate->r[offset] = data; + return true; + + case AVR8_REGIDX_SREG: + cpustate->status = data; + return true; + + default: + verboselog(cpustate->pc, 0, "AVR8: Unrecognized register write: %02x = %02x\n", offset, data ); + return false; + } + return false; +} + +static bool avr8_io_reg_read(avr8_state *cpustate, UINT16 offset, UINT8 *data) +{ + switch( offset ) + { + case AVR8_REGIDX_SPL: + case AVR8_REGIDX_SPH: + case AVR8_REGIDX_TCNT1L: + case AVR8_REGIDX_TCNT1H: + case AVR8_REGIDX_GPIOR0: + *data = cpustate->r[offset]; + return true; + + case AVR8_REGIDX_SREG: + *data = cpustate->status; + return true; + + default: + verboselog(cpustate->pc, 0, "AVR8: Unrecognized register read: %02x\n", offset ); + return false; + } + + return false; +} + /*****************************************************************************/ static CPU_INIT( avr8 ) @@ -191,7 +1063,42 @@ static CPU_INIT( avr8 ) cpustate->program = &device->space(AS_PROGRAM); cpustate->io = &device->space(AS_IO); - WRITE_IO_8(cpustate, AVR8_IO_SREG, 0); + cpustate->status = 0; + WRITE_IO_8(cpustate, AVR8_REGIDX_SPL, 0); + WRITE_IO_8(cpustate, AVR8_REGIDX_SPH, 0); + + for (int i = 0; i < 32; i++) + { + cpustate->r[i] = 0; + } + + cpustate->timer0_top = 0; + cpustate->timer0_increment = 1; + cpustate->timer0_prescale = 0; + cpustate->timer0_prescale_count = 0; + + cpustate->timer1_top = 0; + cpustate->timer1_increment = 1; + cpustate->timer1_prescale = 0; + cpustate->timer1_prescale_count = 0; + + cpustate->timer2_top = 0; + cpustate->timer2_increment = 1; + cpustate->timer2_prescale = 0; + cpustate->timer2_prescale_count = 0; + + AVR8_TIMSK1 = 0; + AVR8_OCR1AH = 0; + AVR8_OCR1AL = 0; + AVR8_OCR1BH = 0; + AVR8_OCR1BL = 0; + AVR8_ICR1H = 0; + AVR8_ICR1L = 0; + AVR8_TCNT1H = 0; + AVR8_TCNT1L = 0; + AVR8_TCNT2 = 0; + + cpustate->interrupt_pending = false; device->save_item(NAME(cpustate->pc)); } @@ -204,8 +1111,10 @@ static CPU_RESET( avr8 ) { avr8_state *cpustate = get_safe_token(device); - WRITE_IO_8(cpustate, AVR8_IO_SREG, 0); + cpustate->status = 0; cpustate->pc = 0; + + cpustate->interrupt_pending = false; } static CPU_EXECUTE( avr8 ) @@ -237,17 +1146,21 @@ static CPU_EXECUTE( avr8 ) case 0x0000: // NOP break; case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd - WRITE_IO_8(cpustate, (RD4(op) << 1)+1, READ_IO_8(cpustate, (RR4(op) << 1)+1)); - WRITE_IO_8(cpustate, RD4(op) << 1, READ_IO_8(cpustate, RR4(op) << 1)); + cpustate->r[(RD4(op) << 1) + 1] = cpustate->r[(RR4(op) << 1) + 1]; + cpustate->r[RD4(op) << 1] = cpustate->r[RR4(op) << 1]; break; case 0x0200: // MULS Rd,Rr - //output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) ); - unimplemented_opcode(cpustate, op); + sd = (INT8)cpustate->r[16 + RD4(op)] * (INT8)cpustate->r[16 + RR4(op)]; + cpustate->r[1] = (sd >> 8) & 0x00ff; + cpustate->r[0] = sd & 0x00ff; + SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0); + SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0); + opcycles = 2; break; case 0x0300: // MULSU Rd,Rr - sd = (INT8)READ_IO_8(cpustate, 16+RD4(op)) * (UINT8)READ_IO_8(cpustate, 16+RR4(op)); - WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff); - WRITE_IO_8(cpustate, 0, sd & 0x00ff); + sd = (INT8)cpustate->r[16 + RD4(op)] * (UINT8)cpustate->r[16 + RR4(op)]; + cpustate->r[1] = (sd >> 8) & 0x00ff; + cpustate->r[0] = sd & 0x00ff; SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0); SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0); opcycles = 2; @@ -256,8 +1169,8 @@ static CPU_EXECUTE( avr8 ) case 0x0500: case 0x0600: case 0x0700: // CPC Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; res = rd - (rr + SREG_R(AVR8_SREG_C)); SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7))); @@ -270,10 +1183,10 @@ static CPU_EXECUTE( avr8 ) case 0x0900: case 0x0a00: case 0x0b00: // SBC Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; res = rd - (rr + SREG_R(AVR8_SREG_C)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7))); SREG_W(AVR8_SREG_N, BIT(res,7)); @@ -285,10 +1198,10 @@ static CPU_EXECUTE( avr8 ) case 0x0d00: case 0x0e00: case 0x0f00: // ADD Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; res = rd + rr; - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; SREG_W(AVR8_SREG_H, (BIT(rd,3) & BIT(rr,3)) | (BIT(rr,3) & NOT(BIT(res,3))) | (NOT(BIT(res,3)) & BIT(rd,3))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & NOT(BIT(rr,7)) & BIT(res,7))); SREG_W(AVR8_SREG_N, BIT(res,7)); @@ -306,8 +1219,8 @@ static CPU_EXECUTE( avr8 ) unimplemented_opcode(cpustate, op); break; case 0x0400: // CP Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; res = rd - rr; SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7))); @@ -317,10 +1230,10 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7)))); break; case 0x0800: // SUB Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; res = rd - rr; - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7))); SREG_W(AVR8_SREG_N, BIT(res,7)); @@ -329,10 +1242,10 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7)))); break; case 0x0c00: // ADC Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; res = rd + rr + SREG_R(AVR8_SREG_C); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; SREG_W(AVR8_SREG_H, (BIT(rd,3) & BIT(rr,3)) | (BIT(rr,3) & NOT(BIT(res,3))) | (NOT(BIT(res,3)) & BIT(rd,3))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & NOT(BIT(rr,7)) & BIT(res,7))); SREG_W(AVR8_SREG_N, BIT(res,7)); @@ -346,43 +1259,42 @@ static CPU_EXECUTE( avr8 ) switch(op & 0x0c00) { case 0x0000: // AND Rd,Rr - //output += sprintf( output, "AND R%d, R%d", RD5(op), RR5(op) ); - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; rd &= rr; SREG_W(AVR8_SREG_V, 0); SREG_W(AVR8_SREG_N, rd & 0x80); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), rd); + cpustate->r[RD5(op)] = rd; break; case 0x0400: // EOR Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; rd ^= rr; SREG_W(AVR8_SREG_V, 0); SREG_W(AVR8_SREG_N, rd & 0x80); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), rd); + cpustate->r[RD5(op)] = rd; break; case 0x0800: // OR Rd,Rr - rd = READ_IO_8(cpustate, RD5(op)); - rr = READ_IO_8(cpustate, RR5(op)); + rd = cpustate->r[RD5(op)]; + rr = cpustate->r[RR5(op)]; rd |= rr; SREG_W(AVR8_SREG_V, 0); SREG_W(AVR8_SREG_N, rd & 0x80); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), rd); + cpustate->r[RD5(op)] = rd; break; case 0x0c00: // MOV Rd,Rr - WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RR5(op))); + cpustate->r[RD5(op)] = cpustate->r[RR5(op)]; break; } break; case 0x3000: // CPI Rd,K - rd = READ_IO_8(cpustate, 16+RD4(op)); + rd = cpustate->r[16 + RD4(op)]; rr = KCONST8(op); res = rd - rr; SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); @@ -393,10 +1305,10 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7)))); break; case 0x4000: // SBCI Rd,K - rd = READ_IO_8(cpustate, 16+RD4(op)); + rd = cpustate->r[16 + RD4(op)]; rr = KCONST8(op); res = rd - (rr + SREG_R(AVR8_SREG_C)); - WRITE_IO_8(cpustate, 16+RD4(op), res); + cpustate->r[16 + RD4(op)] = res; SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7))); SREG_W(AVR8_SREG_N, BIT(res,7)); @@ -405,10 +1317,10 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7)))); break; case 0x5000: // SUBI Rd,K - rd = READ_IO_8(cpustate, 16+RD4(op)); + rd = cpustate->r[16 + RD4(op)]; rr = KCONST8(op); res = rd - rr; - WRITE_IO_8(cpustate, 16+RD4(op), res); + cpustate->r[16 + RD4(op)] = res; SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3)))); SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7))); SREG_W(AVR8_SREG_N, BIT(res,7)); @@ -417,18 +1329,24 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7)))); break; case 0x6000: // ORI Rd,K - rd = READ_IO_8(cpustate, 16+RD4(op)); + rd = cpustate->r[16 + RD4(op)]; rr = KCONST8(op); rd |= rr; SREG_W(AVR8_SREG_V, 0); SREG_W(AVR8_SREG_N, rd & 0x80); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - WRITE_IO_8(cpustate, 16+RD4(op), rd); + cpustate->r[16 + RD4(op)] = rd; break; case 0x7000: // ANDI Rd,K - //output += sprintf( output, "ANDI R%d, 0x%02x", 16+RD4(op), KCONST8(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[16 + RD4(op)]; + rr = KCONST8(op); + rd &= rr; + SREG_W(AVR8_SREG_V, 0); + SREG_W(AVR8_SREG_N, rd & 0x80); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); + cpustate->r[16 + RD4(op)] = rd; break; case 0x8000: case 0xa000: @@ -439,15 +1357,15 @@ static CPU_EXECUTE( avr8 ) unimplemented_opcode(cpustate, op); break; case 0x0008: // LDD Rd,Y+q - WRITE_IO_8(cpustate, RD5(op), YREG + QCONST6(op)); + cpustate->r[RD5(op)] = READ_IO_8(cpustate, YREG + QCONST6(op)); opcycles = 2; break; case 0x0200: // STD Z+q,Rr - //output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) ); - unimplemented_opcode(cpustate, op); + WRITE_IO_8(cpustate, ZREG + QCONST6(op), cpustate->r[RD5(op)]); + opcycles = 2; break; case 0x0208: // STD Y+q,Rr - WRITE_IO_8(cpustate, YREG + QCONST6(op), READ_IO_8(cpustate, RD5(op))); + WRITE_IO_8(cpustate, YREG + QCONST6(op), cpustate->r[RD5(op)]); opcycles = 2; break; } @@ -463,26 +1381,30 @@ static CPU_EXECUTE( avr8 ) op <<= 16; cpustate->pc++; op |= READ_PRG_16(cpustate, cpustate->pc); - WRITE_IO_8(cpustate, RD5(op >> 16), READ_IO_8(cpustate, op & 0x0000ffff)); + cpustate->r[RD5(op >> 16)] = READ_IO_8(cpustate, op & 0x0000ffff); opcycles = 2; break; case 0x0001: // LD Rd,Z+ unimplemented_opcode(cpustate, op); break; case 0x0002: // LD Rd,-Z - //output += sprintf( output, "LD R%d,-Z", RD5(op) ); - unimplemented_opcode(cpustate, op); + pd = ZREG; + pd--; + cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); + cpustate->r[27] = (pd >> 8) & 0x00ff; + cpustate->r[26] = pd & 0x00ff; + opcycles = 2; break; case 0x0004: // LPM Rd,Z - WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, ZREG)); + cpustate->r[RD5(op)] = READ_PRG_8(cpustate, ZREG); opcycles = 3; break; case 0x0005: // LPM Rd,Z+ pd = ZREG; - WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, pd)); + cpustate->r[RD5(op)] = READ_PRG_8(cpustate, pd); pd++; - WRITE_IO_8(cpustate, 31, (pd >> 8) & 0x00ff); - WRITE_IO_8(cpustate, 30, pd & 0x00ff); + cpustate->r[31] = (pd >> 8) & 0x00ff; + cpustate->r[30] = pd & 0x00ff; opcycles = 3; break; case 0x0006: // ELPM Rd,Z @@ -494,31 +1416,42 @@ static CPU_EXECUTE( avr8 ) unimplemented_opcode(cpustate, op); break; case 0x0009: // LD Rd,Y+ - //output += sprintf( output, "LD R%d, Y+", RD5(op) ); - unimplemented_opcode(cpustate, op); + pd = YREG; + cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); + pd++; + cpustate->r[29] = (pd >> 8) & 0x00ff; + cpustate->r[28] = pd & 0x00ff; + opcycles = 2; break; case 0x000a: // LD Rd,-Y - //output += sprintf( output, "LD R%d,-Y", RD5(op) ); - unimplemented_opcode(cpustate, op); + pd = YREG; + pd--; + cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); + cpustate->r[27] = (pd >> 8) & 0x00ff; + cpustate->r[26] = pd & 0x00ff; + opcycles = 2; break; case 0x000c: // LD Rd,X - //output += sprintf( output, "LD R%d, X", RD5(op) ); - unimplemented_opcode(cpustate, op); + cpustate->r[RD5(op)] = READ_IO_8(cpustate, XREG); break; case 0x000d: // LD Rd,X+ pd = XREG; - WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, pd)); + cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); pd++; - WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff); - WRITE_IO_8(cpustate, 26, pd & 0x00ff); + cpustate->r[27] = (pd >> 8) & 0x00ff; + cpustate->r[26] = pd & 0x00ff; opcycles = 2; break; case 0x000e: // LD Rd,-X - //output += sprintf( output, "LD R%d,-X", RD5(op) ); - unimplemented_opcode(cpustate, op); + pd = XREG; + pd--; + cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); + cpustate->r[27] = (pd >> 8) & 0x00ff; + cpustate->r[26] = pd & 0x00ff; + opcycles = 2; break; case 0x000f: // POP Rd - WRITE_IO_8(cpustate, RD5(op), POP(cpustate)); + cpustate->r[RD5(op)] = POP(cpustate); opcycles = 2; break; default: @@ -535,7 +1468,7 @@ static CPU_EXECUTE( avr8 ) op <<= 16; cpustate->pc++; op |= READ_PRG_16(cpustate, cpustate->pc); - WRITE_IO_8(cpustate, op & 0x0000ffff, READ_IO_8(cpustate, RD5(op >> 16))); + WRITE_IO_8(cpustate, op & 0x0000ffff, cpustate->r[RD5(op >> 16)]); opcycles = 2; break; case 0x0001: // ST Z+,Rd @@ -548,35 +1481,31 @@ static CPU_EXECUTE( avr8 ) break; case 0x0009: // ST Y+,Rd pd = YREG; - WRITE_IO_8(cpustate, pd, READ_IO_8(cpustate, RD5(op))); + WRITE_IO_8(cpustate, pd, cpustate->r[RD5(op)]); pd++; - WRITE_IO_8(cpustate, 29, (pd >> 8) & 0x00ff); - WRITE_IO_8(cpustate, 28, pd & 0x00ff); - opcycles = 2; + cpustate->r[29] = (pd >> 8) & 0x00ff; + cpustate->r[28] = pd & 0x00ff; break; case 0x000a: // ST -Z,Rd //output += sprintf( output, "ST -Y , R%d", RD5(op) ); unimplemented_opcode(cpustate, op); break; case 0x000c: // ST X,Rd - rd = READ_IO_8(cpustate, RD5(op)); - WRITE_IO_8(cpustate, XREG, rd); - opcycles = 2; + WRITE_IO_8(cpustate, XREG, cpustate->r[RD5(op)]); break; case 0x000d: // ST X+,Rd pd = XREG; - WRITE_IO_8(cpustate, pd, READ_IO_8(cpustate, RD5(op))); + WRITE_IO_8(cpustate, pd, cpustate->r[RD5(op)]); pd++; - WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff); - WRITE_IO_8(cpustate, 26, pd & 0x00ff); - opcycles = 2; + cpustate->r[27] = (pd >> 8) & 0x00ff; + cpustate->r[26] = pd & 0x00ff; break; case 0x000e: // ST -X,Rd //output += sprintf( output, "ST -X , R%d", RD5(op) ); unimplemented_opcode(cpustate, op); break; case 0x000f: // PUSH Rd - PUSH(cpustate, READ_IO_8(cpustate, RD5(op))); + PUSH(cpustate, cpustate->r[RD5(op)]); opcycles = 2; break; default: @@ -589,17 +1518,17 @@ static CPU_EXECUTE( avr8 ) switch(op & 0x000f) { case 0x0000: // COM Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = ~rd; SREG_W(AVR8_SREG_C, 1); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); SREG_W(AVR8_SREG_N, BIT(res,7)); SREG_W(AVR8_SREG_V, 0); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0001: // NEG Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = 0 - rd; SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); @@ -607,38 +1536,51 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_V, (res == 0x80) ? 1 : 0); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_H, BIT(res,3) | BIT(rd,3)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0002: // SWAP Rd - //output += sprintf( output, "SWAP R%d", RD5(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[RD5(op)]; + cpustate->r[RD5(op)] = (rd >> 4) | (rd << 4); break; case 0x0003: // INC Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = rd + 1; SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0); SREG_W(AVR8_SREG_N, BIT(res,7)); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0005: // ASR Rd - //output += sprintf( output, "ASR R%d", RD5(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[RD5(op)]; + res = (rd & 0x80) | (rd >> 1); + SREG_W(AVR8_SREG_C, rd & 0x01); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_N, (rd & 0x80) ? 1 : 0); + SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + cpustate->r[RD5(op)] = res; break; case 0x0006: // LSR Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = rd >> 1; SREG_W(AVR8_SREG_C, rd & 0x01); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); SREG_W(AVR8_SREG_N, 0); SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C)); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0007: // ROR Rd - //output += sprintf( output, "ROR R%d", RD5(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[RD5(op)]; + res = rd >> 1; + res |= (SREG_R(AVR8_SREG_C) << 7); + SREG_W(AVR8_SREG_C, rd & 0x01); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); + SREG_W(AVR8_SREG_N, res & 7); + SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + cpustate->r[RD5(op)] = res; break; case 0x0008: switch(op & 0x00f0) @@ -683,13 +1625,13 @@ static CPU_EXECUTE( avr8 ) } break; case 0x000a: // DEC Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = rd - 1; SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0); SREG_W(AVR8_SREG_N, BIT(res,7)); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x000c: case 0x000d: // JMP k @@ -698,7 +1640,7 @@ static CPU_EXECUTE( avr8 ) offs |= READ_PRG_16(cpustate, cpustate->pc); cpustate->pc = offs; cpustate->pc--; - opcycles = 4; + opcycles = 3; break; case 0x000e: // CALL k case 0x000f: @@ -709,6 +1651,7 @@ static CPU_EXECUTE( avr8 ) offs |= READ_PRG_16(cpustate, cpustate->pc); cpustate->pc = offs; cpustate->pc--; + opcycles = 4; break; default: unimplemented_opcode(cpustate, op); @@ -720,17 +1663,17 @@ static CPU_EXECUTE( avr8 ) switch(op & 0x000f) { case 0x0000: // COM Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = ~rd; SREG_W(AVR8_SREG_C, 1); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); SREG_W(AVR8_SREG_N, BIT(res,7)); SREG_W(AVR8_SREG_V, 0); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0001: // NEG Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = 0 - rd; SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); @@ -738,38 +1681,51 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_V, (res == 0x80) ? 1 : 0); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_H, BIT(res,3) | BIT(rd,3)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0002: // SWAP Rd - //output += sprintf( output, "SWAP R%d", RD5(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[RD5(op)]; + cpustate->r[RD5(op)] = (rd >> 4) | (rd << 4); break; case 0x0003: // INC Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = rd + 1; SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0); SREG_W(AVR8_SREG_N, BIT(res,7)); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0005: // ASR Rd - //output += sprintf( output, "ASR R%d", RD5(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[RD5(op)]; + res = (rd & 0x80) | (rd >> 1); + SREG_W(AVR8_SREG_C, rd & 0x01); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_N, (rd & 0x80) ? 1 : 0); + SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + cpustate->r[RD5(op)] = res; break; case 0x0006: // LSR Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = rd >> 1; SREG_W(AVR8_SREG_C, rd & 0x01); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); SREG_W(AVR8_SREG_N, 0); SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C)); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x0007: // ROR Rd - //output += sprintf( output, "ROR R%d", RD5(op) ); - unimplemented_opcode(cpustate, op); + rd = cpustate->r[RD5(op)]; + res = rd >> 1; + res |= (SREG_R(AVR8_SREG_C) << 7); + SREG_W(AVR8_SREG_C, rd & 0x01); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); + SREG_W(AVR8_SREG_N, res & 7); + SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + cpustate->r[RD5(op)] = res; break; case 0x0008: switch(op & 0x00f0) @@ -783,8 +1739,14 @@ static CPU_EXECUTE( avr8 ) case 0x0010: // RETI cpustate->pc = POP(cpustate); cpustate->pc |= POP(cpustate) << 8; + //printf("Pop: %04x\n", cpustate->pc); cpustate->pc--; SREG_W(AVR8_SREG_I, 1); + if (cpustate->interrupt_pending) + { + avr8_poll_interrupt(cpustate); + cpustate->interrupt_pending = false; + } opcycles = 4; break; case 0x0080: // SLEEP @@ -800,7 +1762,7 @@ static CPU_EXECUTE( avr8 ) unimplemented_opcode(cpustate, op); break; case 0x00c0: // LPM - WRITE_IO_8(cpustate, 0, READ_PRG_8(cpustate, ZREG)); + cpustate->r[0] = READ_PRG_8(cpustate, ZREG); opcycles = 3; break; case 0x00d0: // ELPM @@ -839,13 +1801,13 @@ static CPU_EXECUTE( avr8 ) } break; case 0x000a: // DEC Rd - rd = READ_IO_8(cpustate, RD5(op)); + rd = cpustate->r[RD5(op)]; res = rd - 1; SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0); SREG_W(AVR8_SREG_N, BIT(res,7)); SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - WRITE_IO_8(cpustate, RD5(op), res); + cpustate->r[RD5(op)] = res; break; case 0x000c: case 0x000d: // JMP k @@ -868,8 +1830,8 @@ static CPU_EXECUTE( avr8 ) } break; case 0x0600: // ADIW Rd+1:Rd,K - rd = READ_IO_8(cpustate, 24 + (DCONST(op) << 1)); - rr = READ_IO_8(cpustate, 25 + (DCONST(op) << 1)); + rd = cpustate->r[24 + (DCONST(op) << 1)]; + rr = cpustate->r[25 + (DCONST(op) << 1)]; pd = rd; pd |= rr << 8; pd += KCONST6(op); @@ -878,8 +1840,8 @@ static CPU_EXECUTE( avr8 ) SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); SREG_W(AVR8_SREG_Z, (pd == 0) ? 1 : 0); SREG_W(AVR8_SREG_C, NOT(BIT(pd,15)) & BIT(rr,7)); - WRITE_IO_8(cpustate, 24 + (DCONST(op) << 1), pd & 0xff); - WRITE_IO_8(cpustate, 25 + (DCONST(op) << 1), (pd >> 8) & 0xff); + cpustate->r[24 + (DCONST(op) << 1)] = pd & 0x00ff; + cpustate->r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff; opcycles = 2; break; case 0x0700: // SBIW Rd+1:Rd,K @@ -888,47 +1850,48 @@ static CPU_EXECUTE( avr8 ) break; case 0x0800: // CBI A,b //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) ); - WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) &~ (1 << RR3(op))); + WRITE_IO_8(cpustate, 32 + ACONST5(op), READ_IO_8(cpustate, 32 + ACONST5(op)) &~ (1 << RR3(op))); opcycles = 2; break; case 0x0900: // SBIC A,b - if(!(READ_IO_8(cpustate, ACONST5(op)) & (1 << RR3(op)))) + if(NOT(BIT(READ_IO_8(cpustate, 32 + ACONST5(op)), (1 << RR3(op))))) { opcycles += avr8_is_long_opcode(op) ? 2 : 1; cpustate->pc += avr8_is_long_opcode(op) ? 2 : 1; } break; case 0x0a00: // SBI A,b - //output += sprintf( output, "SBI 0x%02x, %d", ACONST5(op), RR3(op) ); - WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) | (1 << RR3(op))); + WRITE_IO_8(cpustate, 32 + ACONST5(op), READ_IO_8(cpustate, 32 + ACONST5(op)) | (1 << RR3(op))); opcycles = 2; break; case 0x0b00: // SBIS A,b - //output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) ); - unimplemented_opcode(cpustate, op); + if(BIT(READ_IO_8(cpustate, 32 + ACONST5(op)), (1 << RR3(op)))) + { + opcycles += avr8_is_long_opcode(op) ? 2 : 1; + cpustate->pc += avr8_is_long_opcode(op) ? 2 : 1; + } break; case 0x0c00: case 0x0d00: case 0x0e00: case 0x0f00: // MUL Rd,Rr - sd = (UINT8)READ_IO_8(cpustate, RD5(op)) * (UINT8)READ_IO_8(cpustate, RR5(op)); - WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff); - WRITE_IO_8(cpustate, 0, sd & 0x00ff); + sd = (UINT8)cpustate->r[RD5(op)] * (UINT8)cpustate->r[RR5(op)]; + cpustate->r[1] = (sd >> 8) & 0x00ff; + cpustate->r[0] = sd & 0x00ff; SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0); SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0); opcycles = 2; - //output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) ); break; } break; case 0xb000: if(op & 0x0800) // OUT A,Rr { - WRITE_IO_8(cpustate, 0x20 + ACONST6(op), READ_IO_8(cpustate, RD5(op))); + WRITE_IO_8(cpustate, 32 + ACONST6(op), cpustate->r[RD5(op)]); } else // IN Rd,A { - WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, 0x20 + ACONST6(op))); + cpustate->r[RD5(op)] = READ_IO_8(cpustate, 0x20 + ACONST6(op)); } break; case 0xc000: // RJMP k @@ -944,8 +1907,7 @@ static CPU_EXECUTE( avr8 ) opcycles = 3; break; case 0xe000: // LDI Rd,K - rd = KCONST8(op); - WRITE_IO_8(cpustate, 16 + RD4(op), rd); + cpustate->r[16 + RD4(op)] = KCONST8(op); break; case 0xf000: switch(op & 0x0c00) @@ -977,47 +1939,37 @@ static CPU_EXECUTE( avr8 ) case 0x0800: if(op & 0x0200) // BST Rd, b { - SREG_W(AVR8_SREG_T, (BIT(READ_IO_8(cpustate, RD5(op)),RR3(op))) ? 1 : 0); + SREG_W(AVR8_SREG_T, (BIT(cpustate->r[RD5(op)], RR3(op))) ? 1 : 0); } else // BLD Rd, b { if(SREG_R(AVR8_SREG_T)) { - WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) | (1 << RR3(op))); + cpustate->r[RD5(op)] |= (1 << RR3(op)); } else { - WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) &~ (1 << RR3(op))); + cpustate->r[RD5(op)] &= ~(1 << RR3(op)); } } break; case 0x0c00: if(op & 0x0200) // SBRS Rd, b { - if(BIT(READ_IO_8(cpustate, RD5(op)),RR3(op))) + if(BIT(cpustate->r[RD5(op)], RR3(op))) { op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++); - opcycles = 2; - if((op & 0xfe0c) == 0x940c || - (op & 0xfe0f) == 0xfe0f) - { - cpustate->pc++; - opcycles = 3; - } + cpustate->pc += avr8_is_long_opcode(op) ? 1 : 0; + opcycles = avr8_is_long_opcode(op) ? 3 : 2; } } else // SBRC Rd, b { - if(!BIT(READ_IO_8(cpustate, RD5(op)),RR3(op))) + if(!BIT(cpustate->r[RD5(op)], RR3(op))) { op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++); - opcycles = 2; - if((op & 0xfe0c) == 0x940c || - (op & 0xfc0f) == 0x9000) - { - cpustate->pc++; - opcycles = 3; - } + cpustate->pc += avr8_is_long_opcode(op) ? 1 : 0; + opcycles = avr8_is_long_opcode(op) ? 3 : 2; } } break; @@ -1028,6 +1980,8 @@ static CPU_EXECUTE( avr8 ) cpustate->pc++; cpustate->icount -= opcycles; + + avr8_timer_tick(cpustate, opcycles); } } @@ -1069,40 +2023,40 @@ static CPU_SET_INFO( avr8 ) /* --- the following bits of info are set as 64-bit signed integers --- */ case CPUINFO_INT_PC: /* intentional fallthrough */ - case CPUINFO_INT_REGISTER + AVR8_PC: cpustate->pc = info->i; break; - case CPUINFO_INT_REGISTER + AVR8_SREG: WRITE_IO_8(cpustate, AVR8_IO_SREG, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R0: WRITE_IO_8(cpustate, 0, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R1: WRITE_IO_8(cpustate, 1, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R2: WRITE_IO_8(cpustate, 2, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R3: WRITE_IO_8(cpustate, 3, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R4: WRITE_IO_8(cpustate, 4, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R5: WRITE_IO_8(cpustate, 5, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R6: WRITE_IO_8(cpustate, 6, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R7: WRITE_IO_8(cpustate, 7, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R8: WRITE_IO_8(cpustate, 8, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R9: WRITE_IO_8(cpustate, 9, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R10: WRITE_IO_8(cpustate, 10, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R11: WRITE_IO_8(cpustate, 11, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R12: WRITE_IO_8(cpustate, 12, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R13: WRITE_IO_8(cpustate, 13, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R14: WRITE_IO_8(cpustate, 14, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R15: WRITE_IO_8(cpustate, 15, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R16: WRITE_IO_8(cpustate, 16, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R17: WRITE_IO_8(cpustate, 17, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R18: WRITE_IO_8(cpustate, 18, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R19: WRITE_IO_8(cpustate, 19, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R20: WRITE_IO_8(cpustate, 20, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R21: WRITE_IO_8(cpustate, 21, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R22: WRITE_IO_8(cpustate, 22, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R23: WRITE_IO_8(cpustate, 23, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R24: WRITE_IO_8(cpustate, 24, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R25: WRITE_IO_8(cpustate, 25, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R26: WRITE_IO_8(cpustate, 26, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R27: WRITE_IO_8(cpustate, 27, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R28: WRITE_IO_8(cpustate, 28, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R29: WRITE_IO_8(cpustate, 29, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R30: WRITE_IO_8(cpustate, 30, info->i); break; - case CPUINFO_INT_REGISTER + AVR8_R31: WRITE_IO_8(cpustate, 31, info->i); break; + case CPUINFO_INT_REGISTER + AVR8_PC: cpustate->pc = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_SREG: cpustate->status = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R0: cpustate->r[ 0] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R1: cpustate->r[ 1] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R2: cpustate->r[ 2] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R3: cpustate->r[ 3] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R4: cpustate->r[ 4] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R5: cpustate->r[ 5] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R6: cpustate->r[ 6] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R7: cpustate->r[ 7] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R8: cpustate->r[ 8] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R9: cpustate->r[ 9] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R10: cpustate->r[10] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R11: cpustate->r[11] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R12: cpustate->r[12] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R13: cpustate->r[13] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R14: cpustate->r[14] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R15: cpustate->r[15] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R16: cpustate->r[16] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R17: cpustate->r[17] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R18: cpustate->r[18] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R19: cpustate->r[19] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R20: cpustate->r[20] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R21: cpustate->r[21] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R22: cpustate->r[22] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R23: cpustate->r[23] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R24: cpustate->r[24] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R25: cpustate->r[25] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R26: cpustate->r[26] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R27: cpustate->r[27] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R28: cpustate->r[28] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R29: cpustate->r[29] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R30: cpustate->r[30] = info->i; break; + case CPUINFO_INT_REGISTER + AVR8_R31: cpustate->r[31] = info->i; break; } } @@ -1135,8 +2089,8 @@ CPU_GET_INFO( avr8 ) case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; case CPUINFO_INT_PC: /* intentional fallthrough */ - case CPUINFO_INT_REGISTER + AVR8_PC: info->i = cpustate->pc << 1; break; - case CPUINFO_INT_REGISTER + AVR8_SREG: info->i = READ_IO_8(cpustate, AVR8_IO_SREG); break; + case CPUINFO_INT_REGISTER + AVR8_PC: info->i = cpustate->pc << 1; break; + case CPUINFO_INT_REGISTER + AVR8_SREG: info->i = cpustate->status; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(avr8); break; @@ -1157,39 +2111,39 @@ CPU_GET_INFO( avr8 ) case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break; - case CPUINFO_STR_REGISTER + AVR8_SREG: sprintf(info->s, "SREG: %c%c%c%c%c%c%c%c", (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x80) ? 'I' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x40) ? 'T' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x20) ? 'H' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x10) ? 'S' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x08) ? 'V' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x04) ? 'N' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x02) ? 'Z' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x01) ? 'C' : '-'); break; - case CPUINFO_STR_REGISTER + AVR8_R0: sprintf(info->s, "R0: %02x", READ_IO_8(cpustate, 0) ); break; - case CPUINFO_STR_REGISTER + AVR8_R1: sprintf(info->s, "R1: %02x", READ_IO_8(cpustate, 1) ); break; - case CPUINFO_STR_REGISTER + AVR8_R2: sprintf(info->s, "R2: %02x", READ_IO_8(cpustate, 2) ); break; - case CPUINFO_STR_REGISTER + AVR8_R3: sprintf(info->s, "R3: %02x", READ_IO_8(cpustate, 3) ); break; - case CPUINFO_STR_REGISTER + AVR8_R4: sprintf(info->s, "R4: %02x", READ_IO_8(cpustate, 4) ); break; - case CPUINFO_STR_REGISTER + AVR8_R5: sprintf(info->s, "R5: %02x", READ_IO_8(cpustate, 5) ); break; - case CPUINFO_STR_REGISTER + AVR8_R6: sprintf(info->s, "R6: %02x", READ_IO_8(cpustate, 6) ); break; - case CPUINFO_STR_REGISTER + AVR8_R7: sprintf(info->s, "R7: %02x", READ_IO_8(cpustate, 7) ); break; - case CPUINFO_STR_REGISTER + AVR8_R8: sprintf(info->s, "R8: %02x", READ_IO_8(cpustate, 8) ); break; - case CPUINFO_STR_REGISTER + AVR8_R9: sprintf(info->s, "R9: %02x", READ_IO_8(cpustate, 9) ); break; - case CPUINFO_STR_REGISTER + AVR8_R10: sprintf(info->s, "R10: %02x", READ_IO_8(cpustate, 10) ); break; - case CPUINFO_STR_REGISTER + AVR8_R11: sprintf(info->s, "R11: %02x", READ_IO_8(cpustate, 11) ); break; - case CPUINFO_STR_REGISTER + AVR8_R12: sprintf(info->s, "R12: %02x", READ_IO_8(cpustate, 12) ); break; - case CPUINFO_STR_REGISTER + AVR8_R13: sprintf(info->s, "R13: %02x", READ_IO_8(cpustate, 13) ); break; - case CPUINFO_STR_REGISTER + AVR8_R14: sprintf(info->s, "R14: %02x", READ_IO_8(cpustate, 14) ); break; - case CPUINFO_STR_REGISTER + AVR8_R15: sprintf(info->s, "R15: %02x", READ_IO_8(cpustate, 15) ); break; - case CPUINFO_STR_REGISTER + AVR8_R16: sprintf(info->s, "R16: %02x", READ_IO_8(cpustate, 16) ); break; - case CPUINFO_STR_REGISTER + AVR8_R17: sprintf(info->s, "R17: %02x", READ_IO_8(cpustate, 17) ); break; - case CPUINFO_STR_REGISTER + AVR8_R18: sprintf(info->s, "R18: %02x", READ_IO_8(cpustate, 18) ); break; - case CPUINFO_STR_REGISTER + AVR8_R19: sprintf(info->s, "R19: %02x", READ_IO_8(cpustate, 19) ); break; - case CPUINFO_STR_REGISTER + AVR8_R20: sprintf(info->s, "R20: %02x", READ_IO_8(cpustate, 20) ); break; - case CPUINFO_STR_REGISTER + AVR8_R21: sprintf(info->s, "R21: %02x", READ_IO_8(cpustate, 21) ); break; - case CPUINFO_STR_REGISTER + AVR8_R22: sprintf(info->s, "R22: %02x", READ_IO_8(cpustate, 22) ); break; - case CPUINFO_STR_REGISTER + AVR8_R23: sprintf(info->s, "R23: %02x", READ_IO_8(cpustate, 23) ); break; - case CPUINFO_STR_REGISTER + AVR8_R24: sprintf(info->s, "R24: %02x", READ_IO_8(cpustate, 24) ); break; - case CPUINFO_STR_REGISTER + AVR8_R25: sprintf(info->s, "R25: %02x", READ_IO_8(cpustate, 25) ); break; - case CPUINFO_STR_REGISTER + AVR8_R26: sprintf(info->s, "R26: %02x", READ_IO_8(cpustate, 26) ); break; - case CPUINFO_STR_REGISTER + AVR8_R27: sprintf(info->s, "R27: %02x", READ_IO_8(cpustate, 27) ); break; - case CPUINFO_STR_REGISTER + AVR8_R28: sprintf(info->s, "R28: %02x", READ_IO_8(cpustate, 28) ); break; - case CPUINFO_STR_REGISTER + AVR8_R29: sprintf(info->s, "R29: %02x", READ_IO_8(cpustate, 29) ); break; - case CPUINFO_STR_REGISTER + AVR8_R30: sprintf(info->s, "R30: %02x", READ_IO_8(cpustate, 30) ); break; - case CPUINFO_STR_REGISTER + AVR8_R31: sprintf(info->s, "R31: %02x", READ_IO_8(cpustate, 31) ); break; + case CPUINFO_STR_REGISTER + AVR8_SREG: sprintf(info->s, "SREG: %c%c%c%c%c%c%c%c", (cpustate->status & 0x80) ? 'I' : '-', (cpustate->status & 0x40) ? 'T' : '-', (cpustate->status & 0x20) ? 'H' : '-', (cpustate->status & 0x10) ? 'S' : '-', (cpustate->status & 0x08) ? 'V' : '-', (cpustate->status & 0x04) ? 'N' : '-', (cpustate->status & 0x02) ? 'Z' : '-', (cpustate->status & 0x01) ? 'C' : '-'); break; + case CPUINFO_STR_REGISTER + AVR8_R0: sprintf(info->s, "R0: %02x", cpustate->r[ 0] ); break; + case CPUINFO_STR_REGISTER + AVR8_R1: sprintf(info->s, "R1: %02x", cpustate->r[ 1] ); break; + case CPUINFO_STR_REGISTER + AVR8_R2: sprintf(info->s, "R2: %02x", cpustate->r[ 2] ); break; + case CPUINFO_STR_REGISTER + AVR8_R3: sprintf(info->s, "R3: %02x", cpustate->r[ 3] ); break; + case CPUINFO_STR_REGISTER + AVR8_R4: sprintf(info->s, "R4: %02x", cpustate->r[ 4] ); break; + case CPUINFO_STR_REGISTER + AVR8_R5: sprintf(info->s, "R5: %02x", cpustate->r[ 5] ); break; + case CPUINFO_STR_REGISTER + AVR8_R6: sprintf(info->s, "R6: %02x", cpustate->r[ 6] ); break; + case CPUINFO_STR_REGISTER + AVR8_R7: sprintf(info->s, "R7: %02x", cpustate->r[ 7] ); break; + case CPUINFO_STR_REGISTER + AVR8_R8: sprintf(info->s, "R8: %02x", cpustate->r[ 8] ); break; + case CPUINFO_STR_REGISTER + AVR8_R9: sprintf(info->s, "R9: %02x", cpustate->r[ 9] ); break; + case CPUINFO_STR_REGISTER + AVR8_R10: sprintf(info->s, "R10: %02x", cpustate->r[10] ); break; + case CPUINFO_STR_REGISTER + AVR8_R11: sprintf(info->s, "R11: %02x", cpustate->r[11] ); break; + case CPUINFO_STR_REGISTER + AVR8_R12: sprintf(info->s, "R12: %02x", cpustate->r[12] ); break; + case CPUINFO_STR_REGISTER + AVR8_R13: sprintf(info->s, "R13: %02x", cpustate->r[13] ); break; + case CPUINFO_STR_REGISTER + AVR8_R14: sprintf(info->s, "R14: %02x", cpustate->r[14] ); break; + case CPUINFO_STR_REGISTER + AVR8_R15: sprintf(info->s, "R15: %02x", cpustate->r[15] ); break; + case CPUINFO_STR_REGISTER + AVR8_R16: sprintf(info->s, "R16: %02x", cpustate->r[16] ); break; + case CPUINFO_STR_REGISTER + AVR8_R17: sprintf(info->s, "R17: %02x", cpustate->r[17] ); break; + case CPUINFO_STR_REGISTER + AVR8_R18: sprintf(info->s, "R18: %02x", cpustate->r[18] ); break; + case CPUINFO_STR_REGISTER + AVR8_R19: sprintf(info->s, "R19: %02x", cpustate->r[19] ); break; + case CPUINFO_STR_REGISTER + AVR8_R20: sprintf(info->s, "R20: %02x", cpustate->r[20] ); break; + case CPUINFO_STR_REGISTER + AVR8_R21: sprintf(info->s, "R21: %02x", cpustate->r[21] ); break; + case CPUINFO_STR_REGISTER + AVR8_R22: sprintf(info->s, "R22: %02x", cpustate->r[22] ); break; + case CPUINFO_STR_REGISTER + AVR8_R23: sprintf(info->s, "R23: %02x", cpustate->r[23] ); break; + case CPUINFO_STR_REGISTER + AVR8_R24: sprintf(info->s, "R24: %02x", cpustate->r[24] ); break; + case CPUINFO_STR_REGISTER + AVR8_R25: sprintf(info->s, "R25: %02x", cpustate->r[25] ); break; + case CPUINFO_STR_REGISTER + AVR8_R26: sprintf(info->s, "R26: %02x", cpustate->r[26] ); break; + case CPUINFO_STR_REGISTER + AVR8_R27: sprintf(info->s, "R27: %02x", cpustate->r[27] ); break; + case CPUINFO_STR_REGISTER + AVR8_R28: sprintf(info->s, "R28: %02x", cpustate->r[28] ); break; + case CPUINFO_STR_REGISTER + AVR8_R29: sprintf(info->s, "R29: %02x", cpustate->r[29] ); break; + case CPUINFO_STR_REGISTER + AVR8_R30: sprintf(info->s, "R30: %02x", cpustate->r[30] ); break; + case CPUINFO_STR_REGISTER + AVR8_R31: sprintf(info->s, "R31: %02x", cpustate->r[31] ); break; case CPUINFO_STR_REGISTER + AVR8_X: sprintf(info->s, "X: %04x", XREG ); break; case CPUINFO_STR_REGISTER + AVR8_Y: sprintf(info->s, "Y: %04x", YREG ); break; case CPUINFO_STR_REGISTER + AVR8_Z: sprintf(info->s, "Z: %04x", ZREG ); break; diff --git a/src/emu/cpu/avr8/avr8.h b/src/emu/cpu/avr8/avr8.h index ff3816333c2..d634223d816 100644 --- a/src/emu/cpu/avr8/avr8.h +++ b/src/emu/cpu/avr8/avr8.h @@ -11,6 +11,39 @@ #ifndef __AVR8_H__ #define __AVR8_H__ +// Used by core CPU interface +struct avr8_state +{ + UINT32 pc; + + legacy_cpu_device *device; + address_space *program; + address_space *io; + + int icount; + UINT32 addr_mask; + + UINT8 r[256]; + UINT8 status; + + UINT8 timer0_top; + INT32 timer0_increment; + UINT16 timer0_prescale; + UINT16 timer0_prescale_count; + + UINT16 timer1_top; + INT32 timer1_increment; + UINT16 timer1_prescale; + UINT16 timer1_prescale_count; + + UINT8 timer2_top; + INT32 timer2_increment; + UINT16 timer2_prescale; + UINT16 timer2_prescale_count; + + bool interrupt_pending; +}; + enum { AVR8_SREG = 1, @@ -83,9 +116,192 @@ enum AVR8_INT_SPM_RDY, }; +// Used by I/O register handling +enum +{ + AVR8_REGIDX_R0 = 0, + AVR8_REGIDX_R1, + AVR8_REGIDX_R2, + AVR8_REGIDX_R3, + AVR8_REGIDX_R4, + AVR8_REGIDX_R5, + AVR8_REGIDX_R6, + AVR8_REGIDX_R7, + AVR8_REGIDX_R8, + AVR8_REGIDX_R9, + AVR8_REGIDX_R10, + AVR8_REGIDX_R11, + AVR8_REGIDX_R12, + AVR8_REGIDX_R13, + AVR8_REGIDX_R14, + AVR8_REGIDX_R15, + AVR8_REGIDX_R16, + AVR8_REGIDX_R17, + AVR8_REGIDX_R18, + AVR8_REGIDX_R19, + AVR8_REGIDX_R20, + AVR8_REGIDX_R21, + AVR8_REGIDX_R22, + AVR8_REGIDX_R23, + AVR8_REGIDX_R24, + AVR8_REGIDX_R25, + AVR8_REGIDX_R26, + AVR8_REGIDX_R27, + AVR8_REGIDX_R28, + AVR8_REGIDX_R29, + AVR8_REGIDX_R30, + AVR8_REGIDX_R31, + + AVR8_REGIDX_PINB = 0x23, + AVR8_REGIDX_DDRB, + AVR8_REGIDX_PORTB, + AVR8_REGIDX_PINC, + AVR8_REGIDX_DDRC, + AVR8_REGIDX_PORTC, + AVR8_REGIDX_PIND, + AVR8_REGIDX_DDRD, + AVR8_REGIDX_PORTD, + + AVR8_REGIDX_TIFR0 = 0x35, + AVR8_REGIDX_TIFR1, + AVR8_REGIDX_TIFR2, + + AVR8_REGIDX_PCIFR = 0x3b, + AVR8_REGIDX_EIFR, + AVR8_REGIDX_EIMSK, + AVR8_REGIDX_GPIOR0, + AVR8_REGIDX_EECR, + AVR8_REGIDX_EEDR, + AVR8_REGIDX_EEARL, + AVR8_REGIDX_EEARH, + AVR8_REGIDX_GTCCR, + AVR8_REGIDX_TCCR0A, + AVR8_REGIDX_TCCR0B, + AVR8_REGIDX_TCNT0, + AVR8_REGIDX_OCR0A, + AVR8_REGIDX_OCR0B, + + AVR8_REGIDX_GPIOR1 = 0x4a, + AVR8_REGIDX_GPIOR2, + AVR8_REGIDX_SPCR, + AVR8_REGIDX_SPSR, + AVR8_REGIDX_SPDR, + + AVR8_REGIDX_ACSR = 0x50, + + AVR8_REGIDX_SMCR = 0x53, + AVR8_REGIDX_MCUSR, + AVR8_REGIDX_MCUCR, + + AVR8_REGIDX_SPMCSR = 0x57, + + AVR8_REGIDX_SPL = 0x5d, + AVR8_REGIDX_SPH, + AVR8_REGIDX_SREG, + AVR8_REGIDX_WDTCSR, + AVR8_REGIDX_CLKPR, + + AVR8_REGIDX_PRR = 0x64, + + AVR8_REGIDX_OSCCAL = 0x66, + + AVR8_REGIDX_PCICR = 0x68, + AVR8_REGIDX_EICRA, + + AVR8_REGIDX_PCMSK0 = 0x6B, + AVR8_REGIDX_PCMSK1, + AVR8_REGIDX_PCMSK2, + AVR8_REGIDX_TIMSK0, + AVR8_REGIDX_TIMSK1, + AVR8_REGIDX_TIMSK2, + + AVR8_REGIDX_ADCL = 0x78, + AVR8_REGIDX_ADCH, + AVR8_REGIDX_ADCSRA, + AVR8_REGIDX_ADCSRB, + AVR8_REGIDX_ADMUX, + + AVR8_REGIDX_DIDR0 = 0x7e, + AVR8_REGIDX_DIDR1, + AVR8_REGIDX_TCCR1A, + AVR8_REGIDX_TCCR1B, + AVR8_REGIDX_TCCR1C, + + AVR8_REGIDX_TCNT1L = 0x84, + AVR8_REGIDX_TCNT1H, + AVR8_REGIDX_ICR1L, + AVR8_REGIDX_ICR1H, + AVR8_REGIDX_OCR1AL, + AVR8_REGIDX_OCR1AH, + AVR8_REGIDX_OCR1BL, + AVR8_REGIDX_OCR1BH, + + AVR8_REGIDX_TCCR2A = 0xb0, + AVR8_REGIDX_TCCR2B, + AVR8_REGIDX_TCNT2, + AVR8_REGIDX_OCR2A, + AVR8_REGIDX_OCR2B, + + AVR8_REGIDX_ASSR = 0xb6, + + AVR8_REGIDX_TWBR = 0xb8, + AVR8_REGIDX_TWSR, + AVR8_REGIDX_TWAR, + AVR8_REGIDX_TWDR, + AVR8_REGIDX_TWCR, + AVR8_REGIDX_TWAMR, + + AVR8_REGIDX_UCSR0A = 0xc0, + AVR8_REGIDX_UCSR0B, + AVR8_REGIDX_UCSR0C, + + AVR8_REGIDX_UBRR0L = 0xc4, + AVR8_REGIDX_UBRR0H, + AVR8_REGIDX_UDR0 +}; + +enum +{ + AVR8_REG_A = 0, + AVR8_REG_B, + AVR8_REG_C, + AVR8_REG_D, +}; + +enum +{ + AVR8_INTIDX_SPI, + AVR8_INTIDX_ICF1, + AVR8_INTIDX_OCF1B, + AVR8_INTIDX_OCF1A, + AVR8_INTIDX_TOV1, + AVR8_INTIDX_OCF2B, + AVR8_INTIDX_OCF2A, + AVR8_INTIDX_TOV2, + + AVR8_INTIDX_COUNT, +}; + +#define AVR8_EECR_EERE 0x01 +#define AVR8_EEARH_MASK 0x01 + +#define AVR8_SPSR_SPIF_MASK 0x80 +#define AVR8_SPSR_SPIF_SHIFT 7 +#define AVR8_SPSR_SPR2X_MASK 0x01 + +#define AVR8_SPCR_SPIE_MASK 0x80 +#define AVR8_SPCR_SPE_MASK 0x40 +#define AVR8_SPCR_DORD_MASK 0x20 +#define AVR8_SPCR_MSTR_MASK 0x10 +#define AVR8_SPCR_CPOL_MASK 0x08 +#define AVR8_SPCR_CPHA_MASK 0x04 +#define AVR8_SPCR_SPR_MASK 0x03 + DECLARE_LEGACY_CPU_DEVICE(ATMEGA88, atmega88); DECLARE_LEGACY_CPU_DEVICE(ATMEGA644, atmega644); +void avr8_update_interrupt(device_t *device, int source); + CPU_DISASSEMBLE( avr8 ); #endif /* __AVR8_H__ */ diff --git a/src/mess/drivers/craft.c b/src/mess/drivers/craft.c index 9a4161c780b..2283210a479 100644 --- a/src/mess/drivers/craft.c +++ b/src/mess/drivers/craft.c @@ -6,7 +6,6 @@ #include "emu.h" #include "cpu/avr8/avr8.h" -#include "machine/avr8.h" #include "sound/dac.h" #define VERBOSE_LEVEL (99) @@ -33,12 +32,30 @@ INLINE void verboselog(running_machine &machine, int n_level, const char *s_fmt, #define MASTER_CLOCK 20000000 /****************************************************\ -* I/O devices * +* I/O defines * \****************************************************/ +#define AVR8_DDRD (state->m_regs[AVR8_REGIDX_DDRD]) +#define AVR8_DDRC (state->m_regs[AVR8_REGIDX_DDRC]) +#define AVR8_PORTB (state->m_regs[AVR8_REGIDX_PORTB]) +#define AVR8_DDRB (state->m_regs[AVR8_REGIDX_DDRB]) + +#define AVR8_SPSR (state->m_regs[AVR8_REGIDX_SPSR]) +#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK) + +#define AVR8_SPCR (state->m_regs[AVR8_REGIDX_SPCR]) +#define AVR8_SPCR_SPIE ((AVR8_SPCR & AVR8_SPCR_SPIE_MASK) >> 7) +#define AVR8_SPCR_SPE ((AVR8_SPCR & AVR8_SPCR_SPE_MASK) >> 6) +#define AVR8_SPCR_DORD ((AVR8_SPCR & AVR8_SPCR_DORD_MASK) >> 5) +#define AVR8_SPCR_MSTR ((AVR8_SPCR & AVR8_SPCR_MSTR_MASK) >> 4) +#define AVR8_SPCR_CPOL ((AVR8_SPCR & AVR8_SPCR_CPOL_MASK) >> 3) +#define AVR8_SPCR_CPHA ((AVR8_SPCR & AVR8_SPCR_CPHA_MASK) >> 2) +#define AVR8_SPCR_SPR (AVR8_SPCR & AVR8_SPCR_SPR_MASK) - +/****************************************************\ +* I/O devices * +\****************************************************/ class craft_state : public driver_device { @@ -47,11 +64,6 @@ public: : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu") { - m_timer0_increment = 1; - - m_timer1_increment = 1; - - m_timer2_increment = 1; } virtual void machine_start(); @@ -59,20 +71,10 @@ public: dac_device* dac; UINT8 m_regs[0x100]; + UINT8* m_eeprom; required_device m_maincpu; - emu_timer* m_timer0_timer; - UINT8 m_timer0_top; - INT32 m_timer0_increment; - - emu_timer* m_timer1_timer; - UINT16 m_timer1_top; - INT32 m_timer1_increment; - - emu_timer* m_timer2_timer; - UINT8 m_timer2_top; - INT32 m_timer2_increment; DECLARE_READ8_MEMBER(avr8_read); DECLARE_WRITE8_MEMBER(avr8_write); DECLARE_DRIVER_INIT(craft); @@ -85,113 +87,13 @@ public: void craft_state::machine_start() { - m_timer0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(craft_state::avr8_timer0_tick),this)); - m_timer1_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(craft_state::avr8_timer1_tick),this)); - m_timer2_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(craft_state::avr8_timer2_tick),this)); -} -enum -{ - AVR8_REG_A = 0, - AVR8_REG_B, - AVR8_REG_C, - AVR8_REG_D, -}; - -static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' }; - -TIMER_CALLBACK_MEMBER(craft_state::avr8_timer0_tick) -{ - // TODO -} - -TIMER_CALLBACK_MEMBER(craft_state::avr8_timer1_tick) -{ - /* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */ - - UINT16 count = (m_regs[Avr8::REGIDX_TCNT1H] << 8) | m_regs[Avr8::REGIDX_TCNT1L]; - INT32 wgm1 = ((m_regs[Avr8::REGIDX_TCCR1B] & AVR8_TCCR1B_WGM1_32_MASK) >> 1) | - (m_regs[Avr8::REGIDX_TCCR1A] & AVR8_TCCR1A_WGM1_10_MASK); - - // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer - //UINT8 compare_mode[2] = { (m_regs[Avr8::REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT, - //(m_regs[Avr8::REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT }; - UINT16 ocr1[2] = { (m_regs[Avr8::REGIDX_OCR1AH] << 8) | m_regs[Avr8::REGIDX_OCR1AL], - (m_regs[Avr8::REGIDX_OCR1BH] << 8) | m_regs[Avr8::REGIDX_OCR1BL] }; - INT32 int_lines[2] = { AVR8_INT_T1COMPA, AVR8_INT_T1COMPB }; - INT32 int_masks[2] = { AVR8_TIMSK1_OCIE1A_MASK, AVR8_TIMSK1_OCIE1B_MASK }; - INT32 increment = m_timer1_increment; - - for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) - { - switch(wgm1) - { - case Avr8::WGM1_FAST_PWM_OCR: - if(count == ocr1[reg]) - { - if (reg == 0) - { - m_regs[Avr8::REGIDX_TIFR1] |= (1 << AVR8_TIFR1_TOV1_SHIFT); - count = 0; - increment = 0; - } - if (m_regs[Avr8::REGIDX_TIMSK1] & int_masks[reg]) - { - m_maincpu->set_input_line(int_lines[reg], 1); - } - } - else if(count == 0) - { - if (reg == 0) - { - m_regs[Avr8::REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; - } - if (m_regs[Avr8::REGIDX_TIMSK1] & int_masks[reg]) - { - m_maincpu->set_input_line(int_lines[reg], 0); - } - } - break; - - default: - // TODO - break; - } - /* - switch(compare_mode[reg]) - { - case 0: - //verboselog(machine(), 0, "avr8_update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n"); - break; - - case 1: - case 2: - // TODO - break; - - case 3: - break; - } - */ - } - - count += increment; - m_regs[Avr8::REGIDX_TCNT1H] = (count >> 8) & 0xff; - m_regs[Avr8::REGIDX_TCNT1L] = count & 0xff; } READ8_MEMBER(craft_state::avr8_read) { - - if(offset <= Avr8::REGIDX_R31) - { - return m_regs[offset]; - } - switch( offset ) { - case Avr8::REGIDX_SPL: - case Avr8::REGIDX_SPH: - case Avr8::REGIDX_SREG: + case AVR8_REGIDX_EEDR: return m_regs[offset]; default: @@ -252,51 +154,13 @@ static void avr8_change_port(running_machine &machine, int reg, UINT8 data) { // TODO //verboselog(machine, 0, "avr8_change_port: PORT%c lines %02x changed\n", avr8_reg_name[reg], changed); - if (reg == AVR8_REG_D) { - state->dac->write_unsigned8(data & 0x7f); - } } -} -namespace Avr8 -{ + if (reg == AVR8_REG_D) { + UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2); -enum -{ - INTIDX_SPI, - INTIDX_ICF1, - INTIDX_OCF1B, - INTIDX_OCF1A, - INTIDX_TOV1, - - INTIDX_COUNT, -}; - -class CInterruptCondition -{ - public: - UINT8 m_intindex; - UINT8 m_regindex; - UINT8 m_regmask; - UINT8 m_regshift; - UINT8* mp_reg; -}; - -static const CInterruptCondition s_int_conditions[INTIDX_COUNT] = -{ - { INTIDX_SPI, REGIDX_SPSR, AVR8_SPSR_SPIF_MASK, AVR8_SPSR_SPIF_SHIFT, NULL }, - { INTIDX_ICF1, REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK, AVR8_TIFR1_ICF1_SHIFT, NULL }, - { INTIDX_OCF1B, REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK, AVR8_TIFR1_OCF1B_SHIFT, NULL }, - { INTIDX_OCF1A, REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK, AVR8_TIFR1_OCF1A_SHIFT, NULL }, - { INTIDX_TOV1, REGIDX_TIFR1, AVR8_TIFR1_TOV1_MASK, AVR8_TIFR1_TOV1_SHIFT, NULL } -}; - -} - -static void avr8_interrupt_update(running_machine &machine, int source) -{ - // TODO - verboselog(machine, 0, "avr8_interrupt_update: TODO; source interrupt is %d\n", source); + state->dac->write_unsigned8(audio_sample << 2); + } } /****************/ @@ -319,21 +183,21 @@ static void avr8_spi_update_masterslave_select(running_machine &machine) { // TODO //craft_state *state = machine.driver_data(); - verboselog(machine, 0, "avr8_spi_update_masterslave_select: TODO; AVR is %s\n", AVR8_SPCR_MSTR ? "Master" : "Slave"); + //verboselog(machine, 0, "avr8_spi_update_masterslave_select: TODO; AVR is %s\n", AVR8_SPCR_MSTR ? "Master" : "Slave"); } static void avr8_spi_update_clock_polarity(running_machine &machine) { // TODO //craft_state *state = machine.driver_data(); - verboselog(machine, 0, "avr8_spi_update_clock_polarity: TODO; SCK is Active-%s\n", AVR8_SPCR_CPOL ? "Low" : "High"); + //verboselog(machine, 0, "avr8_spi_update_clock_polarity: TODO; SCK is Active-%s\n", AVR8_SPCR_CPOL ? "Low" : "High"); } static void avr8_spi_update_clock_phase(running_machine &machine) { // TODO //craft_state *state = machine.driver_data(); - verboselog(machine, 0, "avr8_spi_update_clock_phase: TODO; Sampling edge is %s\n", AVR8_SPCR_CPHA ? "Trailing" : "Leading"); + //verboselog(machine, 0, "avr8_spi_update_clock_phase: TODO; Sampling edge is %s\n", AVR8_SPCR_CPHA ? "Trailing" : "Leading"); } static const UINT8 avr8_spi_clock_divisor[8] = { 4, 16, 64, 128, 2, 8, 32, 64 }; @@ -342,7 +206,7 @@ static void avr8_spi_update_clock_rate(running_machine &machine) { // TODO //craft_state *state = machine.driver_data(); - verboselog(machine, 0, "avr8_spi_update_clock_rate: TODO; New clock rate should be f/%d\n", avr8_spi_clock_divisor[AVR8_SPCR_SPR] / (AVR8_SPSR_SPR2X ? 2 : 1)); + //verboselog(machine, 0, "avr8_spi_update_clock_rate: TODO; New clock rate should be f/%d\n", avr8_spi_clock_divisor[AVR8_SPCR_SPR] / (AVR8_SPSR_SPR2X ? 2 : 1)); } static void avr8_change_spcr(running_machine &machine, UINT8 data) @@ -360,7 +224,7 @@ static void avr8_change_spcr(running_machine &machine, UINT8 data) if(changed & AVR8_SPCR_SPIE_MASK) { // Check for SPI interrupt condition - avr8_interrupt_update(machine, Avr8::INTIDX_SPI); + avr8_update_interrupt(state->m_maincpu, AVR8_INTIDX_SPI); } if(low_to_high & AVR8_SPCR_SPE_MASK) @@ -412,510 +276,57 @@ static void avr8_change_spsr(running_machine &machine, UINT8 data) } } -/********************/ -/* Timer 1 Handling */ -/********************/ - -static void avr8_change_timsk1(running_machine &machine, UINT8 data) -{ - craft_state *state = machine.driver_data(); - - UINT8 oldtimsk = AVR8_TIMSK1; - UINT8 newtimsk = data; - UINT8 changed = newtimsk ^ oldtimsk; - - AVR8_TIMSK1 = newtimsk; - - if(changed & AVR8_TIMSK1_ICIE1_MASK) - { - // Check for Input Capture Interrupt interrupt condition - avr8_interrupt_update(machine, Avr8::INTIDX_ICF1); - } - - if(changed & AVR8_TIMSK1_OCIE1B_MASK) - { - // Check for Output Compare B Interrupt interrupt condition - avr8_interrupt_update(machine, Avr8::INTIDX_OCF1B); - } - - if(changed & AVR8_TIMSK1_OCIE1A_MASK) - { - // Check for Output Compare A Interrupt interrupt condition - avr8_interrupt_update(machine, Avr8::INTIDX_OCF1A); - } - - if(changed & AVR8_TIMSK1_TOIE1_MASK) - { - // Check for Output Compare A Interrupt interrupt condition - avr8_interrupt_update(machine, Avr8::INTIDX_TOV1); - } -} - -static void avr8_update_timer1_waveform_gen_mode(running_machine &machine) -{ - // TODO - craft_state *state = machine.driver_data(); - state->m_timer1_top = 0; - verboselog(machine, 0, "avr8_update_timer1_waveform_gen_mode: TODO; WGM1 is %d\n", AVR8_WGM1 ); - switch(AVR8_WGM1) - { - case Avr8::WGM1_NORMAL: - state->m_timer1_top = 0xffff; - break; - - case Avr8::WGM1_PWM_8_PC: - case Avr8::WGM1_FAST_PWM_8: - state->m_timer1_top = 0x00ff; - break; - - case Avr8::WGM1_PWM_9_PC: - case Avr8::WGM1_FAST_PWM_9: - state->m_timer1_top = 0x01ff; - break; - - case Avr8::WGM1_PWM_10_PC: - case Avr8::WGM1_FAST_PWM_10: - state->m_timer1_top = 0x03ff; - break; - - case Avr8::WGM1_PWM_PFC_ICR: - case Avr8::WGM1_PWM_PC_ICR: - case Avr8::WGM1_CTC_ICR: - case Avr8::WGM1_FAST_PWM_ICR: - state->m_timer1_top = AVR8_ICR1; - break; - - case Avr8::WGM1_PWM_PFC_OCR: - case Avr8::WGM1_PWM_PC_OCR: - case Avr8::WGM1_CTC_OCR: - case Avr8::WGM1_FAST_PWM_OCR: - state->m_timer1_top = AVR8_OCR1A; - break; - - default: - verboselog(machine, 0, "avr8_update_timer1_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM1); - break; - } -} - -static void avr8_changed_tccr1a(running_machine &machine, UINT8 data) -{ - craft_state *state = machine.driver_data(); - - UINT8 oldtccr = AVR8_TCCR1A; - UINT8 newtccr = data; - UINT8 changed = newtccr ^ oldtccr; - - state->m_regs[Avr8::REGIDX_TCCR1A] = newtccr; - - if(changed & AVR8_TCCR1A_WGM1_10_MASK) - { - // TODO - avr8_update_timer1_waveform_gen_mode(machine); - } -} - -static void avr8_update_timer1_input_noise_canceler(running_machine &machine) -{ -} - -static void avr8_update_timer1_input_edge_select(running_machine &machine) -{ - // TODO - //craft_state *state = machine.driver_data(); - verboselog(machine, 0, "avr8_update_timer1_input_edge_select: TODO; Clocking edge is %s\n", "test"); -} - -TIMER_CALLBACK_MEMBER(craft_state::avr8_timer2_tick) -{ - /* TODO: Handle comparison, setting OC2x pins, detection of BOTTOM and TOP - - UINT16 count = AVR8_TCNT2; - count += m_timer1_increment; - for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) - { - UINT8 mode = (reg == AVR8_REG_A) ? AVR8_TCCR2A_COM2A : AVR8_TCCR2A_COM2B; - - if(!mode) - { - // Normal port operation, OC2n disconnected - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]); - return; - } - - switch(AVR8_WGM2) - { - case Avr8::WGM2_NORMAL: - case Avr8::WGM2_CTC_CMP: - switch(mode) - { - case 1: // Toggle OC2n on Compare Match - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on Compare Match\n", avr8_reg_name[reg]); - break; - case 2: // Clear OC2n on Compare Match - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on Compare Match\n", avr8_reg_name[reg]); - break; - case 3: // Set OC2n on Compare Match - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on Compare Match\n", avr8_reg_name[reg]); - break; - } - break; - - case Avr8::WGM2_PWM_PC: - switch(mode) - { - case 1: // Normal port operation, OC2n disconnected - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]); - break; - case 2: // Clear OC2n on match when up-counting, set when down-counting - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]); - break; - case 3: // Set OC2n on match when up-counting, clear when down-counting - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match when up-counting, clear when down-counting\n", avr8_reg_name[reg]); - break; - } - break; - - case Avr8::WGM2_PWM_PC_CMP: - switch(mode) - { - case 1: // Toggle OC2n on compare match - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on compare match\n", avr8_reg_name[reg]); - break; - case 2: // Clear OC2n on match when up-counting, set when down-counting - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]); - break; - case 3: // Set OC2n on match when up-counting, clear when down-counting - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match when up-counting, clear when down-counting\n", avr8_reg_name[reg]); - break; - } - break; - - - case Avr8::WGM2_FAST_PWM: - switch(mode) - { - case 1: // Normal port operation, OC2n disconnected - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]); - break; - case 2: // Clear OC2n on match, set at BOTTOM - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match, set at BOTTOM\n", avr8_reg_name[reg]); - break; - case 3: // Set OC2n on match, clear at BOTTOM - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match, clear at BOTTOM\n", avr8_reg_name[reg]); - break; - } - break; - - case Avr8::WGM2_FAST_PWM_CMP: - switch(mode) - { - case 1: // Toggle OC2n on compare match - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on compare match\n", avr8_reg_name[reg]); - break; - case 2: // Clear OC2n on match, set at BOTTOM - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match, set at BOTTOM\n", avr8_reg_name[reg]); - break; - case 3: // Set OC2n on match, clear at BOTTOM - //verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match, clear at BOTTOM\n", avr8_reg_name[reg]); - break; - } - break; - - default: - break; - } - } - */ -} - -static void avr8_update_timer1_clock_source(running_machine &machine) -{ - craft_state *state = machine.driver_data(); - attotime period; - switch(AVR8_TIMER2_CLOCK_SELECT) - { - case 0: // Counter stopped - period = attotime::never; - break; - case 1: // Clk/1; no prescaling - period = attotime::from_hz(MASTER_CLOCK); - break; - case 2: // Clk/8 - period = attotime::from_hz(MASTER_CLOCK/8); - break; - case 3: // Clk/32 - period = attotime::from_hz(MASTER_CLOCK/32); - break; - case 4: // Clk/64 - period = attotime::from_hz(MASTER_CLOCK/64); - break; - case 5: // Clk/128 - period = attotime::from_hz(MASTER_CLOCK/128); - break; - case 6: // T1 trigger, falling edge - case 7: // T1 trigger, rising edge - period = attotime::never; - verboselog(machine, 0, "avr8_update_timer1_clock_source: T1 Trigger mode not implemented yet\n"); - break; - } - state->m_timer1_timer->adjust(period, 0, period); -} - -static void avr8_changed_tccr1b(running_machine &machine, UINT8 data) -{ - craft_state *state = machine.driver_data(); - - UINT8 oldtccr = AVR8_TCCR1B; - UINT8 newtccr = data; - UINT8 changed = newtccr ^ oldtccr; - - state->m_regs[Avr8::REGIDX_TCCR1B] = newtccr; - - if(changed & AVR8_TCCR1B_ICNC1_MASK) - { - // TODO - avr8_update_timer1_input_noise_canceler(machine); - } - - if(changed & AVR8_TCCR1B_ICES1_MASK) - { - // TODO - avr8_update_timer1_input_edge_select(machine); - } - - if(changed & AVR8_TCCR1B_WGM1_32_MASK) - { - // TODO - avr8_update_timer1_waveform_gen_mode(machine); - } - - if(changed & AVR8_TCCR1B_CS_MASK) - { - avr8_update_timer1_clock_source(machine); - } -} - -static void avr8_update_timer2_waveform_gen_mode(running_machine &machine) -{ - craft_state *state = machine.driver_data(); - state->m_timer2_top = 0; - switch(AVR8_WGM2) - { - case Avr8::WGM2_NORMAL: - case Avr8::WGM2_PWM_PC: - case Avr8::WGM2_FAST_PWM: - state->m_timer2_top = 0x00ff; - break; - - case Avr8::WGM2_CTC_CMP: - case Avr8::WGM2_PWM_PC_CMP: - case Avr8::WGM2_FAST_PWM_CMP: - state->m_timer2_top = AVR8_OCR2A; - break; - - default: - verboselog(machine, 0, "avr8_update_timer2_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM2); - break; - } -} - -static void avr8_changed_tccr2a(running_machine &machine, UINT8 data) -{ - craft_state *state = machine.driver_data(); - - UINT8 oldtccr = AVR8_TCCR2A; - UINT8 newtccr = data; - UINT8 changed = newtccr ^ oldtccr; - - if(changed & AVR8_TCCR2A_WGM2_10_MASK) - { - // TODO - avr8_update_timer2_waveform_gen_mode(machine); - } -} - -static void avr8_update_timer2_clock_source(running_machine &machine) -{ - craft_state *state = machine.driver_data(); - attotime period; - switch(AVR8_TIMER2_CLOCK_SELECT) - { - case 0: // Counter stopped - period = attotime::never; - break; - case 1: // Clk/1; no prescaling - period = attotime::from_hz(MASTER_CLOCK); - break; - case 2: // Clk/8 - period = attotime::from_hz(MASTER_CLOCK/8); - break; - case 3: // Clk/32 - period = attotime::from_hz(MASTER_CLOCK/32); - break; - case 4: // Clk/64 - period = attotime::from_hz(MASTER_CLOCK/64); - break; - case 5: // Clk/128 - period = attotime::from_hz(MASTER_CLOCK/128); - break; - case 6: // Clk/256 - period = attotime::from_hz(MASTER_CLOCK/256); - break; - case 7: // Clk/1024 - period = attotime::from_hz(MASTER_CLOCK/1024); - break; - } - state->m_timer2_timer->adjust(period, 0, period); -} - -static void avr8_timer2_force_output_compare(running_machine &machine, int reg) -{ - // TODO - verboselog(machine, 0, "avr8_force_output_compare: TODO; should be forcing OC2%c\n", avr8_reg_name[reg]); -} - -static void avr8_changed_tccr2b(running_machine &machine, UINT8 data) -{ - craft_state *state = machine.driver_data(); - - UINT8 oldtccr = AVR8_TCCR2B; - UINT8 newtccr = data; - UINT8 changed = newtccr ^ oldtccr; - - if(changed & AVR8_TCCR2B_FOC2A_MASK) - { - // TODO - avr8_timer2_force_output_compare(machine, AVR8_REG_A); - } - - if(changed & AVR8_TCCR2B_FOC2B_MASK) - { - // TODO - avr8_timer2_force_output_compare(machine, AVR8_REG_B); - } - - if(changed & AVR8_TCCR2B_WGM2_2_MASK) - { - // TODO - avr8_update_timer2_waveform_gen_mode(machine); - } - - if(changed & AVR8_TCCR2B_CS_MASK) - { - avr8_update_timer2_clock_source(machine); - } -} - -static void avr8_update_ocr1(running_machine &machine, UINT16 newval, UINT8 reg) -{ - craft_state *state = machine.driver_data(); - UINT8 *p_reg_h = (reg == AVR8_REG_A) ? &AVR8_OCR1AH : &AVR8_OCR1BH; - UINT8 *p_reg_l = (reg == AVR8_REG_A) ? &AVR8_OCR1AL : &AVR8_OCR1BL; - *p_reg_h = (UINT8)(newval >> 8); - *p_reg_l = (UINT8)newval; - - // TODO - verboselog(machine, 0, "avr8_update_ocr1: TODO: new OCR1%c = %04x\n", avr8_reg_name[reg], newval); -} - WRITE8_MEMBER(craft_state::avr8_write) { - craft_state *state = machine().driver_data(); - if(offset <= Avr8::REGIDX_R31) - { - m_regs[offset] = data; - return; - } - switch( offset ) { - case Avr8::REGIDX_OCR1BH: - verboselog(machine(), 0, "AVR8: OCR1BH = %02x\n", data ); - avr8_update_ocr1(machine(), (AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B); - break; - - case Avr8::REGIDX_OCR1BL: - verboselog(machine(), 0, "AVR8: OCR1BL = %02x\n", data ); - avr8_update_ocr1(machine(), (AVR8_OCR1B & 0xff00) | data, AVR8_REG_B); - break; - - case Avr8::REGIDX_OCR1AH: - verboselog(machine(), 0, "AVR8: OCR1AH = %02x\n", data ); - avr8_update_ocr1(machine(), (AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A); - break; - - case Avr8::REGIDX_OCR1AL: - verboselog(machine(), 0, "AVR8: OCR1AL = %02x\n", data ); - avr8_update_ocr1(machine(), (AVR8_OCR1A & 0xff00) | data, AVR8_REG_A); - break; - - case Avr8::REGIDX_TCCR1B: - verboselog(machine(), 0, "AVR8: TCCR1B = %02x\n", data ); - avr8_changed_tccr1b(machine(), data); - break; - - case Avr8::REGIDX_TCCR1A: - verboselog(machine(), 0, "AVR8: TCCR1A = %02x\n", data ); - avr8_changed_tccr1a(machine(), data); - break; - - case Avr8::REGIDX_TIMSK1: - verboselog(machine(), 0, "AVR8: TIMSK1 = %02x\n", data ); - avr8_change_timsk1(machine(), data); - break; - - case Avr8::REGIDX_TCCR2B: - verboselog(machine(), 0, "AVR8: TCCR2B = %02x\n", data ); - avr8_changed_tccr2b(machine(), data); - break; - - case Avr8::REGIDX_TCCR2A: - verboselog(machine(), 0, "AVR8: TCCR2A = %02x\n", data ); - avr8_changed_tccr2a(machine(), data); - break; - - case Avr8::REGIDX_TCNT2: - //verboselog(machine(), 0, "AVR8: TCNT2 = %02x\n", data ); - AVR8_TCNT2 = data; - break; - - case Avr8::REGIDX_GTCCR: - //verboselog(machine(), 0, "AVR8: GTCCR = %02x\n", data ); - // TODO - break; - - case Avr8::REGIDX_SPL: - case Avr8::REGIDX_SPH: - case Avr8::REGIDX_SREG: - m_regs[offset] = data; - break; - - case Avr8::REGIDX_SPSR: + case AVR8_REGIDX_SPSR: avr8_change_spsr(machine(), data); break; - case Avr8::REGIDX_SPCR: + case AVR8_REGIDX_SPCR: avr8_change_spcr(machine(), data); break; - case Avr8::REGIDX_PORTD: + case AVR8_REGIDX_SPDR: + // TODO + break; + + case AVR8_REGIDX_EECR: + if (data & AVR8_EECR_EERE) + { + UINT16 addr = (m_regs[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8; + addr |= m_regs[AVR8_REGIDX_EEARL]; + m_regs[AVR8_REGIDX_EEDR] = m_eeprom[addr]; + } + break; + + case AVR8_REGIDX_EEARL: + case AVR8_REGIDX_EEARH: + m_regs[offset] = data; + break; + + case AVR8_REGIDX_PORTD: avr8_change_port(machine(), AVR8_REG_D, data); break; - case Avr8::REGIDX_DDRD: + case AVR8_REGIDX_DDRD: avr8_change_ddr(machine(), AVR8_REG_D, data); break; - case Avr8::REGIDX_DDRC: + case AVR8_REGIDX_PORTC: + avr8_change_port(machine(), AVR8_REG_C, data); + break; + + case AVR8_REGIDX_DDRC: avr8_change_ddr(machine(), AVR8_REG_C, data); break; - case Avr8::REGIDX_PORTB: + case AVR8_REGIDX_PORTB: avr8_change_port(machine(), AVR8_REG_B, data); break; - case Avr8::REGIDX_DDRB: + case AVR8_REGIDX_DDRB: avr8_change_ddr(machine(), AVR8_REG_B, data); break; @@ -967,19 +378,11 @@ void craft_state::machine_reset() { craft_state *state = machine().driver_data(); - AVR8_TIMSK1 = 0; - AVR8_OCR1AH = 0; - AVR8_OCR1AL = 0; - AVR8_OCR1BH = 0; - AVR8_OCR1BL = 0; - AVR8_ICR1H = 0; - AVR8_ICR1L = 0; - AVR8_TCNT1H = 0; - AVR8_TCNT1L = 0; - state->dac = machine().device("dac"); state->dac->write_unsigned8(0x00); + + state->m_eeprom = memregion("eeprom")->base(); } static MACHINE_CONFIG_START( craft, craft_state ) diff --git a/src/mess/drivers/uzebox.c b/src/mess/drivers/uzebox.c index 9ebe836c327..5fa55caa3af 100644 --- a/src/mess/drivers/uzebox.c +++ b/src/mess/drivers/uzebox.c @@ -1,7 +1,6 @@ #include "emu.h" #include "cpu/avr8/avr8.h" -#include "machine/avr8.h" #include "sound/dac.h" #include "imagedev/cartslot.h" diff --git a/src/mess/machine/avr8.h b/src/mess/machine/avr8.h deleted file mode 100644 index f67d9b74512..00000000000 --- a/src/mess/machine/avr8.h +++ /dev/null @@ -1,299 +0,0 @@ -#ifndef __EMU_MACHINE_AVR8_H__ -#define __EMU_MACHINE_AVR8_H__ - -// Helpful enums and defines for the Atmel 8-bit AVR series of microcontrollers - -namespace Avr8 -{ - -enum -{ - REGIDX_R0 = 0, - REGIDX_R1, - REGIDX_R2, - REGIDX_R3, - REGIDX_R4, - REGIDX_R5, - REGIDX_R6, - REGIDX_R7, - REGIDX_R8, - REGIDX_R9, - REGIDX_R10, - REGIDX_R11, - REGIDX_R12, - REGIDX_R13, - REGIDX_R14, - REGIDX_R15, - REGIDX_R16, - REGIDX_R17, - REGIDX_R18, - REGIDX_R19, - REGIDX_R20, - REGIDX_R21, - REGIDX_R22, - REGIDX_R23, - REGIDX_R24, - REGIDX_R25, - REGIDX_R26, - REGIDX_R27, - REGIDX_R28, - REGIDX_R29, - REGIDX_R30, - REGIDX_R31, - - REGIDX_PINB = 0x23, - REGIDX_DDRB, - REGIDX_PORTB, - REGIDX_PINC, - REGIDX_DDRC, - REGIDX_PORTC, - REGIDX_PIND, - REGIDX_DDRD, - REGIDX_PORTD, - - REGIDX_TIFR0 = 0x35, - REGIDX_TIFR1, - REGIDX_TIFR2, - - REGIDX_PCIFR = 0x3b, - REGIDX_EIFR, - REGIDX_EIMSK, - REGIDX_GPIOR0, - REGIDX_EECR, - REGIDX_EEDR, - REGIDX_EEARL, - REGIDX_EEARH, - REGIDX_GTCCR, - REGIDX_TCCR0A, - REGIDX_TCCR0B, - REGIDX_TCNT0, - REGIDX_OCR0A, - REGIDX_OCR0B, - - REGIDX_GPIOR1 = 0x4a, - REGIDX_GPIOR2, - REGIDX_SPCR, - REGIDX_SPSR, - REGIDX_SPDR, - - REGIDX_ACSR = 0x50, - - REGIDX_SMCR = 0x53, - REGIDX_MCUSR, - REGIDX_MCUCR, - - REGIDX_SPMCSR = 0x57, - - REGIDX_SPL = 0x5d, - REGIDX_SPH, - REGIDX_SREG, - REGIDX_WDTCSR, - REGIDX_CLKPR, - - REGIDX_PRR = 0x64, - - REGIDX_OSCCAL = 0x66, - - REGIDX_PCICR = 0x68, - REGIDX_EICRA, - - REGIDX_PCMSK0 = 0x6B, - REGIDX_PCMSK1, - REGIDX_PCMSK2, - REGIDX_TIMSK0, - REGIDX_TIMSK1, - REGIDX_TIMSK2, - - REGIDX_ADCL = 0x78, - REGIDX_ADCH, - REGIDX_ADCSRA, - REGIDX_ADCSRB, - REGIDX_ADMUX, - - REGIDX_DIDR0 = 0x7e, - REGIDX_DIDR1, - REGIDX_TCCR1A, - REGIDX_TCCR1B, - REGIDX_TCCR1C, - - REGIDX_TCNT1L = 0x84, - REGIDX_TCNT1H, - REGIDX_ICR1L, - REGIDX_ICR1H, - REGIDX_OCR1AL, - REGIDX_OCR1AH, - REGIDX_OCR1BL, - REGIDX_OCR1BH, - - REGIDX_TCCR2A = 0xb0, - REGIDX_TCCR2B, - REGIDX_TCNT2, - REGIDX_OCR2A, - REGIDX_OCR2B, - - REGIDX_ASSR = 0xb6, - - REGIDX_TWBR = 0xb8, - REGIDX_TWSR, - REGIDX_TWAR, - REGIDX_TWDR, - REGIDX_TWCR, - REGIDX_TWAMR, - - REGIDX_UCSR0A = 0xc0, - REGIDX_UCSR0B, - REGIDX_UCSR0C, - - REGIDX_UBRR0L = 0xc4, - REGIDX_UBRR0H, - REGIDX_UDR0 -}; - -enum -{ - WGM1_NORMAL = 0, - WGM1_PWM_8_PC, - WGM1_PWM_9_PC, - WGM1_PWM_10_PC, - WGM1_CTC_OCR, - WGM1_FAST_PWM_8, - WGM1_FAST_PWM_9, - WGM1_FAST_PWM_10, - WGM1_PWM_PFC_ICR, - WGM1_PWM_PFC_OCR, - WGM1_PWM_PC_ICR, - WGM1_PWM_PC_OCR, - WGM1_CTC_ICR, - WGM1_RESERVED, - WGM1_FAST_PWM_ICR, - WGM1_FAST_PWM_OCR -}; - -enum -{ - WGM2_NORMAL = 0, - WGM2_PWM_PC, - WGM2_CTC_CMP, - WGM2_FAST_PWM, - WGM2_RESERVED0, - WGM2_PWM_PC_CMP, - WGM2_RESERVED1, - WGM2_FAST_PWM_CMP -}; - -} // namespace AVR8 - -#define AVR8_OCR1BH (state->m_regs[Avr8::REGIDX_OCR1BH]) -#define AVR8_OCR1BL (state->m_regs[Avr8::REGIDX_OCR1BL]) -#define AVR8_OCR1AH (state->m_regs[Avr8::REGIDX_OCR1AH]) -#define AVR8_OCR1AL (state->m_regs[Avr8::REGIDX_OCR1AL]) -#define AVR8_ICR1H (state->m_regs[Avr8::REGIDX_ICR1H]) -#define AVR8_ICR1L (state->m_regs[Avr8::REGIDX_ICR1L]) -#define AVR8_TCNT1H (state->m_regs[Avr8::REGIDX_TCNT1H]) -#define AVR8_TCNT1L (state->m_regs[Avr8::REGIDX_TCNT1L]) - -#define AVR8_SREG_I 0x80 - -#define AVR8_TCCR1B (state->m_regs[Avr8::REGIDX_TCCR1B]) -#define AVR8_TCCR1B_ICNC1_MASK 0x80 -#define AVR8_TCCR1B_ICNC1_SHIFT 7 -#define AVR8_TCCR1B_ICES1_MASK 0x40 -#define AVR8_TCCR1B_ICES1_SHIFT 6 -#define AVR8_TCCR1B_WGM1_32_MASK 0x18 -#define AVR8_TCCR1B_WGM1_32_SHIFT 3 -#define AVR8_TCCR1B_CS_MASK 0x03 -#define AVR8_TCCR1B_CS_SHIFT 0 - -#define AVR8_TCCR1A (state->m_regs[Avr8::REGIDX_TCCR1A]) -#define AVR8_TCCR1A_COM1A_MASK 0xc0 -#define AVR8_TCCR1A_COM1A_SHIFT 6 -#define AVR8_TCCR1A_COM1B_MASK 0x30 -#define AVR8_TCCR1A_COM1B_SHIFT 4 -#define AVR8_TCCR1A_WGM1_10_MASK 0x03 -#define AVR8_TCCR1A_WGM1_10_SHIFT 0 -#define AVR8_TCCR1A_COM1A ((AVR8_TCCR1A & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT) -#define AVR8_TCCR1A_COM1B ((AVR8_TCCR1A & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT) -#define AVR8_TCCR1A_WGM1_10 (AVR8_TCCR1A & AVR8_TCCR1A_WGM1_10_MASK) - -#define AVR8_TIMSK1 (state->m_regs[Avr8::REGIDX_TIMSK1]) -#define AVR8_TIMSK1_ICIE1_MASK 0x20 -#define AVR8_TIMSK1_OCIE1B_MASK 0x04 -#define AVR8_TIMSK1_OCIE1A_MASK 0x02 -#define AVR8_TIMSK1_TOIE1_MASK 0x01 -#define AVR8_TIMSK1_ICIE1 ((AVR8_TIMSK1 & AVR8_TIMSK1_ICIE1_MASK) >> 5) -#define AVR8_TIMSK1_OCIE1B ((AVR8_TIMSK1 & AVR8_TIMSK1_OCIE1B_MASK) >> 2) -#define AVR8_TIMSK1_OCIE1A ((AVR8_TIMSK1 & AVR8_TIMSK1_OCIE1A_MASK) >> 1) -#define AVR8_TIMSK1_TOIE1 (AVR8_TIMSK1 & AVR8_TIMSK1_TOIE1_MASK) - -#define AVR8_TCCR2B (state->m_regs[Avr8::REGIDX_TCCR1B]) -#define AVR8_TCCR2B_FOC2A_MASK 0x80 -#define AVR8_TCCR2B_FOC2A_SHIFT 7 -#define AVR8_TCCR2B_FOC2B_MASK 0x40 -#define AVR8_TCCR2B_FOC2B_SHIFT 6 -#define AVR8_TCCR2B_WGM2_2_MASK 0x08 -#define AVR8_TCCR2B_WGM2_2_SHIFT 3 -#define AVR8_TCCR2B_CS_MASK 0x03 -#define AVR8_TCCR2B_CS_SHIFT 0 -#define AVR8_TIMER2_CLOCK_SELECT ((AVR8_TCCR2B & AVR8_TCCR2B_CS_MASK) >> AVR8_TCCR2B_CS_SHIFT) - -#define AVR8_TCCR2A (state->m_regs[Avr8::REGIDX_TCCR1A]) -#define AVR8_TCCR2A_COM2A_MASK 0xc0 -#define AVR8_TCCR2A_COM2A_SHIFT 6 -#define AVR8_TCCR2A_COM2B_MASK 0x30 -#define AVR8_TCCR2A_COM2B_SHIFT 4 -#define AVR8_TCCR2A_WGM2_10_MASK 0x03 -#define AVR8_TCCR2A_WGM2_10_SHIFT 0 -#define AVR8_TCCR2A_COM2A ((AVR8_TCCR2A & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT) -#define AVR8_TCCR2A_COM2B ((AVR8_TCCR2A & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT) -#define AVR8_TCCR2A_WGM2_10 (AVR8_TCCR2A & AVR8_TCCR1A_WGM2_10_MASK) - -#define AVR8_SPSR (state->m_regs[Avr8::REGIDX_SPSR]) -#define AVR8_SPSR_SPIF_MASK 0x80 -#define AVR8_SPSR_SPIF_SHIFT 7 -#define AVR8_SPSR_SPR2X_MASK 0x01 -#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK) - -#define AVR8_SPCR (state->m_regs[Avr8::REGIDX_SPCR]) -#define AVR8_SPCR_SPIE_MASK 0x80 -#define AVR8_SPCR_SPE_MASK 0x40 -#define AVR8_SPCR_DORD_MASK 0x20 -#define AVR8_SPCR_MSTR_MASK 0x10 -#define AVR8_SPCR_CPOL_MASK 0x08 -#define AVR8_SPCR_CPHA_MASK 0x04 -#define AVR8_SPCR_SPR_MASK 0x03 -#define AVR8_SPCR_SPIE ((AVR8_SPCR & AVR8_SPCR_SPIE_MASK) >> 7) -#define AVR8_SPCR_SPE ((AVR8_SPCR & AVR8_SPCR_SPE_MASK) >> 6) -#define AVR8_SPCR_DORD ((AVR8_SPCR & AVR8_SPCR_DORD_MASK) >> 5) -#define AVR8_SPCR_MSTR ((AVR8_SPCR & AVR8_SPCR_MSTR_MASK) >> 4) -#define AVR8_SPCR_CPOL ((AVR8_SPCR & AVR8_SPCR_CPOL_MASK) >> 3) -#define AVR8_SPCR_CPHA ((AVR8_SPCR & AVR8_SPCR_CPHA_MASK) >> 2) -#define AVR8_SPCR_SPR (AVR8_SPCR & AVR8_SPCR_SPR_MASK) - -#define AVR8_TIFR1 (state->m_regs[Avr8::REGIDX_TIFR1]) -#define AVR8_TIFR1_ICF1_MASK 0x20 -#define AVR8_TIFR1_ICF1_SHIFT 5 -#define AVR8_TIFR1_OCF1B_MASK 0x04 -#define AVR8_TIFR1_OCF1B_SHIFT 2 -#define AVR8_TIFR1_OCF1A_MASK 0x02 -#define AVR8_TIFR1_OCF1A_SHIFT 1 -#define AVR8_TIFR1_TOV1_MASK 0x01 -#define AVR8_TIFR1_TOV1_SHIFT 0 - -#define AVR8_DDRD (state->m_regs[Avr8::REGIDX_DDRD]) -#define AVR8_DDRC (state->m_regs[Avr8::REGIDX_DDRC]) -#define AVR8_PORTB (state->m_regs[Avr8::REGIDX_PORTB]) -#define AVR8_DDRB (state->m_regs[Avr8::REGIDX_DDRB]) - -#define AVR8_OCR1A ((AVR8_OCR1AH << 8) | AVR8_OCR1AL) -#define AVR8_OCR1B ((AVR8_OCR1BH << 8) | AVR8_OCR1BL) -#define AVR8_ICR1 ((AVR8_ICR1H << 8) | AVR8_ICR1L) -#define AVR8_TCNT1 ((AVR8_TCNT1H << 8) | AVR8_TCNT1L) -#define AVR8_WGM1 (((AVR8_TCCR1B & 0x18) >> 1) | (AVR8_TCCR1A & 0x03)) -#define AVR8_TCNT1_DIR (state->m_tcnt1_direction) - -#define AVR8_OCR2B state->m_regs[Avr8::REGIDX_OCR2B] -#define AVR8_OCR2A state->m_regs[Avr8::REGIDX_OCR2A] -#define AVR8_TCNT2 state->m_regs[Avr8::REGIDX_TCNT2] -#define AVR8_WGM2 (((AVR8_TCCR2B & 0x08) >> 1) | (AVR8_TCCR2A & 0x03)) - -#endif // __EMU_MACHINE_AVR8_H__