diff options
Diffstat (limited to 'src/emu/cpu/avr8/avr8.c')
-rw-r--r-- | src/emu/cpu/avr8/avr8.c | 2806 |
1 files changed, 1403 insertions, 1403 deletions
diff --git a/src/emu/cpu/avr8/avr8.c b/src/emu/cpu/avr8/avr8.c index 10aefec61aa..9a271fcab55 100644 --- a/src/emu/cpu/avr8/avr8.c +++ b/src/emu/cpu/avr8/avr8.c @@ -39,7 +39,7 @@ #include "debugger.h" #include "avr8.h" -#define VERBOSE_LEVEL (0) +#define VERBOSE_LEVEL (0) #define ENABLE_VERBOSE_LOG (0) @@ -66,14 +66,14 @@ INLINE void verboselog(UINT16 pc, int n_level, const char *s_fmt, ...) enum { - AVR8_SREG_C = 0, - AVR8_SREG_Z, - AVR8_SREG_N, - AVR8_SREG_V, - AVR8_SREG_S, - AVR8_SREG_H, - AVR8_SREG_T, - AVR8_SREG_I, + AVR8_SREG_C = 0, + AVR8_SREG_Z, + AVR8_SREG_N, + AVR8_SREG_V, + AVR8_SREG_S, + AVR8_SREG_H, + AVR8_SREG_T, + AVR8_SREG_I, }; // I/O Enums @@ -131,181 +131,181 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' }; #define QCONST6(op) ((((op) >> 8) & 0x0020) | (((op) >> 7) & 0x0018) | ((op) & 0x0007)) #define ACONST5(op) (((op) >> 3) & 0x001f) #define ACONST6(op) ((((op) >> 5) & 0x0030) | ((op) & 0x000f)) -#define MULCONST2(op) ((((op) >> 6) & 0x0002) | (((op) >> 3) & 0x0001)) +#define MULCONST2(op) ((((op) >> 6) & 0x0002) | (((op) >> 3) & 0x0001)) // Register Defines #define XREG ((m_r[27] << 8) | m_r[26]) #define YREG ((m_r[29] << 8) | m_r[28]) #define ZREG ((m_r[31] << 8) | m_r[30]) -#define SPREG ((m_r[AVR8_REGIDX_SPH] << 8) | m_r[AVR8_REGIDX_SPL]) +#define SPREG ((m_r[AVR8_REGIDX_SPH] << 8) | m_r[AVR8_REGIDX_SPL]) // I/O Defines -#define AVR8_OCR1BH (m_r[AVR8_REGIDX_OCR1BH]) -#define AVR8_OCR1BL (m_r[AVR8_REGIDX_OCR1BL]) -#define AVR8_OCR1AH (m_r[AVR8_REGIDX_OCR1AH]) -#define AVR8_OCR1AL (m_r[AVR8_REGIDX_OCR1AL]) -#define AVR8_ICR1H (m_r[AVR8_REGIDX_ICR1H]) -#define AVR8_ICR1L (m_r[AVR8_REGIDX_ICR1L]) -#define AVR8_TCNT1H (m_r[AVR8_REGIDX_TCNT1H]) -#define AVR8_TCNT1L (m_r[AVR8_REGIDX_TCNT1L]) - -#define AVR8_TCCR0B (m_r[AVR8_REGIDX_TCCR0B]) -#define AVR8_TCCR0B_FOC0A_MASK 0x80 -#define AVR8_TCCR0B_FOC0A_SHIFT 7 -#define AVR8_TCCR0B_FOC0B_MASK 0x40 -#define AVR8_TCCR0B_FOC0B_SHIFT 6 -#define AVR8_TCCR0B_WGM0_2_MASK 0x08 -#define AVR8_TCCR0B_WGM0_2_SHIFT 3 -#define AVR8_TCCR0B_CS_MASK 0x07 -#define AVR8_TCCR0B_CS_SHIFT 0 -#define AVR8_TIMER0_CLOCK_SELECT (AVR8_TCCR0B & AVR8_TCCR0B_CS_MASK) - -#define AVR8_TCCR0A (m_r[AVR8_REGIDX_TCCR0A]) -#define AVR8_TCCR0A_COM0A_MASK 0xc0 -#define AVR8_TCCR0A_COM0A_SHIFT 6 -#define AVR8_TCCR0A_COM0B_MASK 0x30 -#define AVR8_TCCR0A_COM0B_SHIFT 4 -#define AVR8_TCCR0A_WGM0_10_MASK 0x03 -#define AVR8_TCCR0A_WGM0_10_SHIFT 0 -#define AVR8_TCCR0A_COM0A ((AVR8_TCCR0A & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT) -#define AVR8_TCCR0A_COM0B ((AVR8_TCCR0A & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT) -#define AVR8_TCCR0A_WGM0_10 (AVR8_TCCR0A & AVR8_TCCR0A_WGM0_10_MASK) - -#define AVR8_TIMSK0 (m_r[AVR8_REGIDX_TIMSK0]) -#define AVR8_TIMSK0_OCIE0B_MASK 0x04 -#define AVR8_TIMSK0_OCIE0A_MASK 0x02 -#define AVR8_TIMSK0_TOIE0_MASK 0x01 -#define AVR8_TIMSK0_OCIE0B ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0B_MASK) >> 2) -#define AVR8_TIMSK0_OCIE0A ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0A_MASK) >> 1) -#define AVR8_TIMSK0_TOIE0 (AVR8_TIMSK0 & AVR8_TIMSK0_TOIE0_MASK) - -#define AVR8_TIFR0 (m_r[AVR8_REGIDX_TIFR0]) -#define AVR8_TIFR0_OCF0B_MASK 0x04 -#define AVR8_TIFR0_OCF0B_SHIFT 2 -#define AVR8_TIFR0_OCF0A_MASK 0x02 -#define AVR8_TIFR0_OCF0A_SHIFT 1 -#define AVR8_TIFR0_TOV0_MASK 0x01 -#define AVR8_TIFR0_TOV0_SHIFT 0 -#define AVR8_TIFR0_MASK (AVR8_TIFR0_TOV0_MASK | AVR8_TIFR0_OCF0B_MASK | AVR8_TIFR0_OCF0A_MASK) - -#define AVR8_TCCR1B (m_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 (m_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 (m_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 (m_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 (m_r[AVR8_REGIDX_TCCR2B]) -#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 (m_r[AVR8_REGIDX_TCCR2A]) -#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_TCCR2A_WGM2_10_MASK) - -#define AVR8_TIMSK2 (m_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_TIMSK2_OCIE2B_MASK) >> 2) -#define AVR8_TIMSK2_OCIE2A ((AVR8_TIMSK2 & AVR8_TIMSK2_OCIE2A_MASK) >> 1) -#define AVR8_TIMSK2_TOIE2 (AVR8_TIMSK2 & AVR8_TIMSK2_TOIE2_MASK) - -#define AVR8_TIFR2 (m_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_OCR0A m_r[AVR8_REGIDX_OCR0A] -#define AVR8_OCR0B m_r[AVR8_REGIDX_OCR0B] -#define AVR8_TCNT0 m_r[AVR8_REGIDX_TCNT0] -#define AVR8_WGM0 (((AVR8_TCCR0B & 0x08) >> 1) | (AVR8_TCCR0A & 0x03)) - -#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_OCR2A m_r[AVR8_REGIDX_OCR2A] -#define AVR8_OCR2B m_r[AVR8_REGIDX_OCR2B] -#define AVR8_TCNT2 m_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 - -#define AVR8_SPSR (m_r[AVR8_REGIDX_SPSR]) -#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK) - -#define AVR8_SPCR (m_r[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) - -#define AVR8_SPI_RATE ((AVR8_SPSR_SPR2X << 2) | AVR8_SPCR_SPR) - -#define AVR8_PORTB_MOSI 0x08 +#define AVR8_OCR1BH (m_r[AVR8_REGIDX_OCR1BH]) +#define AVR8_OCR1BL (m_r[AVR8_REGIDX_OCR1BL]) +#define AVR8_OCR1AH (m_r[AVR8_REGIDX_OCR1AH]) +#define AVR8_OCR1AL (m_r[AVR8_REGIDX_OCR1AL]) +#define AVR8_ICR1H (m_r[AVR8_REGIDX_ICR1H]) +#define AVR8_ICR1L (m_r[AVR8_REGIDX_ICR1L]) +#define AVR8_TCNT1H (m_r[AVR8_REGIDX_TCNT1H]) +#define AVR8_TCNT1L (m_r[AVR8_REGIDX_TCNT1L]) + +#define AVR8_TCCR0B (m_r[AVR8_REGIDX_TCCR0B]) +#define AVR8_TCCR0B_FOC0A_MASK 0x80 +#define AVR8_TCCR0B_FOC0A_SHIFT 7 +#define AVR8_TCCR0B_FOC0B_MASK 0x40 +#define AVR8_TCCR0B_FOC0B_SHIFT 6 +#define AVR8_TCCR0B_WGM0_2_MASK 0x08 +#define AVR8_TCCR0B_WGM0_2_SHIFT 3 +#define AVR8_TCCR0B_CS_MASK 0x07 +#define AVR8_TCCR0B_CS_SHIFT 0 +#define AVR8_TIMER0_CLOCK_SELECT (AVR8_TCCR0B & AVR8_TCCR0B_CS_MASK) + +#define AVR8_TCCR0A (m_r[AVR8_REGIDX_TCCR0A]) +#define AVR8_TCCR0A_COM0A_MASK 0xc0 +#define AVR8_TCCR0A_COM0A_SHIFT 6 +#define AVR8_TCCR0A_COM0B_MASK 0x30 +#define AVR8_TCCR0A_COM0B_SHIFT 4 +#define AVR8_TCCR0A_WGM0_10_MASK 0x03 +#define AVR8_TCCR0A_WGM0_10_SHIFT 0 +#define AVR8_TCCR0A_COM0A ((AVR8_TCCR0A & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT) +#define AVR8_TCCR0A_COM0B ((AVR8_TCCR0A & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT) +#define AVR8_TCCR0A_WGM0_10 (AVR8_TCCR0A & AVR8_TCCR0A_WGM0_10_MASK) + +#define AVR8_TIMSK0 (m_r[AVR8_REGIDX_TIMSK0]) +#define AVR8_TIMSK0_OCIE0B_MASK 0x04 +#define AVR8_TIMSK0_OCIE0A_MASK 0x02 +#define AVR8_TIMSK0_TOIE0_MASK 0x01 +#define AVR8_TIMSK0_OCIE0B ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0B_MASK) >> 2) +#define AVR8_TIMSK0_OCIE0A ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0A_MASK) >> 1) +#define AVR8_TIMSK0_TOIE0 (AVR8_TIMSK0 & AVR8_TIMSK0_TOIE0_MASK) + +#define AVR8_TIFR0 (m_r[AVR8_REGIDX_TIFR0]) +#define AVR8_TIFR0_OCF0B_MASK 0x04 +#define AVR8_TIFR0_OCF0B_SHIFT 2 +#define AVR8_TIFR0_OCF0A_MASK 0x02 +#define AVR8_TIFR0_OCF0A_SHIFT 1 +#define AVR8_TIFR0_TOV0_MASK 0x01 +#define AVR8_TIFR0_TOV0_SHIFT 0 +#define AVR8_TIFR0_MASK (AVR8_TIFR0_TOV0_MASK | AVR8_TIFR0_OCF0B_MASK | AVR8_TIFR0_OCF0A_MASK) + +#define AVR8_TCCR1B (m_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 (m_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 (m_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 (m_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 (m_r[AVR8_REGIDX_TCCR2B]) +#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 (m_r[AVR8_REGIDX_TCCR2A]) +#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_TCCR2A_WGM2_10_MASK) + +#define AVR8_TIMSK2 (m_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_TIMSK2_OCIE2B_MASK) >> 2) +#define AVR8_TIMSK2_OCIE2A ((AVR8_TIMSK2 & AVR8_TIMSK2_OCIE2A_MASK) >> 1) +#define AVR8_TIMSK2_TOIE2 (AVR8_TIMSK2 & AVR8_TIMSK2_TOIE2_MASK) + +#define AVR8_TIFR2 (m_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_OCR0A m_r[AVR8_REGIDX_OCR0A] +#define AVR8_OCR0B m_r[AVR8_REGIDX_OCR0B] +#define AVR8_TCNT0 m_r[AVR8_REGIDX_TCNT0] +#define AVR8_WGM0 (((AVR8_TCCR0B & 0x08) >> 1) | (AVR8_TCCR0A & 0x03)) + +#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_OCR2A m_r[AVR8_REGIDX_OCR2A] +#define AVR8_OCR2B m_r[AVR8_REGIDX_OCR2B] +#define AVR8_TCNT2 m_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 + +#define AVR8_SPSR (m_r[AVR8_REGIDX_SPSR]) +#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK) + +#define AVR8_SPCR (m_r[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) + +#define AVR8_SPI_RATE ((AVR8_SPSR_SPR2X << 2) | AVR8_SPCR_SPR) + +#define AVR8_PORTB_MOSI 0x08 //************************************************************************** // DEVICE INTERFACE @@ -346,33 +346,33 @@ atmega644_device::atmega644_device(const machine_config &mconfig, const char *ta avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 addr_mask, address_map_constructor internal_map) : cpu_device(mconfig, type, "AVR8", tag, owner, clock), - m_program_config("program", ENDIANNESS_LITTLE, 8, 22), - m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, internal_map), - m_io_config("io", ENDIANNESS_LITTLE, 8, 2), - m_eeprom(NULL), - m_pc(0), - m_shifted_pc(0), - m_timer0_top(0), - m_timer0_increment(1), - m_timer0_prescale(0), - m_timer0_prescale_count(0), - m_timer1_top(0), - m_timer1_increment(1), - m_timer1_prescale(0), - m_timer1_prescale_count(0), - m_timer2_top(0), - m_timer2_increment(1), - m_timer2_prescale(0), - m_timer2_prescale_count(0), - m_spi_active(false), - m_spi_prescale(0), - m_spi_prescale_count(0), - m_addr_mask(addr_mask), - m_interrupt_pending(false), - m_icount(0), - m_elapsed_cycles(0) + m_program_config("program", ENDIANNESS_LITTLE, 8, 22), + m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, internal_map), + m_io_config("io", ENDIANNESS_LITTLE, 8, 2), + m_eeprom(NULL), + m_pc(0), + m_shifted_pc(0), + m_timer0_top(0), + m_timer0_increment(1), + m_timer0_prescale(0), + m_timer0_prescale_count(0), + m_timer1_top(0), + m_timer1_increment(1), + m_timer1_prescale(0), + m_timer1_prescale_count(0), + m_timer2_top(0), + m_timer2_increment(1), + m_timer2_prescale(0), + m_timer2_prescale_count(0), + m_spi_active(false), + m_spi_prescale(0), + m_spi_prescale_count(0), + m_addr_mask(addr_mask), + m_interrupt_pending(false), + m_icount(0), + m_elapsed_cycles(0) { - // Allocate & setup + // Allocate & setup } @@ -395,7 +395,7 @@ void avr8_device::static_set_config(device_t &device, const avr8_config &config) void avr8_device::unimplemented_opcode(UINT32 op) { - fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, m_pc); + fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, m_pc); } @@ -432,11 +432,11 @@ inline bool avr8_device::is_long_opcode(UINT16 op) void avr8_device::device_start() { - m_pc = 0; + m_pc = 0; - m_program = &space(AS_PROGRAM); - m_data = &space(AS_DATA); - m_io = &space(AS_IO); + m_program = &space(AS_PROGRAM); + m_data = &space(AS_DATA); + m_io = &space(AS_IO); // register our state for the debugger astring tempstr; @@ -521,31 +521,31 @@ void avr8_device::device_reset() m_spi_prescale = 0; m_spi_prescale_count = 0; - m_timer0_top = 0; + m_timer0_top = 0; m_timer0_increment = 1; m_timer0_prescale = 0; m_timer0_prescale_count = 0; - m_timer1_top = 0; + m_timer1_top = 0; m_timer1_increment = 1; m_timer1_prescale = 0; m_timer1_prescale_count = 0; - m_timer2_top = 0; + m_timer2_top = 0; m_timer2_increment = 1; m_timer2_prescale = 0; m_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; + 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; m_interrupt_pending = false; @@ -587,14 +587,14 @@ void avr8_device::state_string_export(const device_state_entry &entry, astring & { case STATE_GENFLAGS: string.printf("%c%c%c%c%c%c%c%c", - (m_r[AVR8_REGIDX_SREG] & 0x80) ? 'I' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x40) ? 'T' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x20) ? 'H' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x10) ? 'S' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x08) ? 'V' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x04) ? 'N' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x02) ? 'Z' : '-', - (m_r[AVR8_REGIDX_SREG] & 0x01) ? 'C' : '-'); + (m_r[AVR8_REGIDX_SREG] & 0x80) ? 'I' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x40) ? 'T' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x20) ? 'H' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x10) ? 'S' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x08) ? 'V' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x04) ? 'N' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x02) ? 'Z' : '-', + (m_r[AVR8_REGIDX_SREG] & 0x01) ? 'C' : '-'); break; } } @@ -641,19 +641,19 @@ offs_t avr8_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *opr inline void avr8_device::push(UINT8 val) { UINT16 sp = SPREG; - m_data->write_byte(sp, val); - sp--; - m_r[AVR8_REGIDX_SPL] = sp & 0x00ff; - m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff; + m_data->write_byte(sp, val); + sp--; + m_r[AVR8_REGIDX_SPL] = sp & 0x00ff; + m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff; } inline UINT8 avr8_device::pop() { UINT16 sp = SPREG; - sp++; + sp++; m_r[AVR8_REGIDX_SPL] = sp & 0x00ff; m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff; - return m_data->read_byte(sp); + return m_data->read_byte(sp); } //************************************************************************** @@ -662,9 +662,9 @@ inline UINT8 avr8_device::pop() void avr8_device::set_irq_line(UINT16 vector, int state) { - // Horrible hack, not accurate - if(state) - { + // Horrible hack, not accurate + if(state) + { if(SREG_R(AVR8_SREG_I)) { SREG_W(AVR8_SREG_I, 0); @@ -677,7 +677,7 @@ void avr8_device::set_irq_line(UINT16 vector, int state) { m_interrupt_pending = true; } - } + } } class CInterruptCondition @@ -707,10 +707,10 @@ static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] = void avr8_device::update_interrupt(int source) { - CInterruptCondition condition = s_int_conditions[source]; + CInterruptCondition condition = s_int_conditions[source]; - int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0; - intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0; + int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0; + intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0; set_irq_line(condition.m_intindex, intstate); @@ -738,10 +738,10 @@ static const CInterruptCondition s_mega644_int_conditions[AVR8_INTIDX_COUNT] = void atmega644_device::update_interrupt(int source) { - CInterruptCondition condition = s_mega644_int_conditions[source]; + CInterruptCondition condition = s_mega644_int_conditions[source]; - int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0; - intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0; + int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0; + intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0; set_irq_line(condition.m_intindex << 1, intstate); @@ -810,94 +810,94 @@ void avr8_device::timer_tick(int cycles) void avr8_device::timer0_tick() { /* - UINT16 count = m_r[AVR8_REGIDX_TCNT0]; - INT32 wgm0 = ((m_r[AVR8_REGIDX_TCCR0B] & AVR8_TCCR0B_WGM0_2_MASK) >> 1) | - (m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_WGM0_10_MASK); - - // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer - //UINT8 compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT, - //(m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT }; - UINT8 ocr0[2] = { m_r[AVR8_REGIDX_OCR0A], m_r[AVR8_REGIDX_OCR0B] }; - UINT8 ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR0_OCF0B_SHIFT) }; - INT32 increment = m_timer0_increment; - - for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) - { - switch(wgm0) - { - case WGM02_FAST_PWM: - if(count == ocr0[reg]) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR0] |= AVR8_TIFR0_TOV0_MASK; - count = 0; - increment = 0; - } - - m_r[AVR8_REGIDX_TIFR0] |= ocf0[reg]; - } - else if(count == 0) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR0] &= ~AVR8_TIFR0_TOV0_MASK; - } - } - break; - - case WGM02_FAST_PWM_CMP: - if(count == ocr0[reg]) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR0] |= AVR8_TIFR0_TOV0_MASK; - count = 0; - increment = 0; - } - - m_r[AVR8_REGIDX_TIFR0] |= ocf0[reg]; - } - else if(count == 0) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR0] &= ~AVR8_TIFR0_TOV0_MASK; - } - } - break; - - default: - // TODO - break; - } - switch(compare_mode[reg]) - { - case 0: - //verboselog(m_pc, 0, "update_timer0_compare_mode: Normal port operation (OC0 disconnected)\n"); - break; - - case 1: - case 2: - // TODO - break; - - case 3: - break; - } - } - - m_r[AVR8_REGIDX_TCNT0] = count + increment; - - update_interrupt(AVR8_INTIDX_OCF0A); - update_interrupt(AVR8_INTIDX_OCF0B); - update_interrupt(AVR8_INTIDX_TOV0); - */ + UINT16 count = m_r[AVR8_REGIDX_TCNT0]; + INT32 wgm0 = ((m_r[AVR8_REGIDX_TCCR0B] & AVR8_TCCR0B_WGM0_2_MASK) >> 1) | + (m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_WGM0_10_MASK); + + // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer + //UINT8 compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT, + //(m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT }; + UINT8 ocr0[2] = { m_r[AVR8_REGIDX_OCR0A], m_r[AVR8_REGIDX_OCR0B] }; + UINT8 ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR0_OCF0B_SHIFT) }; + INT32 increment = m_timer0_increment; + + for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) + { + switch(wgm0) + { + case WGM02_FAST_PWM: + if(count == ocr0[reg]) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR0] |= AVR8_TIFR0_TOV0_MASK; + count = 0; + increment = 0; + } + + m_r[AVR8_REGIDX_TIFR0] |= ocf0[reg]; + } + else if(count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR0] &= ~AVR8_TIFR0_TOV0_MASK; + } + } + break; + + case WGM02_FAST_PWM_CMP: + if(count == ocr0[reg]) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR0] |= AVR8_TIFR0_TOV0_MASK; + count = 0; + increment = 0; + } + + m_r[AVR8_REGIDX_TIFR0] |= ocf0[reg]; + } + else if(count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR0] &= ~AVR8_TIFR0_TOV0_MASK; + } + } + break; + + default: + // TODO + break; + } + switch(compare_mode[reg]) + { + case 0: + //verboselog(m_pc, 0, "update_timer0_compare_mode: Normal port operation (OC0 disconnected)\n"); + break; + + case 1: + case 2: + // TODO + break; + + case 3: + break; + } + } + + m_r[AVR8_REGIDX_TCNT0] = count + increment; + + update_interrupt(AVR8_INTIDX_OCF0A); + update_interrupt(AVR8_INTIDX_OCF0B); + update_interrupt(AVR8_INTIDX_TOV0); + */ } void avr8_device::update_timer0_waveform_gen_mode() { - m_timer0_top = 0; + m_timer0_top = 0; switch(AVR8_WGM0) { case WGM02_NORMAL: @@ -1008,32 +1008,32 @@ void avr8_device::update_timer0_clock_source() void avr8_device::update_ocr0(UINT8 newval, UINT8 reg) { - m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR0A : AVR8_REGIDX_OCR0B] = newval; + m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR0A : AVR8_REGIDX_OCR0B] = newval; } // Timer 1 Handling void avr8_device::timer1_tick() { - /* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */ + /* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */ - UINT16 count = (m_r[AVR8_REGIDX_TCNT1H] << 8) | m_r[AVR8_REGIDX_TCNT1L]; - INT32 wgm1 = ((m_r[AVR8_REGIDX_TCCR1B] & AVR8_TCCR1B_WGM1_32_MASK) >> 1) | - (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_WGM1_10_MASK); + UINT16 count = (m_r[AVR8_REGIDX_TCNT1H] << 8) | m_r[AVR8_REGIDX_TCNT1L]; + INT32 wgm1 = ((m_r[AVR8_REGIDX_TCCR1B] & AVR8_TCCR1B_WGM1_32_MASK) >> 1) | + (m_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] = { (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT, - //(m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT }; - UINT16 ocr1[2] = { (m_r[AVR8_REGIDX_OCR1AH] << 8) | m_r[AVR8_REGIDX_OCR1AL], - (m_r[AVR8_REGIDX_OCR1BH] << 8) | m_r[AVR8_REGIDX_OCR1BL] }; + // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer + //UINT8 compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT, + //(m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT }; + UINT16 ocr1[2] = { (m_r[AVR8_REGIDX_OCR1AH] << 8) | m_r[AVR8_REGIDX_OCR1AL], + (m_r[AVR8_REGIDX_OCR1BH] << 8) | m_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 = m_timer1_increment; + INT32 increment = m_timer1_increment; - for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) - { - switch(wgm1) - { + for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) + { + switch(wgm1) + { case WGM1_CTC_OCR: if (count == 0xffff) { @@ -1043,81 +1043,81 @@ void avr8_device::timer1_tick() increment = 0; } - if (count == ocr1[reg]) - { - if (reg == 0) - { + if (count == ocr1[reg]) + { + if (reg == 0) + { count = 0; increment = 0; - } - m_r[AVR8_REGIDX_TIFR1] |= ocf1[reg]; + } + m_r[AVR8_REGIDX_TIFR1] |= ocf1[reg]; update_interrupt(int1[reg]); - } - else if (count == 0) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; + } + else if (count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; update_interrupt(AVR8_INTIDX_TOV1); - } + } - m_r[AVR8_REGIDX_TIFR1] &= ~ocf1[reg]; + m_r[AVR8_REGIDX_TIFR1] &= ~ocf1[reg]; update_interrupt(int1[reg]); - } - break; - - case WGM1_FAST_PWM_OCR: - if(count == ocr1[reg]) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK; + } + break; + + case WGM1_FAST_PWM_OCR: + if(count == ocr1[reg]) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK; update_interrupt(AVR8_INTIDX_TOV1); - count = 0; - increment = 0; - } + count = 0; + increment = 0; + } - m_r[AVR8_REGIDX_TIFR1] |= ocf1[reg]; + m_r[AVR8_REGIDX_TIFR1] |= ocf1[reg]; update_interrupt(int1[reg]); - } - else if(count == 0) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; + } + else if(count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; update_interrupt(AVR8_INTIDX_TOV1); - } + } - m_r[AVR8_REGIDX_TIFR1] &= ~ocf1[reg]; + m_r[AVR8_REGIDX_TIFR1] &= ~ocf1[reg]; update_interrupt(int1[reg]); - } - break; - - default: - verboselog(m_pc, 0, "update_timer1_compare_mode: Unknown waveform generation mode: %02x\n", wgm1); - break; - } - /* - switch(compare_mode[reg]) - { - case 0: - //verboselog(m_pc, 0, "update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n"); - break; - - case 1: - case 2: - // TODO - break; - - case 3: - break; - } - */ - } - - count += increment; - m_r[AVR8_REGIDX_TCNT1H] = (count >> 8) & 0xff; - m_r[AVR8_REGIDX_TCNT1L] = count & 0xff; + } + break; + + default: + verboselog(m_pc, 0, "update_timer1_compare_mode: Unknown waveform generation mode: %02x\n", wgm1); + break; + } + /* + switch(compare_mode[reg]) + { + case 0: + //verboselog(m_pc, 0, "update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n"); + break; + + case 1: + case 2: + // TODO + break; + + case 3: + break; + } + */ + } + + count += increment; + m_r[AVR8_REGIDX_TCNT1H] = (count >> 8) & 0xff; + m_r[AVR8_REGIDX_TCNT1L] = count & 0xff; } void avr8_device::update_timer1_waveform_gen_mode() @@ -1171,7 +1171,7 @@ void avr8_device::changed_tccr1a(UINT8 data) UINT8 newtccr = data; UINT8 changed = newtccr ^ oldtccr; - m_r[AVR8_REGIDX_TCCR1A] = newtccr; + m_r[AVR8_REGIDX_TCCR1A] = newtccr; if(changed & AVR8_TCCR1A_WGM1_10_MASK) { @@ -1232,7 +1232,7 @@ void avr8_device::changed_tccr1b(UINT8 data) UINT8 newtccr = data; UINT8 changed = newtccr ^ oldtccr; - m_r[AVR8_REGIDX_TCCR1B] = newtccr; + m_r[AVR8_REGIDX_TCCR1B] = newtccr; if(changed & AVR8_TCCR1B_ICNC1_MASK) { @@ -1264,93 +1264,93 @@ void avr8_device::update_ocr1(UINT16 newval, UINT8 reg) *p_reg_h = (UINT8)(newval >> 8); *p_reg_l = (UINT8)newval; - // Nothing needs to be done? All handled in timer callback + // Nothing needs to be done? All handled in timer callback } // Timer 2 Handling void avr8_device::timer2_tick() { - UINT16 count = m_r[AVR8_REGIDX_TCNT2]; - INT32 wgm2 = ((m_r[AVR8_REGIDX_TCCR2B] & AVR8_TCCR2B_WGM2_2_MASK) >> 1) | - (m_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] = { (m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT, - //(m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT }; - UINT8 ocr2[2] = { m_r[AVR8_REGIDX_OCR2A], m_r[AVR8_REGIDX_OCR2B] }; + UINT16 count = m_r[AVR8_REGIDX_TCNT2]; + INT32 wgm2 = ((m_r[AVR8_REGIDX_TCCR2B] & AVR8_TCCR2B_WGM2_2_MASK) >> 1) | + (m_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] = { (m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT, + //(m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT }; + UINT8 ocr2[2] = { m_r[AVR8_REGIDX_OCR2A], m_r[AVR8_REGIDX_OCR2B] }; UINT8 ocf2[2] = { (1 << AVR8_TIFR2_OCF2A_SHIFT), (1 << AVR8_TIFR2_OCF2B_SHIFT) }; - INT32 increment = m_timer2_increment; - - for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) - { - switch(wgm2) - { - case WGM02_FAST_PWM: - if(count == ocr2[reg]) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK; - count = 0; - increment = 0; - } - - m_r[AVR8_REGIDX_TIFR2] |= ocf2[reg]; - } - else if(count == 0) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK; - } - } - break; - - case WGM02_FAST_PWM_CMP: - if(count == ocr2[reg]) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK; - count = 0; - increment = 0; - } - - m_r[AVR8_REGIDX_TIFR2] |= ocf2[reg]; - } - else if(count == 0) - { - if (reg == 0) - { - m_r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK; - } - } - break; - - default: - // TODO - break; - } - /* - switch(compare_mode[reg]) - { - case 0: - //verboselog(m_pc, 0, "update_timer2_compare_mode: Normal port operation (OC2 disconnected)\n"); - break; - - case 1: - case 2: - // TODO - break; - - case 3: - break; - } - */ - } - - m_r[AVR8_REGIDX_TCNT2] = count + increment; + INT32 increment = m_timer2_increment; + + for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) + { + switch(wgm2) + { + case WGM02_FAST_PWM: + if(count == ocr2[reg]) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK; + count = 0; + increment = 0; + } + + m_r[AVR8_REGIDX_TIFR2] |= ocf2[reg]; + } + else if(count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK; + } + } + break; + + case WGM02_FAST_PWM_CMP: + if(count == ocr2[reg]) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK; + count = 0; + increment = 0; + } + + m_r[AVR8_REGIDX_TIFR2] |= ocf2[reg]; + } + else if(count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK; + } + } + break; + + default: + // TODO + break; + } + /* + switch(compare_mode[reg]) + { + case 0: + //verboselog(m_pc, 0, "update_timer2_compare_mode: Normal port operation (OC2 disconnected)\n"); + break; + + case 1: + case 2: + // TODO + break; + + case 3: + break; + } + */ + } + + m_r[AVR8_REGIDX_TCNT2] = count + increment; update_interrupt(AVR8_INTIDX_OCF2A); update_interrupt(AVR8_INTIDX_OCF2B); @@ -1359,7 +1359,7 @@ void avr8_device::timer2_tick() void avr8_device::update_timer2_waveform_gen_mode() { - m_timer2_top = 0; + m_timer2_top = 0; switch(AVR8_WGM2) { case WGM02_NORMAL: @@ -1471,9 +1471,9 @@ void avr8_device::changed_tccr2b(UINT8 data) void avr8_device::update_ocr2(UINT8 newval, UINT8 reg) { - m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR2A : AVR8_REGIDX_OCR2B] = newval; + m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR2A : AVR8_REGIDX_OCR2B] = newval; - // Nothing needs to be done? All handled in timer callback + // Nothing needs to be done? All handled in timer callback } /****************/ @@ -1578,8 +1578,8 @@ void avr8_device::change_spsr(UINT8 data) WRITE8_MEMBER( avr8_device::regs_w ) { - switch( offset ) - { + switch( offset ) + { case AVR8_REGIDX_R0: case AVR8_REGIDX_R1: case AVR8_REGIDX_R2: @@ -1651,8 +1651,8 @@ WRITE8_MEMBER( avr8_device::regs_w ) update_interrupt(AVR8_INTIDX_TOV0); break; - case AVR8_REGIDX_TCNT0: - AVR8_TCNT0 = data; + case AVR8_REGIDX_TCNT0: + AVR8_TCNT0 = data; break; case AVR8_REGIDX_TCCR1B: @@ -1703,12 +1703,12 @@ WRITE8_MEMBER( avr8_device::regs_w ) update_interrupt(AVR8_INTIDX_TOV1); break; - case AVR8_REGIDX_TCNT1H: - AVR8_TCNT1H = data; + case AVR8_REGIDX_TCNT1H: + AVR8_TCNT1H = data; break; - case AVR8_REGIDX_TCNT1L: - AVR8_TCNT1L = data; + case AVR8_REGIDX_TCNT1L: + AVR8_TCNT1L = data; break; case AVR8_REGIDX_TCCR2B: @@ -1744,13 +1744,13 @@ WRITE8_MEMBER( avr8_device::regs_w ) update_interrupt(AVR8_INTIDX_TOV2); break; - case AVR8_REGIDX_TCNT2: - AVR8_TCNT2 = data; + case AVR8_REGIDX_TCNT2: + AVR8_TCNT2 = data; break; - case AVR8_REGIDX_GTCCR: - if (data & AVR8_GTCCR_PSRASY_MASK) - { + case AVR8_REGIDX_GTCCR: + if (data & AVR8_GTCCR_PSRASY_MASK) + { data &= ~AVR8_GTCCR_PSRASY_MASK; m_timer2_prescale_count = 0; } @@ -1802,7 +1802,7 @@ WRITE8_MEMBER( avr8_device::regs_w ) m_r[AVR8_REGIDX_PORTC] = data; break; - case AVR8_REGIDX_PORTD: + case AVR8_REGIDX_PORTD: m_io->write_byte(0x03, data); m_r[AVR8_REGIDX_PORTD] = data; break; @@ -1824,17 +1824,17 @@ WRITE8_MEMBER( avr8_device::regs_w ) break; } - default: + default: verboselog(m_pc, 0, "AVR8: Unknown Register Write: %02x = %02x\n", (UINT8)offset, data); break; - } + } } READ8_MEMBER( avr8_device::regs_r ) { //printf("offset %04x\n", offset); - switch( offset ) - { + switch( offset ) + { case AVR8_REGIDX_R0: case AVR8_REGIDX_R1: case AVR8_REGIDX_R2: @@ -1899,10 +1899,10 @@ READ8_MEMBER( avr8_device::regs_r ) case AVR8_REGIDX_PIND: return m_io->read_byte(AVR8_REG_D); - default: + default: verboselog(m_pc, 0, "AVR8: Unknown Register Read: %02x\n", (UINT8)offset); - return 0; - } + return 0; + } } @@ -1955,48 +1955,48 @@ void avr8_device::execute_set_input(int inputnum, int state) void avr8_device::execute_run() { - UINT32 op = 0; - INT32 offs = 0; - UINT8 rd = 0; - UINT8 rr = 0; - UINT8 res = 0; - UINT16 pd = 0; - INT16 sd = 0; - INT32 opcycles = 1; - - while (m_icount > 0) - { + UINT32 op = 0; + INT32 offs = 0; + UINT8 rd = 0; + UINT8 rr = 0; + UINT8 res = 0; + UINT16 pd = 0; + INT16 sd = 0; + INT32 opcycles = 1; + + while (m_icount > 0) + { opcycles = 1; - m_pc &= m_addr_mask; - m_shifted_pc &= (m_addr_mask << 1) | 1; - - debugger_instruction_hook(this, m_shifted_pc); - - op = (UINT32)m_program->read_word(m_shifted_pc); - - switch(op & 0xf000) - { - case 0x0000: - switch(op & 0x0f00) - { - case 0x0000: // NOP - break; - case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd - m_r[(RD4(op) << 1) + 1] = m_r[(RR4(op) << 1) + 1]; - m_r[RD4(op) << 1] = m_r[RR4(op) << 1]; - break; - case 0x0200: // MULS Rd,Rr - sd = (INT8)m_r[16 + RD4(op)] * (INT8)m_r[16 + RR4(op)]; - m_r[1] = (sd >> 8) & 0x00ff; - m_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: // Multiplicatn - switch(MULCONST2(op)) - { + m_pc &= m_addr_mask; + m_shifted_pc &= (m_addr_mask << 1) | 1; + + debugger_instruction_hook(this, m_shifted_pc); + + op = (UINT32)m_program->read_word(m_shifted_pc); + + switch(op & 0xf000) + { + case 0x0000: + switch(op & 0x0f00) + { + case 0x0000: // NOP + break; + case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd + m_r[(RD4(op) << 1) + 1] = m_r[(RR4(op) << 1) + 1]; + m_r[RD4(op) << 1] = m_r[RR4(op) << 1]; + break; + case 0x0200: // MULS Rd,Rr + sd = (INT8)m_r[16 + RD4(op)] * (INT8)m_r[16 + RR4(op)]; + m_r[1] = (sd >> 8) & 0x00ff; + m_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: // Multiplicatn + switch(MULCONST2(op)) + { case 0x0000: // MULSU Rd,Rr sd = (INT8)m_r[16 + RD3(op)] * (UINT8)m_r[16 + RR3(op)]; m_r[1] = (sd >> 8) & 0x00ff; @@ -2033,869 +2033,869 @@ void avr8_device::execute_run() opcycles = 2; break; } - break; - case 0x0400: - case 0x0500: - case 0x0600: - case 0x0700: // CPC Rd,Rr - rd = m_r[RD5(op)]; - rr = m_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))); - 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) ? SREG_R(AVR8_SREG_Z) : 0); - 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: - case 0x0900: - case 0x0a00: - case 0x0b00: // SBC Rd,Rr - rd = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - res = rd - (rr + SREG_R(AVR8_SREG_C)); - m_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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0); - 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: - case 0x0d00: - case 0x0e00: - case 0x0f00: // ADD Rd,Rr - rd = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - res = rd + rr; - m_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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - SREG_W(AVR8_SREG_C, (BIT(rd,7) & BIT(rr,7)) | (BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(res,7)) & BIT(rd,7))); - break; - } - break; - case 0x1000: - switch(op & 0x0c00) - { - case 0x0000: // CPSE Rd,Rr - rd = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - if (rd == rr) - { - op = (UINT32)m_program->read_word(m_shifted_pc + 2); - opcycles += is_long_opcode(op) ? 2 : 1; - m_pc += is_long_opcode(op) ? 2 : 1; + break; + case 0x0400: + case 0x0500: + case 0x0600: + case 0x0700: // CPC Rd,Rr + rd = m_r[RD5(op)]; + rr = m_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))); + 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) ? SREG_R(AVR8_SREG_Z) : 0); + 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: + case 0x0900: + case 0x0a00: + case 0x0b00: // SBC Rd,Rr + rd = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + res = rd - (rr + SREG_R(AVR8_SREG_C)); + m_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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0); + 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: + case 0x0d00: + case 0x0e00: + case 0x0f00: // ADD Rd,Rr + rd = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + res = rd + rr; + m_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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_C, (BIT(rd,7) & BIT(rr,7)) | (BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(res,7)) & BIT(rd,7))); + break; + } + break; + case 0x1000: + switch(op & 0x0c00) + { + case 0x0000: // CPSE Rd,Rr + rd = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + if (rd == rr) + { + op = (UINT32)m_program->read_word(m_shifted_pc + 2); + opcycles += is_long_opcode(op) ? 2 : 1; + m_pc += is_long_opcode(op) ? 2 : 1; } - break; - case 0x0400: // CP Rd,Rr - rd = m_r[RD5(op)]; - rr = m_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))); - 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); - 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 = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - res = rd - rr; - m_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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - 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 = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - res = rd + rr + SREG_R(AVR8_SREG_C); - m_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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - SREG_W(AVR8_SREG_C, (BIT(rd,7) & BIT(rr,7)) | (BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(res,7)) & BIT(rd,7))); - break; - } - break; - case 0x2000: - switch(op & 0x0c00) - { - case 0x0000: // AND Rd,Rr - rd = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - rd &= rr; - SREG_W(AVR8_SREG_V, 0); - SREG_W(AVR8_SREG_N, BIT(rd,7)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - m_r[RD5(op)] = rd; - break; - case 0x0400: // EOR Rd,Rr - rd = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - rd ^= rr; - SREG_W(AVR8_SREG_V, 0); - SREG_W(AVR8_SREG_N, BIT(rd,7)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - m_r[RD5(op)] = rd; - break; - case 0x0800: // OR Rd,Rr - rd = m_r[RD5(op)]; - rr = m_r[RR5(op)]; - rd |= rr; - SREG_W(AVR8_SREG_V, 0); - SREG_W(AVR8_SREG_N, BIT(rd,7)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - m_r[RD5(op)] = rd; - break; - case 0x0c00: // MOV Rd,Rr - m_r[RD5(op)] = m_r[RR5(op)]; - break; - } - break; - case 0x3000: // CPI Rd,K - rd = m_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)))); - 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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - 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 = m_r[16 + RD4(op)]; - rr = KCONST8(op); - res = rd - (rr + SREG_R(AVR8_SREG_C)); - m_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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0); - 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 = m_r[16 + RD4(op)]; - rr = KCONST8(op); - res = rd - rr; - m_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)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - 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 = m_r[16 + RD4(op)]; - rr = KCONST8(op); - rd |= rr; - SREG_W(AVR8_SREG_V, 0); - SREG_W(AVR8_SREG_N, BIT(rd,7)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - m_r[16 + RD4(op)] = rd; - break; - case 0x7000: // ANDI Rd,K - rd = m_r[16 + RD4(op)]; - rr = KCONST8(op); - rd &= rr; - SREG_W(AVR8_SREG_V, 0); - SREG_W(AVR8_SREG_N, BIT(rd,7)); - SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); - SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); - m_r[16 + RD4(op)] = rd; - break; - case 0x8000: - case 0xa000: - switch(op & 0x0208) - { - case 0x0000: // LDD Rd,Z+q - m_r[RD5(op)] = m_data->read_byte(ZREG + QCONST6(op)); - opcycles = 2; - break; - case 0x0008: // LDD Rd,Y+q - m_r[RD5(op)] = m_data->read_byte(YREG + QCONST6(op)); - opcycles = 2; - break; - case 0x0200: // STD Z+q,Rr - m_data->write_byte(ZREG + QCONST6(op), m_r[RD5(op)]); - opcycles = 2; - break; - case 0x0208: // STD Y+q,Rr - m_data->write_byte(YREG + QCONST6(op), m_r[RD5(op)]); - opcycles = 2; - break; - } - break; - case 0x9000: - switch(op & 0x0f00) - { - case 0x0000: - case 0x0100: - switch(op & 0x000f) - { - case 0x0000: // LDS Rd,k - op <<= 16; - m_pc++; - m_shifted_pc += 2; - op |= m_program->read_word(m_shifted_pc); - m_r[RD5(op >> 16)] = m_data->read_byte(op & 0x0000ffff); - opcycles = 2; - break; - case 0x0001: // LD Rd,Z+ - pd = ZREG; - m_r[RD5(op)] = m_data->read_byte(pd); - pd++; - m_r[31] = (pd >> 8) & 0x00ff; - m_r[30] = pd & 0x00ff; - opcycles = 2; - break; - case 0x0002: // LD Rd,-Z - pd = ZREG; - pd--; - m_r[RD5(op)] = m_data->read_byte(pd); - m_r[31] = (pd >> 8) & 0x00ff; - m_r[30] = pd & 0x00ff; - opcycles = 2; - break; - case 0x0004: // LPM Rd,Z - m_r[RD5(op)] = m_program->read_byte(ZREG); - opcycles = 3; - break; - case 0x0005: // LPM Rd,Z+ - pd = ZREG; - m_r[RD5(op)] = m_program->read_byte(pd); - pd++; - m_r[31] = (pd >> 8) & 0x00ff; - m_r[30] = pd & 0x00ff; - opcycles = 3; - break; - case 0x0006: // ELPM Rd,Z - //output += sprintf( output, "ELPM R%d, Z", RD5(op) ); - unimplemented_opcode(op); - break; - case 0x0007: // ELPM Rd,Z+ - //output += sprintf( output, "ELPM R%d, Z+", RD5(op) ); - unimplemented_opcode(op); - break; - case 0x0009: // LD Rd,Y+ - pd = YREG; - m_r[RD5(op)] = m_data->read_byte(pd); - pd++; - m_r[29] = (pd >> 8) & 0x00ff; - m_r[28] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000a: // LD Rd,-Y - pd = YREG; - pd--; - m_r[RD5(op)] = m_data->read_byte(pd); - m_r[29] = (pd >> 8) & 0x00ff; - m_r[28] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000c: // LD Rd,X - m_r[RD5(op)] = m_data->read_byte(XREG); - opcycles = 2; - break; - case 0x000d: // LD Rd,X+ - pd = XREG; - m_r[RD5(op)] = m_data->read_byte(pd); - pd++; - m_r[27] = (pd >> 8) & 0x00ff; - m_r[26] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000e: // LD Rd,-X - pd = XREG; - pd--; - m_r[RD5(op)] = m_data->read_byte(pd); - m_r[27] = (pd >> 8) & 0x00ff; - m_r[26] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000f: // POP Rd - m_r[RD5(op)] = pop(); - opcycles = 2; - break; - default: - unimplemented_opcode(op); - //output += sprintf( output, "Undefined (%04x)", op ); - break; - } - break; - case 0x0200: - case 0x0300: - switch(op & 0x000f) - { - case 0x0000: // STS k,Rr - op <<= 16; - m_pc++; - m_shifted_pc += 2; - op |= m_program->read_word(m_shifted_pc); - m_data->write_byte(op & 0x0000ffff, m_r[RD5(op >> 16)]); - opcycles = 2; - break; - case 0x0001: // ST Z+,Rd - pd = ZREG; - m_data->write_byte(pd, m_r[RD5(op)]); - pd++; - m_r[31] = (pd >> 8) & 0x00ff; - m_r[30] = pd & 0x00ff; - opcycles = 2; - break; - case 0x0002: // ST -Z,Rd - pd = ZREG; - pd--; - m_data->write_byte(pd, m_r[RD5(op)]); - m_r[31] = (pd >> 8) & 0x00ff; - m_r[30] = pd & 0x00ff; - opcycles = 2; - break; - case 0x0009: // ST Y+,Rd - pd = YREG; - m_data->write_byte(pd, m_r[RD5(op)]); - pd++; - m_r[29] = (pd >> 8) & 0x00ff; - m_r[28] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000a: // ST -Y,Rd - pd = YREG; - pd--; - m_data->write_byte(pd, m_r[RD5(op)]); - m_r[29] = (pd >> 8) & 0x00ff; - m_r[28] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000c: // ST X,Rd - m_data->write_byte(XREG, m_r[RD5(op)]); - break; - case 0x000d: // ST X+,Rd - pd = XREG; - m_data->write_byte(pd, m_r[RD5(op)]); - pd++; - m_r[27] = (pd >> 8) & 0x00ff; - m_r[26] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000e: // ST -X,Rd - pd = XREG; - pd--; - m_data->write_byte(pd, m_r[RD5(op)]); - m_r[27] = (pd >> 8) & 0x00ff; - m_r[26] = pd & 0x00ff; - opcycles = 2; - break; - case 0x000f: // PUSH Rd - push(m_r[RD5(op)]); - opcycles = 2; - break; - default: - unimplemented_opcode(op); - //output += sprintf( output, "Undefined (%04x)", op ); - break; - } - break; - case 0x0400: - switch(op & 0x000f) - { - case 0x0000: // COM Rd - rd = m_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)); - m_r[RD5(op)] = res; - break; - case 0x0001: // NEG Rd - rd = m_r[RD5(op)]; - res = 0 - rd; - SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - SREG_W(AVR8_SREG_N, BIT(res,7)); - 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)); - m_r[RD5(op)] = res; - break; - case 0x0002: // SWAP Rd - rd = m_r[RD5(op)]; - m_r[RD5(op)] = (rd >> 4) | (rd << 4); - break; - case 0x0003: // INC Rd - rd = m_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); - m_r[RD5(op)] = res; - break; - case 0x0005: // ASR Rd - rd = m_r[RD5(op)]; - res = (rd & 0x80) | (rd >> 1); - SREG_W(AVR8_SREG_C, BIT(rd,0)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - SREG_W(AVR8_SREG_N, BIT(rd,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)); - m_r[RD5(op)] = res; - break; - case 0x0006: // LSR Rd - rd = m_r[RD5(op)]; - res = rd >> 1; - SREG_W(AVR8_SREG_C, BIT(rd,0)); - 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)); - m_r[RD5(op)] = res; - break; - case 0x0007: // ROR Rd - rd = m_r[RD5(op)]; - res = rd >> 1; - res |= (SREG_R(AVR8_SREG_C) << 7); - SREG_W(AVR8_SREG_C, BIT(rd,0)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); - SREG_W(AVR8_SREG_N, BIT(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)); - m_r[RD5(op)] = res; - break; - case 0x0008: - switch(op & 0x00f0) - { - case 0x0000: // SEC - case 0x0010: // SEZ - case 0x0020: // SEN - case 0x0030: // SEV - case 0x0040: // SES - case 0x0050: // SEH - case 0x0060: // SET - case 0x0070: // SEI - SREG_W((op >> 4) & 0x07, 1); - break; - case 0x0080: // CLC - case 0x0090: // CLZ - case 0x00a0: // CLN - case 0x00b0: // CLV - case 0x00c0: // CLS - case 0x00d0: // CLH - case 0x00e0: // CLT - case 0x00f0: // CLI - SREG_W((op >> 4) & 0x07, 0); - break; - } - break; - case 0x0009: - switch(op & 0x00f0) - { - case 0x0000: // IJMP - m_pc = ZREG - 1; - opcycles = 2; - break; - case 0x0010: // EIJMP - //output += sprintf( output, "EIJMP" ); - unimplemented_opcode(op); - break; - default: - //output += sprintf( output, "Undefined (%04x)", op ); - unimplemented_opcode(op); - break; - } - break; - case 0x000a: // DEC Rd - rd = m_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); - m_r[RD5(op)] = res; - break; - case 0x000c: - case 0x000d: // JMP k + break; + case 0x0400: // CP Rd,Rr + rd = m_r[RD5(op)]; + rr = m_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))); + 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); + 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 = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + res = rd - rr; + m_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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + 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 = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + res = rd + rr + SREG_R(AVR8_SREG_C); + m_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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_C, (BIT(rd,7) & BIT(rr,7)) | (BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(res,7)) & BIT(rd,7))); + break; + } + break; + case 0x2000: + switch(op & 0x0c00) + { + case 0x0000: // AND Rd,Rr + rd = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + rd &= rr; + SREG_W(AVR8_SREG_V, 0); + SREG_W(AVR8_SREG_N, BIT(rd,7)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); + m_r[RD5(op)] = rd; + break; + case 0x0400: // EOR Rd,Rr + rd = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + rd ^= rr; + SREG_W(AVR8_SREG_V, 0); + SREG_W(AVR8_SREG_N, BIT(rd,7)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); + m_r[RD5(op)] = rd; + break; + case 0x0800: // OR Rd,Rr + rd = m_r[RD5(op)]; + rr = m_r[RR5(op)]; + rd |= rr; + SREG_W(AVR8_SREG_V, 0); + SREG_W(AVR8_SREG_N, BIT(rd,7)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); + m_r[RD5(op)] = rd; + break; + case 0x0c00: // MOV Rd,Rr + m_r[RD5(op)] = m_r[RR5(op)]; + break; + } + break; + case 0x3000: // CPI Rd,K + rd = m_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)))); + 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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + 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 = m_r[16 + RD4(op)]; + rr = KCONST8(op); + res = rd - (rr + SREG_R(AVR8_SREG_C)); + m_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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0); + 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 = m_r[16 + RD4(op)]; + rr = KCONST8(op); + res = rd - rr; + m_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)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + 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 = m_r[16 + RD4(op)]; + rr = KCONST8(op); + rd |= rr; + SREG_W(AVR8_SREG_V, 0); + SREG_W(AVR8_SREG_N, BIT(rd,7)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); + m_r[16 + RD4(op)] = rd; + break; + case 0x7000: // ANDI Rd,K + rd = m_r[16 + RD4(op)]; + rr = KCONST8(op); + rd &= rr; + SREG_W(AVR8_SREG_V, 0); + SREG_W(AVR8_SREG_N, BIT(rd,7)); + SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); + SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0); + m_r[16 + RD4(op)] = rd; + break; + case 0x8000: + case 0xa000: + switch(op & 0x0208) + { + case 0x0000: // LDD Rd,Z+q + m_r[RD5(op)] = m_data->read_byte(ZREG + QCONST6(op)); + opcycles = 2; + break; + case 0x0008: // LDD Rd,Y+q + m_r[RD5(op)] = m_data->read_byte(YREG + QCONST6(op)); + opcycles = 2; + break; + case 0x0200: // STD Z+q,Rr + m_data->write_byte(ZREG + QCONST6(op), m_r[RD5(op)]); + opcycles = 2; + break; + case 0x0208: // STD Y+q,Rr + m_data->write_byte(YREG + QCONST6(op), m_r[RD5(op)]); + opcycles = 2; + break; + } + break; + case 0x9000: + switch(op & 0x0f00) + { + case 0x0000: + case 0x0100: + switch(op & 0x000f) + { + case 0x0000: // LDS Rd,k + op <<= 16; + m_pc++; + m_shifted_pc += 2; + op |= m_program->read_word(m_shifted_pc); + m_r[RD5(op >> 16)] = m_data->read_byte(op & 0x0000ffff); + opcycles = 2; + break; + case 0x0001: // LD Rd,Z+ + pd = ZREG; + m_r[RD5(op)] = m_data->read_byte(pd); + pd++; + m_r[31] = (pd >> 8) & 0x00ff; + m_r[30] = pd & 0x00ff; + opcycles = 2; + break; + case 0x0002: // LD Rd,-Z + pd = ZREG; + pd--; + m_r[RD5(op)] = m_data->read_byte(pd); + m_r[31] = (pd >> 8) & 0x00ff; + m_r[30] = pd & 0x00ff; + opcycles = 2; + break; + case 0x0004: // LPM Rd,Z + m_r[RD5(op)] = m_program->read_byte(ZREG); + opcycles = 3; + break; + case 0x0005: // LPM Rd,Z+ + pd = ZREG; + m_r[RD5(op)] = m_program->read_byte(pd); + pd++; + m_r[31] = (pd >> 8) & 0x00ff; + m_r[30] = pd & 0x00ff; + opcycles = 3; + break; + case 0x0006: // ELPM Rd,Z + //output += sprintf( output, "ELPM R%d, Z", RD5(op) ); + unimplemented_opcode(op); + break; + case 0x0007: // ELPM Rd,Z+ + //output += sprintf( output, "ELPM R%d, Z+", RD5(op) ); + unimplemented_opcode(op); + break; + case 0x0009: // LD Rd,Y+ + pd = YREG; + m_r[RD5(op)] = m_data->read_byte(pd); + pd++; + m_r[29] = (pd >> 8) & 0x00ff; + m_r[28] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000a: // LD Rd,-Y + pd = YREG; + pd--; + m_r[RD5(op)] = m_data->read_byte(pd); + m_r[29] = (pd >> 8) & 0x00ff; + m_r[28] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000c: // LD Rd,X + m_r[RD5(op)] = m_data->read_byte(XREG); + opcycles = 2; + break; + case 0x000d: // LD Rd,X+ + pd = XREG; + m_r[RD5(op)] = m_data->read_byte(pd); + pd++; + m_r[27] = (pd >> 8) & 0x00ff; + m_r[26] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000e: // LD Rd,-X + pd = XREG; + pd--; + m_r[RD5(op)] = m_data->read_byte(pd); + m_r[27] = (pd >> 8) & 0x00ff; + m_r[26] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000f: // POP Rd + m_r[RD5(op)] = pop(); + opcycles = 2; + break; + default: + unimplemented_opcode(op); + //output += sprintf( output, "Undefined (%04x)", op ); + break; + } + break; + case 0x0200: + case 0x0300: + switch(op & 0x000f) + { + case 0x0000: // STS k,Rr + op <<= 16; + m_pc++; + m_shifted_pc += 2; + op |= m_program->read_word(m_shifted_pc); + m_data->write_byte(op & 0x0000ffff, m_r[RD5(op >> 16)]); + opcycles = 2; + break; + case 0x0001: // ST Z+,Rd + pd = ZREG; + m_data->write_byte(pd, m_r[RD5(op)]); + pd++; + m_r[31] = (pd >> 8) & 0x00ff; + m_r[30] = pd & 0x00ff; + opcycles = 2; + break; + case 0x0002: // ST -Z,Rd + pd = ZREG; + pd--; + m_data->write_byte(pd, m_r[RD5(op)]); + m_r[31] = (pd >> 8) & 0x00ff; + m_r[30] = pd & 0x00ff; + opcycles = 2; + break; + case 0x0009: // ST Y+,Rd + pd = YREG; + m_data->write_byte(pd, m_r[RD5(op)]); + pd++; + m_r[29] = (pd >> 8) & 0x00ff; + m_r[28] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000a: // ST -Y,Rd + pd = YREG; + pd--; + m_data->write_byte(pd, m_r[RD5(op)]); + m_r[29] = (pd >> 8) & 0x00ff; + m_r[28] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000c: // ST X,Rd + m_data->write_byte(XREG, m_r[RD5(op)]); + break; + case 0x000d: // ST X+,Rd + pd = XREG; + m_data->write_byte(pd, m_r[RD5(op)]); + pd++; + m_r[27] = (pd >> 8) & 0x00ff; + m_r[26] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000e: // ST -X,Rd + pd = XREG; + pd--; + m_data->write_byte(pd, m_r[RD5(op)]); + m_r[27] = (pd >> 8) & 0x00ff; + m_r[26] = pd & 0x00ff; + opcycles = 2; + break; + case 0x000f: // PUSH Rd + push(m_r[RD5(op)]); + opcycles = 2; + break; + default: + unimplemented_opcode(op); + //output += sprintf( output, "Undefined (%04x)", op ); + break; + } + break; + case 0x0400: + switch(op & 0x000f) + { + case 0x0000: // COM Rd + rd = m_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)); + m_r[RD5(op)] = res; + break; + case 0x0001: // NEG Rd + rd = m_r[RD5(op)]; + res = 0 - rd; + SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_N, BIT(res,7)); + 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)); + m_r[RD5(op)] = res; + break; + case 0x0002: // SWAP Rd + rd = m_r[RD5(op)]; + m_r[RD5(op)] = (rd >> 4) | (rd << 4); + break; + case 0x0003: // INC Rd + rd = m_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); + m_r[RD5(op)] = res; + break; + case 0x0005: // ASR Rd + rd = m_r[RD5(op)]; + res = (rd & 0x80) | (rd >> 1); + SREG_W(AVR8_SREG_C, BIT(rd,0)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_N, BIT(rd,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)); + m_r[RD5(op)] = res; + break; + case 0x0006: // LSR Rd + rd = m_r[RD5(op)]; + res = rd >> 1; + SREG_W(AVR8_SREG_C, BIT(rd,0)); + 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)); + m_r[RD5(op)] = res; + break; + case 0x0007: // ROR Rd + rd = m_r[RD5(op)]; + res = rd >> 1; + res |= (SREG_R(AVR8_SREG_C) << 7); + SREG_W(AVR8_SREG_C, BIT(rd,0)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); + SREG_W(AVR8_SREG_N, BIT(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)); + m_r[RD5(op)] = res; + break; + case 0x0008: + switch(op & 0x00f0) + { + case 0x0000: // SEC + case 0x0010: // SEZ + case 0x0020: // SEN + case 0x0030: // SEV + case 0x0040: // SES + case 0x0050: // SEH + case 0x0060: // SET + case 0x0070: // SEI + SREG_W((op >> 4) & 0x07, 1); + break; + case 0x0080: // CLC + case 0x0090: // CLZ + case 0x00a0: // CLN + case 0x00b0: // CLV + case 0x00c0: // CLS + case 0x00d0: // CLH + case 0x00e0: // CLT + case 0x00f0: // CLI + SREG_W((op >> 4) & 0x07, 0); + break; + } + break; + case 0x0009: + switch(op & 0x00f0) + { + case 0x0000: // IJMP + m_pc = ZREG - 1; + opcycles = 2; + break; + case 0x0010: // EIJMP + //output += sprintf( output, "EIJMP" ); + unimplemented_opcode(op); + break; + default: + //output += sprintf( output, "Undefined (%04x)", op ); + unimplemented_opcode(op); + break; + } + break; + case 0x000a: // DEC Rd + rd = m_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); + m_r[RD5(op)] = res; + break; + case 0x000c: + case 0x000d: // JMP k offs = KCONST22(op) << 16; - m_pc++; - m_shifted_pc += 2; - offs |= m_program->read_word(m_shifted_pc); - m_pc = offs; + m_pc++; + m_shifted_pc += 2; + offs |= m_program->read_word(m_shifted_pc); + m_pc = offs; m_pc--; opcycles = 3; - break; - case 0x000e: // CALL k - case 0x000f: + break; + case 0x000e: // CALL k + case 0x000f: push((m_pc + 2) & 0x00ff); push(((m_pc + 2) >> 8) & 0x00ff); offs = KCONST22(op) << 16; - m_pc++; - m_shifted_pc += 2; - offs |= m_program->read_word(m_shifted_pc); - m_pc = offs; + m_pc++; + m_shifted_pc += 2; + offs |= m_program->read_word(m_shifted_pc); + m_pc = offs; m_pc--; opcycles = 4; - break; - default: - unimplemented_opcode(op); - //output += sprintf( output, "Undefined (%04x)", op ); - break; - } - break; - case 0x0500: - switch(op & 0x000f) - { - case 0x0000: // COM Rd - rd = m_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)); - m_r[RD5(op)] = res; - break; - case 0x0001: // NEG Rd - rd = m_r[RD5(op)]; - res = 0 - rd; - SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - SREG_W(AVR8_SREG_N, BIT(res,7)); - 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)); - m_r[RD5(op)] = res; - break; - case 0x0002: // SWAP Rd - rd = m_r[RD5(op)]; - m_r[RD5(op)] = (rd >> 4) | (rd << 4); - break; - case 0x0003: // INC Rd - rd = m_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); - m_r[RD5(op)] = res; - break; - case 0x0005: // ASR Rd - rd = m_r[RD5(op)]; - res = (rd & 0x80) | (rd >> 1); - SREG_W(AVR8_SREG_C, BIT(rd,0)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); - SREG_W(AVR8_SREG_N, BIT(rd,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)); - m_r[RD5(op)] = res; - break; - case 0x0006: // LSR Rd - rd = m_r[RD5(op)]; - res = rd >> 1; - SREG_W(AVR8_SREG_C, BIT(rd,0)); - 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)); - m_r[RD5(op)] = res; - break; - case 0x0007: // ROR Rd - rd = m_r[RD5(op)]; - res = rd >> 1; - res |= (SREG_R(AVR8_SREG_C) << 7); - SREG_W(AVR8_SREG_C, BIT(rd,0)); - SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); - SREG_W(AVR8_SREG_N, BIT(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)); - m_r[RD5(op)] = res; - break; - case 0x0008: - switch(op & 0x00f0) - { - case 0x0000: // RET - m_pc = pop() << 8; - m_pc |= pop(); - m_pc--; - opcycles = 4; - break; - case 0x0010: // RETI - m_pc = pop() << 8; - m_pc |= pop(); - m_pc--; - SREG_W(AVR8_SREG_I, 1); - opcycles = 4; - break; - case 0x0080: // SLEEP - //output += sprintf( output, "SLEEP" ); - unimplemented_opcode(op); - break; - case 0x0090: // BREAK - //output += sprintf( output, "BREAK" ); - unimplemented_opcode(op); - break; - case 0x00a0: // WDR - //output += sprintf( output, "WDR" ); - unimplemented_opcode(op); - break; - case 0x00c0: // LPM - m_r[0] = m_program->read_byte(ZREG); - opcycles = 3; - break; - case 0x00d0: // ELPM - //output += sprintf( output, "ELPM" ); - unimplemented_opcode(op); - break; - case 0x00e0: // SPM - //output += sprintf( output, "SPM" ); - unimplemented_opcode(op); - break; - case 0x00f0: // SPM Z+ - //output += sprintf( output, "SPM Z+" ); - unimplemented_opcode(op); - break; - default: - unimplemented_opcode(op); - //output += sprintf( output, "Undefined (%04x)", op ); - break; - } - break; - case 0x0009: - switch(op & 0x00f0) - { - case 0x0000: // ICALL - push((m_pc + 1) & 0x00ff); - push(((m_pc + 1) >> 8) & 0x00ff); - m_pc = ZREG; - m_pc--; - opcycles = 3; - break; - case 0x0010: // EICALL - //output += sprintf( output, "EICALL" ); - unimplemented_opcode(op); - break; - default: - unimplemented_opcode(op); - //output += sprintf( output, "Undefined (%04x)", op ); - break; - } - break; - case 0x000a: // DEC Rd - rd = m_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); - m_r[RD5(op)] = res; - break; - case 0x000c: - case 0x000d: // JMP k - //op <<= 8; - //op |= oprom[pos++]; - //op <<= 8; - //op |= oprom[pos++]; - //output += sprintf( output, "JMP 0x%06x", KCONST22(op) ); - unimplemented_opcode(op); - break; - case 0x000e: - case 0x000f: // CALL k - //op <<= 8; - //op |= oprom[pos++]; - //op <<= 8; - //op |= oprom[pos++]; - //output += sprintf( output, "CALL 0x%06x", KCONST22(op) ); - unimplemented_opcode(op); - break; - } - break; - case 0x0600: // ADIW Rd+1:Rd,K - rd = m_r[24 + (DCONST(op) << 1)]; - rr = m_r[25 + (DCONST(op) << 1)]; - pd = rd; - pd |= rr << 8; - pd += KCONST6(op); - SREG_W(AVR8_SREG_V, BIT(pd,15) & NOT(BIT(rr,7))); - SREG_W(AVR8_SREG_N, BIT(pd,15)); - 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)); - m_r[24 + (DCONST(op) << 1)] = pd & 0x00ff; - m_r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff; - opcycles = 2; - break; - case 0x0700: // SBIW Rd+1:Rd,K - rd = m_r[24 + (DCONST(op) << 1)]; - rr = m_r[25 + (DCONST(op) << 1)]; - pd = rd; - pd |= rr << 8; - pd -= KCONST6(op); - SREG_W(AVR8_SREG_V, NOT(BIT(pd,15)) & BIT(rr,7)); - SREG_W(AVR8_SREG_N, BIT(pd,15)); - 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, BIT(pd,15) & NOT(BIT(rr,7))); - m_r[24 + (DCONST(op) << 1)] = pd & 0x00ff; - m_r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff; - opcycles = 2; - break; - case 0x0800: // CBI A,b - //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) ); - m_data->write_byte(32 + ACONST5(op), m_data->read_byte(32 + ACONST5(op)) &~ (1 << RR3(op))); - opcycles = 2; - break; - case 0x0900: // SBIC A,b - if(NOT(BIT(m_data->read_byte(32 + ACONST5(op)), RR3(op)))) - { - op = (UINT32)m_program->read_word(m_shifted_pc + 2); + break; + default: + unimplemented_opcode(op); + //output += sprintf( output, "Undefined (%04x)", op ); + break; + } + break; + case 0x0500: + switch(op & 0x000f) + { + case 0x0000: // COM Rd + rd = m_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)); + m_r[RD5(op)] = res; + break; + case 0x0001: // NEG Rd + rd = m_r[RD5(op)]; + res = 0 - rd; + SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_N, BIT(res,7)); + 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)); + m_r[RD5(op)] = res; + break; + case 0x0002: // SWAP Rd + rd = m_r[RD5(op)]; + m_r[RD5(op)] = (rd >> 4) | (rd << 4); + break; + case 0x0003: // INC Rd + rd = m_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); + m_r[RD5(op)] = res; + break; + case 0x0005: // ASR Rd + rd = m_r[RD5(op)]; + res = (rd & 0x80) | (rd >> 1); + SREG_W(AVR8_SREG_C, BIT(rd,0)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0); + SREG_W(AVR8_SREG_N, BIT(rd,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)); + m_r[RD5(op)] = res; + break; + case 0x0006: // LSR Rd + rd = m_r[RD5(op)]; + res = rd >> 1; + SREG_W(AVR8_SREG_C, BIT(rd,0)); + 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)); + m_r[RD5(op)] = res; + break; + case 0x0007: // ROR Rd + rd = m_r[RD5(op)]; + res = rd >> 1; + res |= (SREG_R(AVR8_SREG_C) << 7); + SREG_W(AVR8_SREG_C, BIT(rd,0)); + SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0); + SREG_W(AVR8_SREG_N, BIT(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)); + m_r[RD5(op)] = res; + break; + case 0x0008: + switch(op & 0x00f0) + { + case 0x0000: // RET + m_pc = pop() << 8; + m_pc |= pop(); + m_pc--; + opcycles = 4; + break; + case 0x0010: // RETI + m_pc = pop() << 8; + m_pc |= pop(); + m_pc--; + SREG_W(AVR8_SREG_I, 1); + opcycles = 4; + break; + case 0x0080: // SLEEP + //output += sprintf( output, "SLEEP" ); + unimplemented_opcode(op); + break; + case 0x0090: // BREAK + //output += sprintf( output, "BREAK" ); + unimplemented_opcode(op); + break; + case 0x00a0: // WDR + //output += sprintf( output, "WDR" ); + unimplemented_opcode(op); + break; + case 0x00c0: // LPM + m_r[0] = m_program->read_byte(ZREG); + opcycles = 3; + break; + case 0x00d0: // ELPM + //output += sprintf( output, "ELPM" ); + unimplemented_opcode(op); + break; + case 0x00e0: // SPM + //output += sprintf( output, "SPM" ); + unimplemented_opcode(op); + break; + case 0x00f0: // SPM Z+ + //output += sprintf( output, "SPM Z+" ); + unimplemented_opcode(op); + break; + default: + unimplemented_opcode(op); + //output += sprintf( output, "Undefined (%04x)", op ); + break; + } + break; + case 0x0009: + switch(op & 0x00f0) + { + case 0x0000: // ICALL + push((m_pc + 1) & 0x00ff); + push(((m_pc + 1) >> 8) & 0x00ff); + m_pc = ZREG; + m_pc--; + opcycles = 3; + break; + case 0x0010: // EICALL + //output += sprintf( output, "EICALL" ); + unimplemented_opcode(op); + break; + default: + unimplemented_opcode(op); + //output += sprintf( output, "Undefined (%04x)", op ); + break; + } + break; + case 0x000a: // DEC Rd + rd = m_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); + m_r[RD5(op)] = res; + break; + case 0x000c: + case 0x000d: // JMP k + //op <<= 8; + //op |= oprom[pos++]; + //op <<= 8; + //op |= oprom[pos++]; + //output += sprintf( output, "JMP 0x%06x", KCONST22(op) ); + unimplemented_opcode(op); + break; + case 0x000e: + case 0x000f: // CALL k + //op <<= 8; + //op |= oprom[pos++]; + //op <<= 8; + //op |= oprom[pos++]; + //output += sprintf( output, "CALL 0x%06x", KCONST22(op) ); + unimplemented_opcode(op); + break; + } + break; + case 0x0600: // ADIW Rd+1:Rd,K + rd = m_r[24 + (DCONST(op) << 1)]; + rr = m_r[25 + (DCONST(op) << 1)]; + pd = rd; + pd |= rr << 8; + pd += KCONST6(op); + SREG_W(AVR8_SREG_V, BIT(pd,15) & NOT(BIT(rr,7))); + SREG_W(AVR8_SREG_N, BIT(pd,15)); + 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)); + m_r[24 + (DCONST(op) << 1)] = pd & 0x00ff; + m_r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff; + opcycles = 2; + break; + case 0x0700: // SBIW Rd+1:Rd,K + rd = m_r[24 + (DCONST(op) << 1)]; + rr = m_r[25 + (DCONST(op) << 1)]; + pd = rd; + pd |= rr << 8; + pd -= KCONST6(op); + SREG_W(AVR8_SREG_V, NOT(BIT(pd,15)) & BIT(rr,7)); + SREG_W(AVR8_SREG_N, BIT(pd,15)); + 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, BIT(pd,15) & NOT(BIT(rr,7))); + m_r[24 + (DCONST(op) << 1)] = pd & 0x00ff; + m_r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff; + opcycles = 2; + break; + case 0x0800: // CBI A,b + //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) ); + m_data->write_byte(32 + ACONST5(op), m_data->read_byte(32 + ACONST5(op)) &~ (1 << RR3(op))); + opcycles = 2; + break; + case 0x0900: // SBIC A,b + if(NOT(BIT(m_data->read_byte(32 + ACONST5(op)), RR3(op)))) + { + op = (UINT32)m_program->read_word(m_shifted_pc + 2); opcycles = is_long_opcode(op) ? 3 : 2; - m_pc += is_long_opcode(op) ? 2 : 1; + m_pc += is_long_opcode(op) ? 2 : 1; } - break; - case 0x0a00: // SBI A,b - m_data->write_byte(32 + ACONST5(op), m_data->read_byte(32 + ACONST5(op)) | (1 << RR3(op))); - opcycles = 2; - break; - case 0x0b00: // SBIS A,b - if(BIT(m_data->read_byte(32 + ACONST5(op)), RR3(op))) - { - op = (UINT32)m_program->read_word(m_shifted_pc + 2); + break; + case 0x0a00: // SBI A,b + m_data->write_byte(32 + ACONST5(op), m_data->read_byte(32 + ACONST5(op)) | (1 << RR3(op))); + opcycles = 2; + break; + case 0x0b00: // SBIS A,b + if(BIT(m_data->read_byte(32 + ACONST5(op)), RR3(op))) + { + op = (UINT32)m_program->read_word(m_shifted_pc + 2); opcycles = is_long_opcode(op) ? 3 : 2; - m_pc += is_long_opcode(op) ? 2 : 1; + m_pc += is_long_opcode(op) ? 2 : 1; + } + break; + case 0x0c00: + case 0x0d00: + case 0x0e00: + case 0x0f00: // MUL Rd,Rr + sd = (UINT8)m_r[RD5(op)] * (UINT8)m_r[RR5(op)]; + m_r[1] = (sd >> 8) & 0x00ff; + m_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; + } + break; + case 0xb000: + if(op & 0x0800) // OUT A,Rr + { + m_data->write_byte(32 + ACONST6(op), m_r[RD5(op)]); + } + else // IN Rd,A + { + m_r[RD5(op)] = m_data->read_byte(0x20 + ACONST6(op)); + } + break; + case 0xc000: // RJMP k + offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)); + m_pc += offs; + opcycles = 2; + break; + case 0xd000: // RCALL k + offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)); + push((m_pc + 1) & 0x00ff); + push(((m_pc + 1) >> 8) & 0x00ff); + m_pc += offs; + opcycles = 3; + break; + case 0xe000: // LDI Rd,K + m_r[16 + RD4(op)] = KCONST8(op); + break; + case 0xf000: + switch(op & 0x0c00) + { + case 0x0000: // BRLO through BRIE + if(SREG_R(op & 0x0007)) + { + offs = (INT32)(KCONST7(op)); + if(offs & 0x40) + { + offs |= 0xffffff80; + } + m_pc += offs; + opcycles = 2; + } + break; + case 0x0400: // BRSH through BRID + if(SREG_R(op & 0x0007) == 0) + { + offs = (INT32)(KCONST7(op)); + if(offs & 0x40) + { + offs |= 0xffffff80; + } + m_pc += offs; + opcycles = 2; } - break; - case 0x0c00: - case 0x0d00: - case 0x0e00: - case 0x0f00: // MUL Rd,Rr - sd = (UINT8)m_r[RD5(op)] * (UINT8)m_r[RR5(op)]; - m_r[1] = (sd >> 8) & 0x00ff; - m_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; - } - break; - case 0xb000: - if(op & 0x0800) // OUT A,Rr - { - m_data->write_byte(32 + ACONST6(op), m_r[RD5(op)]); - } - else // IN Rd,A - { - m_r[RD5(op)] = m_data->read_byte(0x20 + ACONST6(op)); - } - break; - case 0xc000: // RJMP k - offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)); - m_pc += offs; - opcycles = 2; - break; - case 0xd000: // RCALL k - offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)); - push((m_pc + 1) & 0x00ff); - push(((m_pc + 1) >> 8) & 0x00ff); - m_pc += offs; - opcycles = 3; - break; - case 0xe000: // LDI Rd,K - m_r[16 + RD4(op)] = KCONST8(op); - break; - case 0xf000: - switch(op & 0x0c00) - { - case 0x0000: // BRLO through BRIE - if(SREG_R(op & 0x0007)) - { - offs = (INT32)(KCONST7(op)); - if(offs & 0x40) - { - offs |= 0xffffff80; - } - m_pc += offs; - opcycles = 2; - } - break; - case 0x0400: // BRSH through BRID - if(SREG_R(op & 0x0007) == 0) - { - offs = (INT32)(KCONST7(op)); - if(offs & 0x40) - { - offs |= 0xffffff80; - } - m_pc += offs; - opcycles = 2; - } - break; - case 0x0800: - if(op & 0x0200) // BST Rd, b - { - SREG_W(AVR8_SREG_T, (BIT(m_r[RD5(op)], RR3(op))) ? 1 : 0); - } - else // BLD Rd, b - { - if(SREG_R(AVR8_SREG_T)) - { - m_r[RD5(op)] |= (1 << RR3(op)); - } - else - { - m_r[RD5(op)] &= ~(1 << RR3(op)); - } - } - break; - case 0x0c00: - if(op & 0x0200) // SBRS Rd, b - { - if(BIT(m_r[RD5(op)], RR3(op))) - { - op = (UINT32)m_program->read_word(m_shifted_pc + 2); - m_pc += is_long_opcode(op) ? 2 : 1; - opcycles = is_long_opcode(op) ? 3 : 2; - } - } - else // SBRC Rd, b - { - if(NOT(BIT(m_r[RD5(op)], RR3(op)))) - { - op = (UINT32)m_program->read_word(m_shifted_pc + 2); - m_pc += is_long_opcode(op) ? 2 : 1; - opcycles = is_long_opcode(op) ? 3 : 2; - } - } - break; - } - break; - } - - m_pc++; - - m_shifted_pc = m_pc << 1; - - m_icount -= opcycles; + break; + case 0x0800: + if(op & 0x0200) // BST Rd, b + { + SREG_W(AVR8_SREG_T, (BIT(m_r[RD5(op)], RR3(op))) ? 1 : 0); + } + else // BLD Rd, b + { + if(SREG_R(AVR8_SREG_T)) + { + m_r[RD5(op)] |= (1 << RR3(op)); + } + else + { + m_r[RD5(op)] &= ~(1 << RR3(op)); + } + } + break; + case 0x0c00: + if(op & 0x0200) // SBRS Rd, b + { + if(BIT(m_r[RD5(op)], RR3(op))) + { + op = (UINT32)m_program->read_word(m_shifted_pc + 2); + m_pc += is_long_opcode(op) ? 2 : 1; + opcycles = is_long_opcode(op) ? 3 : 2; + } + } + else // SBRC Rd, b + { + if(NOT(BIT(m_r[RD5(op)], RR3(op)))) + { + op = (UINT32)m_program->read_word(m_shifted_pc + 2); + m_pc += is_long_opcode(op) ? 2 : 1; + opcycles = is_long_opcode(op) ? 3 : 2; + } + } + break; + } + break; + } + + m_pc++; + + m_shifted_pc = m_pc << 1; + + m_icount -= opcycles; timer_tick(opcycles); - } + } } |