From e04f490e4b0a7bc5ed9c212663facaf8195c96f4 Mon Sep 17 00:00:00 2001 From: Ryan Holtz Date: Tue, 14 Jul 2020 07:26:41 +0200 Subject: [PATCH] -avr8: Fixed assorted Timer 0 and Timer 1 bugs. [Ryan Holtz] -avr8dasm: Fixed erroneous disassembly of CBI, SBI, SBIS, and SBIC opcodes. [Ryan Holtz] New working machines -------------------- Power Ninja Action Challenge [Ryan Holtz] --- src/devices/cpu/avr8/avr8.cpp | 134 ++-- src/devices/cpu/avr8/avr8dasm.cpp | 1027 ++++++++++++++--------------- src/mame/drivers/craft.cpp | 250 ++++--- src/mame/mame.lst | 1 + 4 files changed, 742 insertions(+), 670 deletions(-) diff --git a/src/devices/cpu/avr8/avr8.cpp b/src/devices/cpu/avr8/avr8.cpp index 69096da7059..013ac8db6f6 100644 --- a/src/devices/cpu/avr8/avr8.cpp +++ b/src/devices/cpu/avr8/avr8.cpp @@ -92,7 +92,7 @@ #define LOG_TIMERS (LOG_TIMER0 | LOG_TIMER1 | LOG_TIMER2 | LOG_TIMER3 | LOG_TIMER4 | LOG_TIMER5) #define LOG_TIMER_TICKS (LOG_TIMER0_TICK | LOG_TIMER1_TICK | LOG_TIMER2_TICK | LOG_TIMER3_TICK | LOG_TIMER4_TICK | LOG_TIMER5_TICK) #define LOG_ALL (LOG_UNKNOWN | LOG_BOOT | LOG_TIMERS | LOG_TIMER_TICKS | LOG_EEPROM | LOG_GPIO | LOG_WDOG | LOG_CLOCK | LOG_POWER \ - LOG_OSC | LOG_PINCHG | LOG_EXTMEM | LOG_ADC | LOG_DIGINPUT | LOG_ASYNC | LOG_TWI | LOG_UART) + | LOG_OSC | LOG_PINCHG | LOG_EXTMEM | LOG_ADC | LOG_DIGINPUT | LOG_ASYNC | LOG_TWI | LOG_UART) #define VERBOSE (0) #include "logmacro.h" @@ -870,6 +870,7 @@ void avr8_device::device_start() // Misc. save_item(NAME(m_addr_mask)); save_item(NAME(m_interrupt_pending)); + save_item(NAME(m_opcycles)); // set our instruction counter set_icountptr(m_icount); @@ -1040,7 +1041,6 @@ inline uint8_t avr8_device::pop() void avr8_device::set_irq_line(uint16_t vector, int state) { - // Horrible hack, not accurate if (state) { if (SREG_R(AVR8_SREG_I)) @@ -1058,17 +1058,16 @@ void avr8_device::set_irq_line(uint16_t vector, int state) } } -class CInterruptCondition +struct interrupt_condition { - public: - uint8_t m_intindex; - uint8_t m_intreg; - uint8_t m_intmask; - uint8_t m_regindex; - uint8_t m_regmask; + uint8_t m_intindex; + uint8_t m_intreg; + uint8_t m_intmask; + uint8_t m_regindex; + uint8_t m_regmask; }; -static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] = +static const interrupt_condition 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_T0COMPB, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0B_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0B_MASK }, @@ -1085,7 +1084,7 @@ static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] = void avr8_device::update_interrupt(int source) { - const CInterruptCondition &condition = s_int_conditions[source]; + const interrupt_condition &condition = s_int_conditions[source]; int intstate = 0; if (m_r[condition.m_intreg] & condition.m_intmask) @@ -1101,7 +1100,7 @@ void avr8_device::update_interrupt(int source) void atmega328_device::update_interrupt(int source) { - const CInterruptCondition &condition = s_int_conditions[source]; + const interrupt_condition &condition = s_int_conditions[source]; int intstate = 0; if (m_r[condition.m_intreg] & condition.m_intmask) @@ -1115,7 +1114,7 @@ void atmega328_device::update_interrupt(int source) } } -static const CInterruptCondition s_mega644_int_conditions[AVR8_INTIDX_COUNT] = +static const interrupt_condition s_mega644_int_conditions[AVR8_INTIDX_COUNT] = { { ATMEGA644_INT_SPI_STC, AVR8_REGIDX_SPCR, AVR8_SPCR_SPIE_MASK, AVR8_REGIDX_SPSR, AVR8_SPSR_SPIF_MASK }, { ATMEGA644_INT_T0COMPB, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0B_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0B_MASK }, @@ -1132,7 +1131,7 @@ static const CInterruptCondition s_mega644_int_conditions[AVR8_INTIDX_COUNT] = void atmega644_device::update_interrupt(int source) { - const CInterruptCondition &condition = s_mega644_int_conditions[source]; + const interrupt_condition &condition = s_mega644_int_conditions[source]; int intstate = 0; if (m_r[condition.m_intreg] & condition.m_intmask) @@ -1149,7 +1148,7 @@ void atmega644_device::update_interrupt(int source) //TODO: review this! void atmega1280_device::update_interrupt(int source) { - const CInterruptCondition &condition = s_mega644_int_conditions[source]; + const interrupt_condition &condition = s_mega644_int_conditions[source]; int intstate = 0; if (m_r[condition.m_intreg] & condition.m_intmask) @@ -1166,7 +1165,7 @@ void atmega1280_device::update_interrupt(int source) //TODO: review this! void atmega2560_device::update_interrupt(int source) { - const CInterruptCondition &condition = s_mega644_int_conditions[source]; + const interrupt_condition &condition = s_mega644_int_conditions[source]; int intstate = 0; if (m_r[condition.m_intreg] & condition.m_intmask) @@ -1224,20 +1223,17 @@ void avr8_device::timer_tick() } } -// uint8_t ocr0[2] = { m_r[AVR8_REGIDX_OCR0A], m_r[AVR8_REGIDX_OCR0B] }; -//TODO uint8_t ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR4_OCF0B_SHIFT) }; -//TODO uint8_t int0[2] = { AVR8_INTIDX_OCF0A, AVR8_INTIDX_OCF0B }; - -#define LOG_TIMER_0 0 -#define LOG_TIMER_5 0 // Timer 0 Handling void avr8_device::timer0_tick() { + static const uint8_t s_ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR0_OCF0B_SHIFT) }; + static const uint8_t s_int0[2] = { AVR8_INTIDX_OCF0A, AVR8_INTIDX_OCF0B }; + LOGMASKED(LOG_TIMER0_TICK, "%s: AVR8_WGM0: %d\n", machine().describe_context(), AVR8_WGM0); LOGMASKED(LOG_TIMER0_TICK, "%s: AVR8_TCCR0A_COM0B: %d\n", machine().describe_context(), AVR8_TCCR0A_COM0B); uint8_t count = m_r[AVR8_REGIDX_TCNT0]; - int32_t increment = m_timer_increment[0]; + count++; switch (AVR8_WGM0) { @@ -1253,10 +1249,16 @@ void avr8_device::timer0_tick() switch (AVR8_TCCR0A_COM0B) { case 0: /* Normal Operation */ - if (count == m_timer_top[0]) + if (count == AVR8_OCR0A) { - LOGMASKED(LOG_TIMER0, "%s: timer0: Set normal OC0B behavior\n", machine().describe_context()); - m_timer_top[0] = 0; + m_r[AVR8_REGIDX_TIFR0] |= s_ocf0[AVR8_REG_A]; + update_interrupt(s_int0[AVR8_REG_A]); + count = 0; + } + else if (count == AVR8_OCR0B) + { + m_r[AVR8_REGIDX_TIFR0] |= s_ocf0[AVR8_REG_B]; + update_interrupt(s_int0[AVR8_REG_B]); } break; @@ -1290,26 +1292,23 @@ void avr8_device::timer0_tick() break; case WGM02_FAST_PWM: - LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM: Unimplemented timer0 waveform generation mode\n", machine().describe_context()); - break; + LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM: Unimplemented timer0 waveform generation mode\n", machine().describe_context()); + break; case WGM02_PWM_PC_CMP: - LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_PWM_PC_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context()); - break; + LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_PWM_PC_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context()); + break; case WGM02_FAST_PWM_CMP: - LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context()); - break; + LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context()); + break; default: LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: update_timer0_compare_mode: Unknown waveform generation mode: %02x\n", machine().describe_context(), AVR8_WGM0); break; } - count = count & 0xff; - - count += increment; - m_r[AVR8_REGIDX_TCNT0] = count & 0xff; + m_r[AVR8_REGIDX_TCNT0] = count; } void avr8_device::changed_tccr0a(uint8_t data) @@ -1379,11 +1378,15 @@ inline void avr8_device::timer1_tick() static const uint8_t s_int1[2] = { AVR8_INTIDX_OCF1A, AVR8_INTIDX_OCF1B }; int32_t increment = m_timer_increment[1]; + LOGMASKED(LOG_TIMER1_TICK, "%s: AVR8_WGM1: %d\n", machine().describe_context(), AVR8_WGM1); + for (int32_t reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) { switch (m_wgm1) { case WGM1_CTC_OCR: + LOGMASKED(LOG_TIMER1_TICK, "%s: timer1_count: %04x\n", machine().describe_context(), m_timer1_count); + LOGMASKED(LOG_TIMER1_TICK, "%s: OCR1%c: %04x\n", machine().describe_context(), reg ? 'A' : 'B', m_ocr1[reg]); if (m_timer1_count == 0xffff) { m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK; @@ -1409,9 +1412,6 @@ inline void avr8_device::timer1_tick() m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; update_interrupt(AVR8_INTIDX_TOV1); } - - m_r[AVR8_REGIDX_TIFR1] &= ~s_ocf1[reg]; - update_interrupt(s_int1[reg]); } break; @@ -1882,7 +1882,7 @@ void avr8_device::update_timer_clock_source(uint8_t t, uint8_t clock_select) }; m_timer_prescale[t] = s_prescale_values[(t == 2) ? 1 : 0][clock_select]; - LOGMASKED((LOG_TIMER0 + t), "%s: update_timer_clock_source: t = %d, cs = %d\n", t, machine().describe_context(), clock_select); + LOGMASKED((LOG_TIMER0 + t), "%s: update_timer_clock_source: t = %d, cs = %d\n", machine().describe_context(), t, clock_select); if (m_timer_prescale[t] == 0xffff) { @@ -2250,56 +2250,67 @@ void avr8_device::regs_w(offs_t offset, uint8_t data) break; case AVR8_REGIDX_PORTA: + LOGMASKED(LOG_GPIO, "%s: PORTA Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTA, data); m_r[AVR8_REGIDX_PORTA] = data; break; case AVR8_REGIDX_PORTB: + LOGMASKED(LOG_GPIO, "%s: PORTB Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTB, data); m_r[AVR8_REGIDX_PORTB] = data; break; case AVR8_REGIDX_PORTC: + LOGMASKED(LOG_GPIO, "%s: PORTC Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTC, data); m_r[AVR8_REGIDX_PORTC] = data; break; case AVR8_REGIDX_PORTD: + LOGMASKED(LOG_GPIO, "%s: PORTD Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTD, data); m_r[AVR8_REGIDX_PORTD] = data; break; case AVR8_REGIDX_PORTE: + LOGMASKED(LOG_GPIO, "%s: PORTE Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTE, data); m_r[AVR8_REGIDX_PORTE] = data; break; case AVR8_REGIDX_PORTF: + LOGMASKED(LOG_GPIO, "%s: PORTF Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTF, data); m_r[AVR8_REGIDX_PORTF] = data; break; case AVR8_REGIDX_PORTG: + LOGMASKED(LOG_GPIO, "%s: PORTG Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTG, data); m_r[AVR8_REGIDX_PORTG] = data; break; case AVR8_REGIDX_PORTH: + LOGMASKED(LOG_GPIO, "%s: PORTH Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTH, data); m_r[AVR8_REGIDX_PORTH] = data; break; case AVR8_REGIDX_PORTJ: + LOGMASKED(LOG_GPIO, "%s: PORTJ Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTJ, data); m_r[AVR8_REGIDX_PORTJ] = data; break; case AVR8_REGIDX_PORTK: + LOGMASKED(LOG_GPIO, "%s: PORTK Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTK, data); m_r[AVR8_REGIDX_PORTK] = data; break; case AVR8_REGIDX_PORTL: + LOGMASKED(LOG_GPIO, "%s: PORTL Write: %02x\n", machine().describe_context(), data); m_io->write_byte(AVR8_IO_PORTL, data); m_r[AVR8_REGIDX_PORTL] = data; break; @@ -2327,12 +2338,12 @@ void avr8_device::regs_w(offs_t offset, uint8_t data) case AVR8_REGIDX_OCR0A: LOGMASKED(LOG_TIMER0, "%s: OCR0A = %02x\n", machine().describe_context(), data); - update_ocr0(AVR8_OCR0A, AVR8_REG_A); + update_ocr0(data, AVR8_REG_A); break; case AVR8_REGIDX_OCR0B: LOGMASKED(LOG_TIMER0, "%s: OCR0B = %02x\n", machine().describe_context(), data); - update_ocr0(AVR8_OCR0B, AVR8_REG_B); + update_ocr0(data, AVR8_REG_B); break; case AVR8_REGIDX_TIFR0: @@ -2408,7 +2419,12 @@ void avr8_device::regs_w(offs_t offset, uint8_t data) break; case AVR8_REGIDX_GPIOR1: + LOGMASKED(LOG_GPIO, "%s: GPIOR1 Write: %02x\n", machine().describe_context(), data); + m_r[offset] = data; + break; + case AVR8_REGIDX_GPIOR2: + LOGMASKED(LOG_GPIO, "%s: GPIOR2 Write: %02x\n", machine().describe_context(), data); m_r[offset] = data; break; @@ -2813,6 +2829,8 @@ void avr8_device::regs_w(offs_t offset, uint8_t data) uint8_t avr8_device::regs_r(offs_t offset) { + uint8_t data = m_r[offset]; + switch (offset) { case AVR8_REGIDX_R0: @@ -2847,7 +2865,7 @@ uint8_t avr8_device::regs_r(offs_t offset) case AVR8_REGIDX_R29: case AVR8_REGIDX_R30: case AVR8_REGIDX_R31: - return m_r[offset]; + return data; case AVR8_REGIDX_PINA: // TODO: account for DDRA @@ -2904,7 +2922,7 @@ uint8_t avr8_device::regs_r(offs_t offset) case AVR8_REGIDX_PORTJ: case AVR8_REGIDX_PORTK: case AVR8_REGIDX_PORTL: - return m_r[offset]; + return data; case AVR8_REGIDX_DDRA: case AVR8_REGIDX_DDRB: @@ -2917,19 +2935,25 @@ uint8_t avr8_device::regs_r(offs_t offset) case AVR8_REGIDX_DDRJ: case AVR8_REGIDX_DDRK: case AVR8_REGIDX_DDRL: - return m_r[offset]; + return data; // EEPROM registers case AVR8_REGIDX_EECR: case AVR8_REGIDX_EEDR: - return m_r[offset]; + return data; // Miscellaneous registers // TODO: Implement readback for all applicable registers. case AVR8_REGIDX_GPIOR0: + LOGMASKED(LOG_GPIO, "%s: GPIOR0 Read: %02x\n", machine().describe_context(), data); + return data; case AVR8_REGIDX_GPIOR1: + LOGMASKED(LOG_GPIO, "%s: GPIOR1 Read: %02x\n", machine().describe_context(), data); + return data; case AVR8_REGIDX_GPIOR2: + LOGMASKED(LOG_GPIO, "%s: GPIOR2 Read: %02x\n", machine().describe_context(), data); + return data; // case AVR8_REGIDX_UCSR0B: // TODO: needed for Replicator 1 case AVR8_REGIDX_SPDR: // TODO: needed for Replicator 1 case AVR8_REGIDX_SPSR: // TODO: needed for Replicator 1 @@ -2939,12 +2963,26 @@ uint8_t avr8_device::regs_r(offs_t offset) case AVR8_REGIDX_SPH: case AVR8_REGIDX_SREG: case AVR8_REGIDX_TIMSK0: + LOGMASKED(LOG_TIMER0, "%s: TIMSK0 Read: %02x\n", machine().describe_context(), data); + return data; case AVR8_REGIDX_TIMSK1: + LOGMASKED(LOG_TIMER1, "%s: TIMSK1 Read: %02x\n", machine().describe_context(), data); + return data; case AVR8_REGIDX_TIMSK2: -// case AVR8_REGIDX_TIMSK3: // TODO: needed for Replicator 1 + LOGMASKED(LOG_TIMER2, "%s: TIMSK2 Read: %02x\n", machine().describe_context(), data); + return data; + case AVR8_REGIDX_TIMSK3: + LOGMASKED(LOG_TIMER3, "%s: TIMSK3 Read: %02x\n", machine().describe_context(), data); + return data; case AVR8_REGIDX_TIMSK4: + LOGMASKED(LOG_TIMER4, "%s: TIMSK4 Read: %02x\n", machine().describe_context(), data); + return data; case AVR8_REGIDX_TIMSK5: - return m_r[offset]; + LOGMASKED(LOG_TIMER5, "%s: TIMSK5 Read: %02x\n", machine().describe_context(), data); + return data; + case AVR8_REGIDX_TIFR1: + //LOGMASKED(LOG_TIMER0, "%s: TIFR1 Read: %02x\n", machine().describe_context(), data); + return data; // Two-wire registers case AVR8_REGIDX_TWCR: diff --git a/src/devices/cpu/avr8/avr8dasm.cpp b/src/devices/cpu/avr8/avr8dasm.cpp index 5f47198c425..3fed61c55fa 100644 --- a/src/devices/cpu/avr8/avr8dasm.cpp +++ b/src/devices/cpu/avr8/avr8dasm.cpp @@ -106,572 +106,539 @@ offs_t avr8_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat switch(op & 0xf000) { + case 0x0000: + switch(op & 0x0f00) + { case 0x0000: - switch(op & 0x0f00) + util::stream_format(stream, "NOP"); + break; + case 0x0100: + util::stream_format(stream, "MOVW R%d:R%d, R%d:R%d", (RD4(op) << 1)+1, RD4(op) << 1, (RR4(op) << 1)+1, RR4(op) << 1); + break; + case 0x0200: + util::stream_format(stream, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op)); + break; + case 0x0300: + switch(MULCONST2(op)) { - case 0x0000: - util::stream_format(stream, "NOP"); - break; - case 0x0100: - util::stream_format(stream, "MOVW R%d:R%d, R%d:R%d", (RD4(op) << 1)+1, RD4(op) << 1, (RR4(op) << 1)+1, RR4(op) << 1); - break; - case 0x0200: - util::stream_format(stream, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op)); - break; - case 0x0300: - switch(MULCONST2(op)) - { - case 0: - util::stream_format(stream, "MULSU R%d, R%d", 16+RD3(op), 16+RR3(op)); - break; - case 1: - util::stream_format(stream, "FMUL R%d, R%d", 16+RD3(op), 16+RR3(op)); - break; - case 2: - util::stream_format(stream, "FMULS R%d, R%d", 16+RD3(op), 16+RR3(op)); - break; - case 3: - util::stream_format(stream, "FMULSU R%d, R%d", 16+RD3(op), 16+RR3(op)); - break; - } - break; - case 0x0400: - case 0x0500: - case 0x0600: - case 0x0700: - util::stream_format(stream, "CPC R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0800: - case 0x0900: - case 0x0a00: - case 0x0b00: - util::stream_format(stream, "SBC R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0c00: - case 0x0d00: - case 0x0e00: - case 0x0f00: - util::stream_format(stream, "ADD R%d, R%d", RD5(op), RR5(op)); - break; + case 0: + util::stream_format(stream, "MULSU R%d, R%d", 16+RD3(op), 16+RR3(op)); + break; + case 1: + util::stream_format(stream, "FMUL R%d, R%d", 16+RD3(op), 16+RR3(op)); + break; + case 2: + util::stream_format(stream, "FMULS R%d, R%d", 16+RD3(op), 16+RR3(op)); + break; + case 3: + util::stream_format(stream, "FMULSU R%d, R%d", 16+RD3(op), 16+RR3(op)); + break; } break; - case 0x1000: - switch(op & 0x0c00) + case 0x0400: + case 0x0500: + case 0x0600: + case 0x0700: + util::stream_format(stream, "CPC R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0800: + case 0x0900: + case 0x0a00: + case 0x0b00: + util::stream_format(stream, "SBC R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0c00: + case 0x0d00: + case 0x0e00: + case 0x0f00: + util::stream_format(stream, "ADD R%d, R%d", RD5(op), RR5(op)); + break; + } + break; + case 0x1000: + switch(op & 0x0c00) + { + case 0x0000: + util::stream_format(stream, "CPSE R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0400: + util::stream_format(stream, "CP R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0800: + util::stream_format(stream, "SUB R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0c00: + util::stream_format(stream, "ADC R%d, R%d", RD5(op), RR5(op)); + break; + } + break; + case 0x2000: + switch(op & 0x0c00) + { + case 0x0000: + util::stream_format(stream, "AND R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0400: + util::stream_format(stream, "EOR R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0800: + util::stream_format(stream, "OR R%d, R%d", RD5(op), RR5(op)); + break; + case 0x0c00: + util::stream_format(stream, "MOV R%d, R%d", RD5(op), RR5(op)); + break; + } + break; + case 0x3000: + util::stream_format(stream, "CPI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); + break; + case 0x4000: + util::stream_format(stream, "SBCI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); + break; + case 0x5000: + util::stream_format(stream, "SUBI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); + break; + case 0x6000: + util::stream_format(stream, "ORI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); + break; + case 0x7000: + util::stream_format(stream, "ANDI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); + break; + case 0x8000: + case 0xa000: + switch(op & 0x0208) + { + case 0x0000: + util::stream_format(stream, "LD(D) R%d, Z+%02x", RD5(op), QCONST6(op)); + break; + case 0x0008: + util::stream_format(stream, "LD(D) R%d, Y+%02x", RD5(op), QCONST6(op)); + break; + case 0x0200: + util::stream_format(stream, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op)); + break; + case 0x0208: + util::stream_format(stream, "ST(D) Y+%02x, R%d", QCONST6(op), RD5(op)); + break; + } + break; + case 0x9000: + switch(op & 0x0f00) + { + case 0x0000: + case 0x0100: + switch(op & 0x000f) { - case 0x0000: - util::stream_format(stream, "CPSE R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0400: - util::stream_format(stream, "CP R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0800: - util::stream_format(stream, "SUB R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0c00: - util::stream_format(stream, "ADC R%d, R%d", RD5(op), RR5(op)); - break; + case 0x0000: + op <<= 16; + op |= opcodes.r16(pc); + pc += 2; + util::stream_format(stream, "LDS R%d, (0x%04x)", RD5(op >> 16), op & 0x0000ffff); + break; + case 0x0001: + util::stream_format(stream, "LD R%d, Z+", RD5(op)); + break; + case 0x0002: + util::stream_format(stream, "LD R%d,-Z", RD5(op)); + break; + case 0x0004: + util::stream_format(stream, "LPM R%d, Z", RD5(op)); + break; + case 0x0005: + util::stream_format(stream, "LPM R%d, Z+", RD5(op)); + break; + case 0x0006: + util::stream_format(stream, "ELPM R%d, Z", RD5(op)); + break; + case 0x0007: + util::stream_format(stream, "ELPM R%d, Z+", RD5(op)); + break; + case 0x0009: + util::stream_format(stream, "LD R%d, Y+", RD5(op)); + break; + case 0x000a: + util::stream_format(stream, "LD R%d,-Y", RD5(op)); + break; + case 0x000c: + util::stream_format(stream, "LD R%d, X", RD5(op)); + break; + case 0x000d: + util::stream_format(stream, "LD R%d, X+", RD5(op)); + break; + case 0x000e: + util::stream_format(stream, "LD R%d,-X", RD5(op)); + break; + case 0x000f: + util::stream_format(stream, "POP R%d", RD5(op)); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; } break; - case 0x2000: - switch(op & 0x0c00) + case 0x0200: + case 0x0300: + switch(op & 0x000f) { - case 0x0000: - util::stream_format(stream, "AND R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0400: - util::stream_format(stream, "EOR R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0800: - util::stream_format(stream, "OR R%d, R%d", RD5(op), RR5(op)); - break; - case 0x0c00: - util::stream_format(stream, "MOV R%d, R%d", RD5(op), RR5(op)); - break; + case 0x0000: + op <<= 16; + op |= opcodes.r16(pc); + pc += 2; + util::stream_format(stream, "STS (0x%04x), R%d", op & 0x0000ffff, RD5(op >> 16)); + break; + case 0x0001: + util::stream_format(stream, "ST Z+, R%d", RD5(op)); + break; + case 0x0002: + util::stream_format(stream, "ST -Z , R%d", RD5(op)); + break; + case 0x0009: + util::stream_format(stream, "ST Y+, R%d", RD5(op)); + break; + case 0x000a: + util::stream_format(stream, "ST -Y , R%d", RD5(op)); + break; + case 0x000c: + util::stream_format(stream, "ST X , R%d", RD5(op)); + break; + case 0x000d: + util::stream_format(stream, "ST X+, R%d", RD5(op)); + break; + case 0x000e: + util::stream_format(stream, "ST -X , R%d", RD5(op)); + break; + case 0x000f: + util::stream_format(stream, "PUSH R%d", RD5(op)); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; } break; - case 0x3000: - util::stream_format(stream, "CPI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); - break; - case 0x4000: - util::stream_format(stream, "SBCI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); - break; - case 0x5000: - util::stream_format(stream, "SUBI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); - break; - case 0x6000: - util::stream_format(stream, "ORI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); - break; - case 0x7000: - util::stream_format(stream, "ANDI R%d, 0x%02x", 16+RD4(op), KCONST8(op)); - break; - case 0x8000: - case 0xa000: - switch(op & 0x0208) + case 0x0400: + switch(op & 0x000f) { + case 0x0000: + util::stream_format(stream, "COM R%d", RD5(op)); + break; + case 0x0001: + util::stream_format(stream, "NEG R%d", RD5(op)); + break; + case 0x0002: + util::stream_format(stream, "SWAP R%d", RD5(op)); + break; + case 0x0003: + util::stream_format(stream, "INC R%d", RD5(op)); + break; + case 0x0005: + util::stream_format(stream, "ASR R%d", RD5(op)); + break; + case 0x0006: + util::stream_format(stream, "LSR R%d", RD5(op)); + break; + case 0x0007: + util::stream_format(stream, "ROR R%d", RD5(op)); + break; + case 0x0008: + switch(op & 0x00f0) + { case 0x0000: - util::stream_format(stream, "LD(D) R%d, Z+%02x", RD5(op), QCONST6(op)); + util::stream_format(stream, "SEC"); break; - case 0x0008: - util::stream_format(stream, "LD(D) R%d, Y+%02x", RD5(op), QCONST6(op)); + case 0x0010: + util::stream_format(stream, "SEZ"); break; - case 0x0200: - util::stream_format(stream, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op)); + case 0x0020: + util::stream_format(stream, "SEN"); break; - case 0x0208: - util::stream_format(stream, "ST(D) Y+%02x, R%d", QCONST6(op), RD5(op)); + case 0x0030: + util::stream_format(stream, "SEV"); break; + case 0x0040: + util::stream_format(stream, "SES"); + break; + case 0x0050: + util::stream_format(stream, "SEH"); + break; + case 0x0060: + util::stream_format(stream, "SET"); + break; + case 0x0070: + util::stream_format(stream, "SEI"); + break; + case 0x0080: + util::stream_format(stream, "CLC"); + break; + case 0x0090: + util::stream_format(stream, "CLZ"); + break; + case 0x00a0: + util::stream_format(stream, "CLN"); + break; + case 0x00b0: + util::stream_format(stream, "CLV"); + break; + case 0x00c0: + util::stream_format(stream, "CLS"); + break; + case 0x00d0: + util::stream_format(stream, "CLH"); + break; + case 0x00e0: + util::stream_format(stream, "CLT"); + break; + case 0x00f0: + util::stream_format(stream, "CLI"); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; + } + break; + case 0x0009: + switch(op & 0x00f0) + { + case 0x0000: + util::stream_format(stream, "IJMP"); + break; + case 0x0010: + util::stream_format(stream, "EIJMP"); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; + } + break; + case 0x000a: + util::stream_format(stream, "DEC R%d", RD5(op)); + break; + case 0x000c: + case 0x000d: + addr = KCONST22(op) << 16; + addr |= opcodes.r16(pc); + pc += 2; + util::stream_format(stream, "JMP 0x%06x", addr << 1); + break; + case 0x000e: + case 0x000f: + addr = KCONST22(op) << 16; + addr |= opcodes.r16(pc); + pc += 2; + util::stream_format(stream, "CALL 0x%06x", addr << 1); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; } break; - case 0x9000: - switch(op & 0x0f00) + case 0x0500: + switch(op & 0x000f) { + case 0x0000: + util::stream_format(stream, "COM R%d", RD5(op)); + break; + case 0x0001: + util::stream_format(stream, "NEG R%d", RD5(op)); + break; + case 0x0002: + util::stream_format(stream, "SWAP R%d", RD5(op)); + break; + case 0x0003: + util::stream_format(stream, "INC R%d", RD5(op)); + break; + case 0x0005: + util::stream_format(stream, "ASR R%d", RD5(op)); + break; + case 0x0006: + util::stream_format(stream, "LSR R%d", RD5(op)); + break; + case 0x0007: + util::stream_format(stream, "ROR R%d", RD5(op)); + break; + case 0x0008: + switch(op & 0x00f0) + { case 0x0000: - case 0x0100: - switch(op & 0x000f) - { - case 0x0000: - op <<= 16; - op |= opcodes.r16(pc); - pc += 2; - util::stream_format(stream, "LDS R%d, (0x%04x)", RD5(op >> 16), op & 0x0000ffff); - break; - case 0x0001: - util::stream_format(stream, "LD R%d, Z+", RD5(op)); - break; - case 0x0002: - util::stream_format(stream, "LD R%d,-Z", RD5(op)); - break; - case 0x0004: - util::stream_format(stream, "LPM R%d, Z", RD5(op)); - break; - case 0x0005: - util::stream_format(stream, "LPM R%d, Z+", RD5(op)); - break; - case 0x0006: - util::stream_format(stream, "ELPM R%d, Z", RD5(op)); - break; - case 0x0007: - util::stream_format(stream, "ELPM R%d, Z+", RD5(op)); - break; - case 0x0009: - util::stream_format(stream, "LD R%d, Y+", RD5(op)); - break; - case 0x000a: - util::stream_format(stream, "LD R%d,-Y", RD5(op)); - break; - case 0x000c: - util::stream_format(stream, "LD R%d, X", RD5(op)); - break; - case 0x000d: - util::stream_format(stream, "LD R%d, X+", RD5(op)); - break; - case 0x000e: - util::stream_format(stream, "LD R%d,-X", RD5(op)); - break; - case 0x000f: - util::stream_format(stream, "POP R%d", RD5(op)); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } + util::stream_format(stream, "RET"); break; - case 0x0200: - case 0x0300: - switch(op & 0x000f) - { - case 0x0000: - op <<= 16; - op |= opcodes.r16(pc); - pc += 2; - util::stream_format(stream, "STS (0x%04x), R%d", op & 0x0000ffff, RD5(op >> 16)); - break; - case 0x0001: - util::stream_format(stream, "ST Z+, R%d", RD5(op)); - break; - case 0x0002: - util::stream_format(stream, "ST -Z , R%d", RD5(op)); - break; - case 0x0009: - util::stream_format(stream, "ST Y+, R%d", RD5(op)); - break; - case 0x000a: - util::stream_format(stream, "ST -Y , R%d", RD5(op)); - break; - case 0x000c: - util::stream_format(stream, "ST X , R%d", RD5(op)); - break; - case 0x000d: - util::stream_format(stream, "ST X+, R%d", RD5(op)); - break; - case 0x000e: - util::stream_format(stream, "ST -X , R%d", RD5(op)); - break; - case 0x000f: - util::stream_format(stream, "PUSH R%d", RD5(op)); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } + case 0x0010: + util::stream_format(stream, "RETI"); break; - case 0x0400: - switch(op & 0x000f) - { - case 0x0000: - util::stream_format(stream, "COM R%d", RD5(op)); - break; - case 0x0001: - util::stream_format(stream, "NEG R%d", RD5(op)); - break; - case 0x0002: - util::stream_format(stream, "SWAP R%d", RD5(op)); - break; - case 0x0003: - util::stream_format(stream, "INC R%d", RD5(op)); - break; - case 0x0005: - util::stream_format(stream, "ASR R%d", RD5(op)); - break; - case 0x0006: - util::stream_format(stream, "LSR R%d", RD5(op)); - break; - case 0x0007: - util::stream_format(stream, "ROR R%d", RD5(op)); - break; - case 0x0008: - switch(op & 0x00f0) - { - case 0x0000: - util::stream_format(stream, "SEC"); - break; - case 0x0010: - util::stream_format(stream, "SEZ"); - break; - case 0x0020: - util::stream_format(stream, "SEN"); - break; - case 0x0030: - util::stream_format(stream, "SEV"); - break; - case 0x0040: - util::stream_format(stream, "SES"); - break; - case 0x0050: - util::stream_format(stream, "SEH"); - break; - case 0x0060: - util::stream_format(stream, "SET"); - break; - case 0x0070: - util::stream_format(stream, "SEI"); - break; - case 0x0080: - util::stream_format(stream, "CLC"); - break; - case 0x0090: - util::stream_format(stream, "CLZ"); - break; - case 0x00a0: - util::stream_format(stream, "CLN"); - break; - case 0x00b0: - util::stream_format(stream, "CLV"); - break; - case 0x00c0: - util::stream_format(stream, "CLS"); - break; - case 0x00d0: - util::stream_format(stream, "CLH"); - break; - case 0x00e0: - util::stream_format(stream, "CLT"); - break; - case 0x00f0: - util::stream_format(stream, "CLI"); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } - break; - case 0x0009: - switch(op & 0x00f0) - { - case 0x0000: - util::stream_format(stream, "IJMP"); - break; - case 0x0010: - util::stream_format(stream, "EIJMP"); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } - break; - case 0x000a: - util::stream_format(stream, "DEC R%d", RD5(op)); - break; - case 0x000c: - case 0x000d: - addr = KCONST22(op) << 16; - addr |= opcodes.r16(pc); - pc += 2; - util::stream_format(stream, "JMP 0x%06x", addr << 1); - break; - case 0x000e: - case 0x000f: - addr = KCONST22(op) << 16; - addr |= opcodes.r16(pc); - pc += 2; - util::stream_format(stream, "CALL 0x%06x", addr << 1); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } + case 0x0080: + util::stream_format(stream, "SLEEP"); break; - case 0x0500: - switch(op & 0x000f) - { - case 0x0000: - util::stream_format(stream, "COM R%d", RD5(op)); - break; - case 0x0001: - util::stream_format(stream, "NEG R%d", RD5(op)); - break; - case 0x0002: - util::stream_format(stream, "SWAP R%d", RD5(op)); - break; - case 0x0003: - util::stream_format(stream, "INC R%d", RD5(op)); - break; - case 0x0005: - util::stream_format(stream, "ASR R%d", RD5(op)); - break; - case 0x0006: - util::stream_format(stream, "LSR R%d", RD5(op)); - break; - case 0x0007: - util::stream_format(stream, "ROR R%d", RD5(op)); - break; - case 0x0008: - switch(op & 0x00f0) - { - case 0x0000: - util::stream_format(stream, "RET"); - break; - case 0x0010: - util::stream_format(stream, "RETI"); - break; - case 0x0080: - util::stream_format(stream, "SLEEP"); - break; - case 0x0090: - util::stream_format(stream, "BREAK"); - break; - case 0x00a0: - util::stream_format(stream, "WDR"); - break; - case 0x00c0: - util::stream_format(stream, "LPM"); - break; - case 0x00d0: - util::stream_format(stream, "ELPM"); - break; - case 0x00e0: - util::stream_format(stream, "SPM"); - break; - case 0x00f0: - util::stream_format(stream, "SPM Z+"); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } - break; - case 0x0009: - switch(op & 0x00f0) - { - case 0x0000: - util::stream_format(stream, "ICALL"); - break; - case 0x0010: - util::stream_format(stream, "EICALL"); - break; - default: - util::stream_format(stream, "Undefined (%08x)", op); - break; - } - break; - case 0x000a: - util::stream_format(stream, "DEC R%d", RD5(op)); - break; - case 0x000c: - case 0x000d: - op <<= 16; - op |= opcodes.r16(pc); - pc += 2; - util::stream_format(stream, "JMP 0x%06x", KCONST22(op) << 1); - break; - case 0x000e: - case 0x000f: - op <<= 16; - op |= opcodes.r16(pc); - pc += 2; - util::stream_format(stream, "CALL 0x%06x", KCONST22(op) << 1); - break; - } + case 0x0090: + util::stream_format(stream, "BREAK"); break; - case 0x0600: - util::stream_format(stream, "ADIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op)); + case 0x00a0: + util::stream_format(stream, "WDR"); break; - case 0x0700: - util::stream_format(stream, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op)); + case 0x00c0: + util::stream_format(stream, "LPM"); break; - case 0x0800: - if (ACONST5(op) < 0x20) + case 0x00d0: + util::stream_format(stream, "ELPM"); + break; + case 0x00e0: + util::stream_format(stream, "SPM"); + break; + case 0x00f0: + util::stream_format(stream, "SPM Z+"); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; + } + break; + case 0x0009: + switch(op & 0x00f0) + { + case 0x0000: + util::stream_format(stream, "ICALL"); + break; + case 0x0010: + util::stream_format(stream, "EICALL"); + break; + default: + util::stream_format(stream, "Undefined (%08x)", op); + break; + } + break; + case 0x000a: + util::stream_format(stream, "DEC R%d", RD5(op)); + break; + case 0x000c: + case 0x000d: + op <<= 16; + op |= opcodes.r16(pc); + pc += 2; + util::stream_format(stream, "JMP 0x%06x", KCONST22(op) << 1); + break; + case 0x000e: + case 0x000f: + op <<= 16; + op |= opcodes.r16(pc); + pc += 2; + util::stream_format(stream, "CALL 0x%06x", KCONST22(op) << 1); + break; + } + break; + case 0x0600: + util::stream_format(stream, "ADIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op)); + break; + case 0x0700: + util::stream_format(stream, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op)); + break; + case 0x0800: util::stream_format(stream, "CBI %s, %s", register_names[ACONST5(op)], register_bit_names[ACONST5(op)][RR3(op)]); - else - util::stream_format(stream, "CBI 0x%02x, %d", ACONST5(op), RR3(op)); - break; - case 0x0900: - if (ACONST5(op) < 0x20) + break; + case 0x0900: util::stream_format(stream, "SBIC %s, %s", register_names[ACONST5(op)], register_bit_names[ACONST5(op)][RR3(op)]); - else - util::stream_format(stream, "SBIC 0x%02x, %d", ACONST5(op), RR3(op)); - break; - case 0x0a00: - if (ACONST5(op) < 0x20) + break; + case 0x0a00: util::stream_format(stream, "SBI %s, %s", register_names[ACONST5(op)], register_bit_names[ACONST5(op)][RR3(op)]); - else - util::stream_format(stream, "SBI 0x%02x, %d", ACONST5(op), RR3(op)); - break; - case 0x0b00: - if (ACONST5(op) < 0x20) + break; + case 0x0b00: util::stream_format(stream, "SBIS %s, %s", register_names[ACONST5(op)], register_bit_names[ACONST5(op)][RR3(op)]); - else - util::stream_format(stream, "SBIS 0x%02x, %d", ACONST5(op), RR3(op)); - break; - case 0x0c00: - case 0x0d00: - case 0x0e00: - case 0x0f00: - util::stream_format(stream, "MUL R%d, R%d", RD5(op), RR5(op)); - break; - } break; - case 0xb000: - if(op & 0x0800) - { - if (ACONST6(op) < 0x40 ) { + case 0x0c00: + case 0x0d00: + case 0x0e00: + case 0x0f00: + util::stream_format(stream, "MUL R%d, R%d", RD5(op), RR5(op)); + break; + } + break; + case 0xb000: + if(op & 0x0800) util::stream_format(stream, "OUT %s, R%d", register_names[ACONST6(op)], RD5(op)); - } else { - util::stream_format(stream, "OUT 0x%02x, R%d", ACONST6(op), RD5(op)); - } - } - else - { - if (ACONST6(op) < 0x40 ) { + else util::stream_format(stream, "IN R%d, %s", RD5(op), register_names[ACONST6(op)]); - } else { - util::stream_format(stream, "IN R%d, 0x%02x", RD5(op), ACONST6(op)); - } - } - break; - case 0xc000: - //I'm not sure if this is correct. why pc + ... : pc + 8 + ... ? - util::stream_format(stream, "RJMP %08x", (((op & 0x0800) ? pc + ((op & 0x0fff) | 0xfffff000) : pc + 8 + (op & 0x0fff)) << 0)); - break; - case 0xd000: - util::stream_format(stream, "RCALL %08x", (((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)) << 1)); - break; - case 0xe000: - util::stream_format(stream, "LDI R%d, 0x%02x", 16 + RD4(op), KCONST8(op)); - break; - case 0xf000: - switch(op & 0x0c00) + break; + case 0xc000: + util::stream_format(stream, "RJMP %08x", (((op & 0x0800) ? pc + ((op & 0x0fff) | 0xfffff000) : pc + 2 + (op & 0x0fff)) << 0)); + break; + case 0xd000: + util::stream_format(stream, "RCALL %08x", (((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)) << 1)); + break; + case 0xe000: + util::stream_format(stream, "LDI R%d, 0x%02x", 16 + RD4(op), KCONST8(op)); + break; + case 0xf000: + switch(op & 0x0c00) + { + case 0x0000: + switch(op & 0x0007) { - case 0x0000: - switch(op & 0x0007) - { - case 0x0000: - util::stream_format(stream, "BRLO %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0001: - util::stream_format(stream, "BREQ %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0002: - util::stream_format(stream, "BRMI %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0003: - util::stream_format(stream, "BRVS %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0004: - util::stream_format(stream, "BRLT %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0005: - util::stream_format(stream, "BRHS %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0006: - util::stream_format(stream, "BRTS %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0007: - util::stream_format(stream, "BRIE %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - } - break; - case 0x0400: - switch(op & 0x0007) - { - case 0x0000: - util::stream_format(stream, "BRSH %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0001: - util::stream_format(stream, "BRNE %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0002: - util::stream_format(stream, "BRPL %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0003: - util::stream_format(stream, "BRVC %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0004: - util::stream_format(stream, "BRGE %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0005: - util::stream_format(stream, "BRHC %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0006: - util::stream_format(stream, "BRTC %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - case 0x0007: - util::stream_format(stream, "BRID %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); - break; - } - break; - case 0x0800: - if(op & 0x0200) - { - util::stream_format(stream, "BST R%d, %d", RD5(op), RR3(op)); - } - else - { - util::stream_format(stream, "BLD R%d, %d", RD5(op), RR3(op)); - } - break; - case 0x0c00: - if(op & 0x0200) - { - util::stream_format(stream, "SBRS R%d, %d", RD5(op), RR3(op)); - } - else - { - util::stream_format(stream, "SBRC R%d, %d", RD5(op), RR3(op)); - } - break; + case 0x0000: + util::stream_format(stream, "BRLO %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0001: + util::stream_format(stream, "BREQ %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0002: + util::stream_format(stream, "BRMI %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0003: + util::stream_format(stream, "BRVS %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0004: + util::stream_format(stream, "BRLT %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0005: + util::stream_format(stream, "BRHS %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0006: + util::stream_format(stream, "BRTS %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0007: + util::stream_format(stream, "BRIE %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; } break; + case 0x0400: + switch(op & 0x0007) + { + case 0x0000: + util::stream_format(stream, "BRSH %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0001: + util::stream_format(stream, "BRNE %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0002: + util::stream_format(stream, "BRPL %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0003: + util::stream_format(stream, "BRVC %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0004: + util::stream_format(stream, "BRGE %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0005: + util::stream_format(stream, "BRHC %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0006: + util::stream_format(stream, "BRTC %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + case 0x0007: + util::stream_format(stream, "BRID %08x", (((op & 0x0200) ? (KCONST7(op) | 0xff80) : KCONST7(op)) << 1)); + break; + } + break; + case 0x0800: + if(op & 0x0200) + util::stream_format(stream, "BST R%d, %d", RD5(op), RR3(op)); + else + util::stream_format(stream, "BLD R%d, %d", RD5(op), RR3(op)); + break; + case 0x0c00: + if(op & 0x0200) + util::stream_format(stream, "SBRS R%d, %d", RD5(op), RR3(op)); + else + util::stream_format(stream, "SBRC R%d, %d", RD5(op), RR3(op)); + break; + } + break; } return (pc - base_pc) | SUPPORTED; diff --git a/src/mame/drivers/craft.cpp b/src/mame/drivers/craft.cpp index 81bd2b7eed9..3481f58d231 100644 --- a/src/mame/drivers/craft.cpp +++ b/src/mame/drivers/craft.cpp @@ -2,7 +2,7 @@ // copyright-holders:Ryan Holtz /********************************************************************** - "Craft" demo platform by Linus Akesson + ATmega88-based demo platforms by Linus Åkesson **********************************************************************/ @@ -14,8 +14,6 @@ #include "emupal.h" #include "speaker.h" -#define MASTER_CLOCK 20000000 - #define VISIBLE_CYCLES 480 #define HSYNC_CYCLES 155 #define LINE_CYCLES (VISIBLE_CYCLES + HSYNC_CYCLES) @@ -25,15 +23,72 @@ #define CYCLES_PER_FRAME (LINES_PER_FRAME * LINE_CYCLES) #define PIXELS_PER_FRAME (CYCLES_PER_FRAME) -class craft_state : public driver_device +class lft_state : public driver_device +{ +public: + lft_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_dac(*this, "dac") + { + } + + void base_config(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + + virtual uint32_t master_clock() const = 0; + + void prg_map(address_map &map); + void data_map(address_map &map); + void io_map(address_map &map); + + uint8_t port_r(offs_t offset); + void port_w(offs_t offset, uint8_t data); + + virtual void port_update(const offs_t offset, const uint8_t old, const uint8_t data) = 0; + + required_device m_maincpu; + required_device m_dac; + + enum port : uint8_t + { + PORT_A, + PORT_B, + PORT_C, + PORT_D, + + PORT_COUNT + }; + + uint8_t m_ports[PORT_COUNT]; +}; + +class powernin_state : public lft_state +{ +public: + powernin_state(const machine_config &mconfig, device_type type, const char *tag) + : lft_state(mconfig, type, tag) + { + } + + void powernin(machine_config &config); + +private: + virtual uint32_t master_clock() const override { return 8000000; } + + virtual void port_update(const offs_t offset, const uint8_t old, const uint8_t data) override; +}; + +class craft_state : public lft_state { public: craft_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") + : lft_state(mconfig, type, tag) , m_screen(*this, "screen") , m_palette(*this, "palette") - , m_dac(*this, "dac") { } @@ -43,29 +98,20 @@ private: virtual void machine_start() override; virtual void machine_reset() override; - void craft_prg_map(address_map &map); - void craft_data_map(address_map &map); - void craft_io_map(address_map &map); + virtual uint32_t master_clock() const override { return 20000000; } - uint8_t port_r(offs_t offset); - void port_w(offs_t offset, uint8_t data); + virtual void port_update(const offs_t offset, const uint8_t old, const uint8_t data) override; void init_palette(palette_device &palette) const; void video_update(); uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - required_device m_maincpu; required_device m_screen; required_device m_palette; - required_device m_dac; uint32_t m_last_cycles; uint64_t m_frame_start_cycle; - uint8_t m_port_b; - uint8_t m_port_c; - uint8_t m_port_d; - uint8_t m_latched_color; std::unique_ptr m_pixels; }; @@ -74,79 +120,73 @@ private: // GPIO //************************************************************************** -uint8_t craft_state::port_r(offs_t offset) +uint8_t lft_state::port_r(offs_t offset) { - switch (offset) - { - case 0x00: // Port A - break; - case 0x01: // Port B - return m_port_b; - case 0x02: // Port C - return m_port_c; - case 0x03: // Port D - return m_port_d; - } - - return 0; + return m_ports[offset]; } -void craft_state::port_w(offs_t offset, uint8_t data) +void lft_state::port_w(offs_t offset, uint8_t data) { + const uint8_t old = m_ports[offset]; + m_ports[offset] = data; + port_update(offset, old, data); +} + +void craft_state::port_update(const offs_t offset, const uint8_t old, const uint8_t data) +{ + const uint8_t changed = data ^ old; switch (offset) { - case AVR8_IO_PORTA: - break; + case AVR8_IO_PORTA: + break; - case AVR8_IO_PORTB: + case AVR8_IO_PORTB: + if (BIT(changed, 1) && BIT(data, 1)) { - uint8_t old_port_b = m_port_b; - uint8_t pins = data; - uint8_t changed = pins ^ old_port_b; - if (BIT(changed, 1) && BIT(data, 1)) - { - m_frame_start_cycle = machine().time().as_ticks(MASTER_CLOCK); - video_update(); - } - if (BIT(changed, 3)) - { - video_update(); - m_latched_color = (pins & 0x08) ? (m_port_c & 0x3f) : 0x3f; - } - m_port_b = data; - break; - } - - case AVR8_IO_PORTC: + m_frame_start_cycle = machine().time().as_ticks(master_clock()); video_update(); - m_port_c = data; - m_latched_color = m_port_c; - break; + } + if (BIT(changed, 3)) + { + video_update(); + m_latched_color = (data & 0x08) ? (m_ports[PORT_C] & 0x3f) : 0x3f; + } + break; - case AVR8_IO_PORTD: - m_port_d = data; - m_dac->write((data & 0x02) | ((data & 0xf4) >> 2)); - break; + case AVR8_IO_PORTC: + video_update(); + m_latched_color = data; + break; + + case AVR8_IO_PORTD: + m_dac->write((data & 0x02) | ((data & 0xf4) >> 2)); + break; } } +void powernin_state::port_update(const offs_t offset, const uint8_t old, const uint8_t data) +{ + if (offset == AVR8_IO_PORTD) + m_dac->write(data); +} + //************************************************************************** // MEMORY //************************************************************************** -void craft_state::craft_prg_map(address_map &map) +void lft_state::prg_map(address_map &map) { map(0x0000, 0x1fff).rom(); } -void craft_state::craft_data_map(address_map &map) +void lft_state::data_map(address_map &map) { map(0x0100, 0x04ff).ram(); } -void craft_state::craft_io_map(address_map &map) +void lft_state::io_map(address_map &map) { - map(AVR8_IO_PORTA, AVR8_IO_PORTD).rw(FUNC(craft_state::port_r), FUNC(craft_state::port_w)); + map(AVR8_IO_PORTA, AVR8_IO_PORTD).rw(FUNC(lft_state::port_r), FUNC(lft_state::port_w)); } //************************************************************************** @@ -166,7 +206,7 @@ void craft_state::init_palette(palette_device &palette) const void craft_state::video_update() { - uint64_t cycles = machine().time().as_ticks(MASTER_CLOCK); + uint64_t cycles = machine().time().as_ticks(master_clock()); uint32_t frame_cycles = (uint32_t)(cycles - m_frame_start_cycle); if (m_last_cycles < frame_cycles) @@ -214,67 +254,93 @@ uint32_t craft_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, // MACHINE //************************************************************************** -static INPUT_PORTS_START( craft ) +static INPUT_PORTS_START( empty_input ) INPUT_PORTS_END +void lft_state::machine_start() +{ + save_item(NAME(m_ports)); +} + +void lft_state::machine_reset() +{ + memset(m_ports, 0, PORT_COUNT); +} + void craft_state::machine_start() { + lft_state::machine_start(); + m_pixels = std::make_unique(PIXELS_PER_FRAME); save_item(NAME(m_last_cycles)); save_item(NAME(m_frame_start_cycle)); - save_item(NAME(m_port_b)); - save_item(NAME(m_port_c)); - save_item(NAME(m_port_d)); - save_item(NAME(m_latched_color)); save_pointer(NAME(m_pixels), PIXELS_PER_FRAME); } void craft_state::machine_reset() { + lft_state::machine_reset(); + m_frame_start_cycle = 0; m_last_cycles = 0; - m_port_b = 0; - m_port_c = 0; - m_port_d = 0; - m_latched_color = 0; memset(&m_pixels[0], 0, PIXELS_PER_FRAME); } -void craft_state::craft(machine_config &config) +void lft_state::base_config(machine_config &config) { /* basic machine hardware */ - ATMEGA88(config, m_maincpu, MASTER_CLOCK); - m_maincpu->set_addrmap(AS_PROGRAM, &craft_state::craft_prg_map); - m_maincpu->set_addrmap(AS_DATA, &craft_state::craft_data_map); - m_maincpu->set_addrmap(AS_IO, &craft_state::craft_io_map); + ATMEGA88(config, m_maincpu, master_clock()); + m_maincpu->set_addrmap(AS_PROGRAM, &lft_state::prg_map); + m_maincpu->set_addrmap(AS_DATA, &lft_state::data_map); + m_maincpu->set_addrmap(AS_IO, &lft_state::io_map); m_maincpu->set_eeprom_tag("eeprom"); - /* video hardware */ + /* sound hardware */ + SPEAKER(config, "avr8").front_center(); + voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0)); + vref.add_route(0, m_dac, 1.0, DAC_VREF_POS_INPUT); + vref.add_route(0, m_dac, -1.0, DAC_VREF_NEG_INPUT); +} + +void craft_state::craft(machine_config &config) +{ + base_config(config); + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(MASTER_CLOCK, 635, 47, 527, 525, 36, 516); + m_screen->set_raw(master_clock(), 635, 47, 527, 525, 36, 516); m_screen->set_screen_update(FUNC(craft_state::screen_update)); PALETTE(config, m_palette, FUNC(craft_state::init_palette), 64); - /* sound hardware */ - SPEAKER(config, "avr8").front_center(); - DAC_6BIT_R2R(config, "dac", 0).add_route(0, "avr8", 0.25); // pd1/pd2/pd4/pd5/pd6/pd7 + 2k(x7) + 1k(x5) - voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0)); - vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT); - vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT); + DAC_6BIT_R2R(config, m_dac, 0).add_route(0, "avr8", 0.25); // pd1/pd2/pd4/pd5/pd6/pd7 + 2k(x7) + 1k(x5) +} + +void powernin_state::powernin(machine_config &config) +{ + base_config(config); + + DAC_8BIT_R2R(config, m_dac, 0).add_route(0, "avr8", 0.9); } ROM_START( craft ) - ROM_REGION( 0x2000, "maincpu", 0 ) /* Main program store */ + ROM_REGION( 0x2000, "maincpu", 0 ) ROM_LOAD( "craft.bin", 0x0000, 0x2000, CRC(2e6f9ad2) SHA1(75e495bf18395d74289ca7ee2649622fc4010457) ) - ROM_REGION( 0x200, "eeprom", 0 ) /* on-die eeprom */ + ROM_REGION( 0x200, "eeprom", 0 ) ROM_LOAD( "eeprom.raw", 0x0000, 0x0200, CRC(e18a2af9) SHA1(81fc6f2d391edfd3244870214fac37929af0ac0c) ) ROM_END -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */ -CONS(2008, craft, 0, 0, craft, craft, craft_state, empty_init, "Linus Akesson", "Craft", MACHINE_IMPERFECT_GRAPHICS) +ROM_START( powernin ) + ROM_REGION( 0x2000, "maincpu", 0 ) + ROM_LOAD( "powernin.bin", 0x0000, 0x2000, CRC(67458936) SHA1(26a86846a24dd974723a66bea6c22baf51c7bec9) ) + ROM_REGION( 0x200, "eeprom", 0 ) + ROM_LOAD( "eeprom.raw", 0x0000, 0x0200, CRC(bd7bc39f) SHA1(9d0ac37bb3ec8c95990fd37a962a17a95ce97aa0) ) +ROM_END + +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */ +CONS(2008, craft, 0, 0, craft, empty_input, craft_state, empty_init, "Linus Åkesson", "Craft", MACHINE_IMPERFECT_GRAPHICS) +CONS(2009, powernin, 0, 0, powernin, empty_input, powernin_state, empty_init, "Linus Åkesson", "Power Ninja Action Challenge", 0) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index ae8a7de2392..0c6e81ff4ef 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -11263,6 +11263,7 @@ cpzodiacj // @source:craft.cpp craft // Craft, by [lft] +powernin // Power Ninja Action Challenge, by [lft] @source:crazybal.cpp crazybal // EGS