summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/avr8/avr8.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/avr8/avr8.c')
-rw-r--r--trunk/src/emu/cpu/avr8/avr8.c1205
1 files changed, 1205 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/avr8/avr8.c b/trunk/src/emu/cpu/avr8/avr8.c
new file mode 100644
index 00000000000..045a46c9d00
--- /dev/null
+++ b/trunk/src/emu/cpu/avr8/avr8.c
@@ -0,0 +1,1205 @@
+/*
+ Atmel 8-bit AVR emulator
+
+ (Skeleton)
+
+ DONE:
+ - Disassembler
+ - [lft]'s "Craft" depends on on-chip device support now instead of opcodes (it requires unusually few in order to boot)
+
+ TODO:
+ - Everything else
+ * Finish opcode implementation
+ * Add proper cycle timing
+ * Add Interrupts
+ * Add on-chip hardware (machine driver)
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "avr8.h"
+
+typedef struct _avr8_state avr8_state;
+struct _avr8_state
+{
+ UINT32 pc;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ int icount;
+ UINT32 addr_mask;
+};
+
+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,
+};
+
+enum
+{
+ AVR8_IO_SPL = 0x5d,
+ AVR8_IO_SPH = 0x5e,
+ AVR8_IO_SREG = 0x5f,
+};
+
+#define SREG_R(b) ((READ_IO_8(cpustate, AVR8_IO_SREG) & (1 << (b))) >> (b))
+#define SREG_W(b,v) WRITE_IO_8(cpustate, AVR8_IO_SREG, (READ_IO_8(cpustate, AVR8_IO_SREG) &~ (1 << (b))) | (((v) ? 1 : 0) << (b)))
+#define NOT(x) (1 - (x))
+
+#define RD2(op) (((op) >> 4) & 0x0003)
+#define RD3(op) (((op) >> 4) & 0x0007)
+#define RD4(op) (((op) >> 4) & 0x000f)
+#define RD5(op) (((op) >> 4) & 0x001f)
+#define RR3(op) ((op) & 0x0007)
+#define RR4(op) ((op) & 0x000f)
+#define RR5(op) ((((op) >> 5) & 0x0010) | ((op) & 0x000f))
+#define KCONST6(op) ((((op) >> 2) & 0x0030) | ((op) & 0x000f))
+#define KCONST7(op) (((op) >> 3) & 0x007f)
+#define KCONST8(op) ((((op) >> 4) & 0x00f0) | ((op) & 0x000f))
+#define KCONST22(op) (((((UINT32)(op) >> 3) & 0x003e) | ((UINT32)(op) & 0x0001)) << 16)
+#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 XREG ((READ_IO_8(cpustate, 27) << 8) | READ_IO_8(cpustate, 26))
+#define YREG ((READ_IO_8(cpustate, 29) << 8) | READ_IO_8(cpustate, 28))
+#define ZREG ((READ_IO_8(cpustate, 31) << 8) | READ_IO_8(cpustate, 30))
+#define SPREG ((READ_IO_8(cpustate, AVR8_IO_SPH) << 8) | READ_IO_8(cpustate, AVR8_IO_SPL))
+
+INLINE avr8_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ATMEGA88 || device->type() == ATMEGA644);
+ return (avr8_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/*****************************************************************************/
+
+static void unimplemented_opcode(avr8_state *cpustate, UINT32 op)
+{
+ fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, cpustate->pc);
+}
+
+/*****************************************************************************/
+
+INLINE bool avr8_is_long_opcode(UINT16 op)
+{
+ if((op & 0xf000) == 0x9000)
+ {
+ if((op & 0x0f00) < 0x0400)
+ {
+ if((op & 0x000f) == 0x0000)
+ {
+ return true;
+ }
+ }
+ else if((op & 0x0f00) < 0x0600)
+ {
+ if((op & 0x000f) >= 0x000c)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+INLINE UINT8 READ_PRG_8(avr8_state *cpustate, UINT32 address)
+{
+ return cpustate->program->read_byte(address);
+}
+
+INLINE UINT16 READ_PRG_16(avr8_state *cpustate, UINT32 address)
+{
+ return cpustate->program->read_word(address << 1);
+}
+
+INLINE void WRITE_PRG_8(avr8_state *cpustate, UINT32 address, UINT8 data)
+{
+ cpustate->program->write_byte(address, data);
+}
+
+INLINE void WRITE_PRG_16(avr8_state *cpustate, UINT32 address, UINT16 data)
+{
+ cpustate->program->write_word(address, data);
+}
+
+INLINE UINT8 READ_IO_8(avr8_state *cpustate, UINT16 address)
+{
+ return cpustate->io->read_byte(address);
+}
+
+INLINE void WRITE_IO_8(avr8_state *cpustate, UINT16 address, UINT8 data)
+{
+ cpustate->io->write_byte(address, data);
+}
+
+INLINE void PUSH(avr8_state *cpustate, UINT8 val)
+{
+ UINT16 sp = SPREG;
+ WRITE_IO_8(cpustate, sp, val);
+ sp--;
+ //printf( "PUSH %02x, new SP = %04x\n", val, sp );
+ WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff);
+}
+
+INLINE UINT8 POP(avr8_state *cpustate)
+{
+ UINT16 sp = SPREG;
+ sp++;
+ WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff);
+ //printf( "POP %02x, new SP = %04x\n", READ_IO_8(cpustate, sp), sp );
+ return READ_IO_8(cpustate, sp);
+}
+
+static void avr8_set_irq_line(avr8_state *cpustate, UINT16 vector, int state)
+{
+ //printf( "OMFG SETTING IRQ LINE\n" );
+ // Horrible hack, not accurate
+ if(state)
+ {
+ if(SREG_R(AVR8_SREG_I))
+ {
+ SREG_W(AVR8_SREG_I, 0);
+ PUSH(cpustate, (cpustate->pc >> 8) & 0x00ff);
+ PUSH(cpustate, cpustate->pc & 0x00ff);
+ cpustate->pc = vector;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static CPU_INIT( avr8 )
+{
+ avr8_state *cpustate = get_safe_token(device);
+
+ cpustate->pc = 0;
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ WRITE_IO_8(cpustate, AVR8_IO_SREG, 0);
+
+ device->save_item(NAME(cpustate->pc));
+}
+
+static CPU_EXIT( avr8 )
+{
+}
+
+static CPU_RESET( avr8 )
+{
+ avr8_state *cpustate = get_safe_token(device);
+
+ WRITE_IO_8(cpustate, AVR8_IO_SREG, 0);
+ cpustate->pc = 0;
+}
+
+static CPU_EXECUTE( avr8 )
+{
+ UINT32 op = 0;
+ INT32 offs = 0;
+ UINT8 rd = 0;
+ UINT8 rr = 0;
+ UINT8 res = 0;
+ UINT16 pd = 0;
+ INT16 sd = 0;
+ INT32 opcycles = 1;
+ //UINT16 pr = 0;
+ avr8_state *cpustate = get_safe_token(device);
+
+ while (cpustate->icount > 0)
+ {
+ cpustate->pc &= cpustate->addr_mask;
+
+ debugger_instruction_hook(device, cpustate->pc << 1);
+
+ op = (UINT32)READ_PRG_16(cpustate, cpustate->pc);
+
+ switch(op & 0xf000)
+ {
+ case 0x0000:
+ switch(op & 0x0f00)
+ {
+ case 0x0000: // NOP
+ break;
+ case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd
+ WRITE_IO_8(cpustate, (RD4(op) << 1)+1, READ_IO_8(cpustate, (RR4(op) << 1)+1));
+ WRITE_IO_8(cpustate, RD4(op) << 1, READ_IO_8(cpustate, RR4(op) << 1));
+ break;
+ case 0x0200: // MULS Rd,Rr
+ //output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0300: // MULSU Rd,Rr
+ sd = (INT8)READ_IO_8(cpustate, 16+RD4(op)) * (UINT8)READ_IO_8(cpustate, 16+RR4(op));
+ WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 0, sd & 0x00ff);
+ SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0);
+ SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0);
+ opcycles = 2;
+ break;
+ case 0x0400:
+ case 0x0500:
+ case 0x0600:
+ case 0x0700: // CPC Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, 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) ? 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:
+ case 0x0900:
+ case 0x0a00:
+ case 0x0b00: // SBC Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd - (rr + SREG_R(AVR8_SREG_C));
+ WRITE_IO_8(cpustate, 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:
+ case 0x0d00:
+ case 0x0e00:
+ case 0x0f00: // ADD Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd + rr;
+ WRITE_IO_8(cpustate, 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: // CPSR Rd,Rr
+ //output += sprintf( output, "CPSE R%d, R%d", RD5(op), RR5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0400: // CP Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, 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 = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd - rr;
+ WRITE_IO_8(cpustate, 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 = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd + rr + SREG_R(AVR8_SREG_C);
+ WRITE_IO_8(cpustate, 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
+ //output += sprintf( output, "AND R%d, R%d", RD5(op), RR5(op) );
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ rd &= rr;
+ SREG_W(AVR8_SREG_V, 0);
+ SREG_W(AVR8_SREG_N, rd & 0x80);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), rd);
+ break;
+ case 0x0400: // EOR Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ rd ^= rr;
+ SREG_W(AVR8_SREG_V, 0);
+ SREG_W(AVR8_SREG_N, rd & 0x80);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), rd);
+ break;
+ case 0x0800: // OR Rd,Rr
+ //output += sprintf( output, "OR R%d, R%d", RD5(op), RR5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0c00: // MOV Rd,Rr
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RR5(op)));
+ break;
+ }
+ break;
+ case 0x3000: // CPI Rd,K
+ rd = READ_IO_8(cpustate, 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
+ //output += sprintf( output, "SBCI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x5000: // SUBI Rd,K
+ rd = READ_IO_8(cpustate, 16+RD4(op));
+ rr = KCONST8(op);
+ res = rd - rr;
+ WRITE_IO_8(cpustate, 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
+ //output += sprintf( output, "ORI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x7000: // ANDI Rd,K
+ //output += sprintf( output, "ANDI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x8000:
+ case 0xa000:
+ switch(op & 0x0208)
+ {
+ case 0x0000: // LDD Rd,Z+q
+ //output += sprintf( output, "LD(D) R%d, Z+%02x", RD5(op), QCONST6(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0008: // LDD Rd,Y+q
+ WRITE_IO_8(cpustate, RD5(op), YREG + QCONST6(op));
+ opcycles = 2;
+ break;
+ case 0x0200: // STD Z+q,Rr
+ //output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0208: // STD Y+q,Rr
+ WRITE_IO_8(cpustate, YREG + QCONST6(op), READ_IO_8(cpustate, 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;
+ cpustate->pc++;
+ op |= READ_PRG_16(cpustate, cpustate->pc);
+ WRITE_IO_8(cpustate, RD5(op >> 16), READ_IO_8(cpustate, op & 0x0000ffff));
+ opcycles = 2;
+ break;
+ case 0x0001: // LD Rd,Z+
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0002: // LD Rd,-Z
+ //output += sprintf( output, "LD R%d,-Z", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0004: // LPM Rd,Z
+ WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, ZREG));
+ opcycles = 3;
+ break;
+ case 0x0005: // LPM Rd,Z+
+ pd = ZREG;
+ WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, pd));
+ pd++;
+ WRITE_IO_8(cpustate, 31, (pd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 30, pd & 0x00ff);
+ opcycles = 3;
+ break;
+ case 0x0006: // ELPM Rd,Z
+ //output += sprintf( output, "ELPM R%d, Z", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0007: // ELPM Rd,Z+
+ //output += sprintf( output, "ELPM R%d, Z+", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0009: // LD Rd,Y+
+ //output += sprintf( output, "LD R%d, Y+", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000a: // LD Rd,-Y
+ //output += sprintf( output, "LD R%d,-Y", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000c: // LD Rd,X
+ //output += sprintf( output, "LD R%d, X", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000d: // LD Rd,X+
+ pd = XREG;
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, pd));
+ pd++;
+ WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 26, pd & 0x00ff);
+ opcycles = 2;
+ break;
+ case 0x000e: // LD Rd,-X
+ //output += sprintf( output, "LD R%d,-X", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000f: // POP Rd
+ WRITE_IO_8(cpustate, RD5(op), POP(cpustate));
+ opcycles = 2;
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0200:
+ case 0x0300:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // STS k,Rr
+ op <<= 16;
+ cpustate->pc++;
+ op |= READ_PRG_16(cpustate, cpustate->pc);
+ WRITE_IO_8(cpustate, op & 0x0000ffff, READ_IO_8(cpustate, RD5(op >> 16)));
+ opcycles = 2;
+ break;
+ case 0x0001: // ST Z+,Rd
+ //output += sprintf( output, "ST Z+, R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0002: // ST -Z,Rd
+ //output += sprintf( output, "ST -Z , R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0009: // ST Y+,Rd
+ //output += sprintf( output, "ST Y+, R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000a: // ST -Z,Rd
+ //output += sprintf( output, "ST -Y , R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000c: // ST X,Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ WRITE_IO_8(cpustate, XREG, rd);
+ opcycles = 2;
+ break;
+ case 0x000d: // ST X+,Rd
+ pd = XREG;
+ WRITE_IO_8(cpustate, pd, READ_IO_8(cpustate, RD5(op)));
+ pd++;
+ WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 26, pd & 0x00ff);
+ opcycles = 2;
+ break;
+ case 0x000e: // ST -X,Rd
+ //output += sprintf( output, "ST -X , R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000f: // PUSH Rd
+ PUSH(cpustate, READ_IO_8(cpustate, RD5(op)));
+ opcycles = 2;
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0400:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // COM Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ rd = ~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));
+ break;
+ case 0x0001: // NEG Rd
+ rd = READ_IO_8(cpustate, 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));
+ break;
+ case 0x0002: // SWAP Rd
+ //output += sprintf( output, "SWAP R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0003: // INC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd + 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x0005: // ASR Rd
+ //output += sprintf( output, "ASR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0006: // LSR Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd >> 1;
+ SREG_W(AVR8_SREG_C, rd & 0x01);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0);
+ SREG_W(AVR8_SREG_N, 0);
+ SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ break;
+ case 0x0007: // ROR Rd
+ //output += sprintf( output, "ROR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ 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
+ cpustate->pc = ZREG - 1;
+ opcycles = 2;
+ break;
+ case 0x0010: // EIJMP
+ //output += sprintf( output, "EIJMP" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ default:
+ //output += sprintf( output, "Undefined (%04x)", op );
+ unimplemented_opcode(cpustate, op);
+ break;
+ }
+ break;
+ case 0x000a: // DEC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd - 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x000c:
+ case 0x000d: // JMP k
+ offs = KCONST22(op) << 16;
+ cpustate->pc++;
+ offs |= READ_PRG_16(cpustate, cpustate->pc);
+ cpustate->pc = offs;
+ cpustate->pc--;
+ opcycles = 4;
+ break;
+ case 0x000e: // CALL k
+ case 0x000f:
+ PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff);
+ PUSH(cpustate, (cpustate->pc + 1) & 0x00ff);
+ offs = KCONST22(op) << 16;
+ cpustate->pc++;
+ offs |= READ_PRG_16(cpustate, cpustate->pc);
+ cpustate->pc = offs;
+ cpustate->pc--;
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0500:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // COM Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ rd = ~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));
+ break;
+ case 0x0001: // NEG Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = 0 - rd;
+ WRITE_IO_8(cpustate, RD5(op), res);
+ 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));
+ break;
+ case 0x0002: // SWAP Rd
+ //output += sprintf( output, "SWAP R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0003: // INC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd + 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x0005: // ASR Rd
+ //output += sprintf( output, "ASR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0006: // LSR Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd >> 1;
+ SREG_W(AVR8_SREG_C, rd & 0x01);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0);
+ SREG_W(AVR8_SREG_N, 0);
+ SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ break;
+ case 0x0007: // ROR Rd
+ //output += sprintf( output, "ROR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0008:
+ switch(op & 0x00f0)
+ {
+ case 0x0000: // RET
+ cpustate->pc = POP(cpustate);
+ cpustate->pc |= POP(cpustate) << 8;
+ cpustate->pc--;
+ opcycles = 4;
+ break;
+ case 0x0010: // RETI
+ cpustate->pc = POP(cpustate);
+ cpustate->pc |= POP(cpustate) << 8;
+ cpustate->pc--;
+ SREG_W(AVR8_SREG_I, 1);
+ opcycles = 4;
+ break;
+ case 0x0080: // SLEEP
+ //output += sprintf( output, "SLEEP" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0090: // BREAK
+ //output += sprintf( output, "BREAK" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00a0: // WDR
+ //output += sprintf( output, "WDR" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00c0: // LPM
+ WRITE_IO_8(cpustate, 0, READ_PRG_8(cpustate, ZREG));
+ opcycles = 3;
+ break;
+ case 0x00d0: // ELPM
+ //output += sprintf( output, "ELPM" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00e0: // SPM
+ //output += sprintf( output, "SPM" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00f0: // SPM Z+
+ //output += sprintf( output, "SPM Z+" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0009:
+ switch(op & 0x00f0)
+ {
+ case 0x0000: // ICALL
+ //output += sprintf( output, "ICALL" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0010: // EICALL
+ //output += sprintf( output, "EICALL" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x000a: // DEC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd - 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ 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(cpustate, 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(cpustate, op);
+ break;
+ }
+ break;
+ case 0x0600: // ADIW Rd+1:Rd,K
+ //output += sprintf( output, "ADIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0700: // SBIW Rd+1:Rd,K
+ //output += sprintf( output, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0800: // CBI A,b
+ //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) );
+ WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) &~ (1 << RR3(op)));
+ opcycles = 2;
+ break;
+ case 0x0900: // SBIC A,b
+ if(!(READ_IO_8(cpustate, ACONST5(op)) & (1 << RR3(op))))
+ {
+ opcycles += avr8_is_long_opcode(op) ? 2 : 1;
+ cpustate->pc += avr8_is_long_opcode(op) ? 2 : 1;
+ }
+ break;
+ case 0x0a00: // SBI A,b
+ //output += sprintf( output, "SBI 0x%02x, %d", ACONST5(op), RR3(op) );
+ WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) | (1 << RR3(op)));
+ opcycles = 2;
+ break;
+ case 0x0b00: // SBIS A,b
+ //output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0c00:
+ case 0x0d00:
+ case 0x0e00:
+ case 0x0f00: // MUL Rd,Rr
+ sd = (UINT8)READ_IO_8(cpustate, RD5(op)) * (UINT8)READ_IO_8(cpustate, RR5(op));
+ WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 0, sd & 0x00ff);
+ SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0);
+ SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0);
+ opcycles = 2;
+ //output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) );
+ break;
+ }
+ break;
+ case 0xb000:
+ if(op & 0x0800) // OUT A,Rr
+ {
+ WRITE_IO_8(cpustate, 0x20 + ACONST6(op), READ_IO_8(cpustate, RD5(op)));
+ }
+ else // IN Rd,A
+ {
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, 0x20 + ACONST6(op)));
+ }
+ break;
+ case 0xc000: // RJMP k
+ offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
+ cpustate->pc += offs;
+ opcycles = 2;
+ break;
+ case 0xd000: // RCALL k
+ offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
+ PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff);
+ PUSH(cpustate, (cpustate->pc + 1) & 0x00ff);
+ cpustate->pc += offs;
+ opcycles = 3;
+ break;
+ case 0xe000: // LDI Rd,K
+ rd = KCONST8(op);
+ WRITE_IO_8(cpustate, 16 + RD4(op), rd);
+ 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;
+ }
+ cpustate->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;
+ }
+ cpustate->pc += offs;
+ opcycles = 2;
+ }
+ break;
+ case 0x0800:
+ if(op & 0x0200) // BST Rd, b
+ {
+ SREG_W(AVR8_SREG_T, (BIT(READ_IO_8(cpustate, RD5(op)),RR3(op))) ? 1 : 0);
+ }
+ else // BLD Rd, b
+ {
+ if(SREG_R(AVR8_SREG_T))
+ {
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) | (1 << RR3(op)));
+ }
+ else
+ {
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) &~ (1 << RR3(op)));
+ }
+ }
+ break;
+ case 0x0c00:
+ if(op & 0x0200) // SBRS Rd, b
+ {
+ if(BIT(READ_IO_8(cpustate, RD5(op)),RR3(op)))
+ {
+ op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
+ opcycles = 2;
+ if((op & 0xfe0c) == 0x940c ||
+ (op & 0xfe0f) == 0xfe0f)
+ {
+ cpustate->pc++;
+ opcycles = 3;
+ }
+ }
+ }
+ else // SBRC Rd, b
+ {
+ if(!BIT(READ_IO_8(cpustate, RD5(op)),RR3(op)))
+ {
+ op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
+ opcycles = 2;
+ if((op & 0xfe0c) == 0x940c ||
+ (op & 0xfc0f) == 0x9000)
+ {
+ cpustate->pc++;
+ opcycles = 3;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ cpustate->pc++;
+
+ cpustate->icount -= opcycles;
+ }
+}
+
+/*****************************************************************************/
+
+static CPU_SET_INFO( avr8 )
+{
+ avr8_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+
+ /* interrupt lines/exceptions */
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_RESET: avr8_set_irq_line(cpustate, AVR8_INT_RESET, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_INT0: avr8_set_irq_line(cpustate, AVR8_INT_INT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_INT1: avr8_set_irq_line(cpustate, AVR8_INT_INT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT0: avr8_set_irq_line(cpustate, AVR8_INT_PCINT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT1: avr8_set_irq_line(cpustate, AVR8_INT_PCINT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT2: avr8_set_irq_line(cpustate, AVR8_INT_PCINT2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_WDT: avr8_set_irq_line(cpustate, AVR8_INT_WDT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T2COMPA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T2COMPB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2OVF: avr8_set_irq_line(cpustate, AVR8_INT_T2OVF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1CAPT: avr8_set_irq_line(cpustate, AVR8_INT_T1CAPT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T1COMPA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T1COMPB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1OVF: avr8_set_irq_line(cpustate, AVR8_INT_T1OVF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T0COMPA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T0COMPB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0OVF: avr8_set_irq_line(cpustate, AVR8_INT_T0OVF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_SPI_STC: avr8_set_irq_line(cpustate, AVR8_INT_SPI_STC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_RX: avr8_set_irq_line(cpustate, AVR8_INT_USART_RX, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_UDRE: avr8_set_irq_line(cpustate, AVR8_INT_USART_UDRE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_TX: avr8_set_irq_line(cpustate, AVR8_INT_USART_TX, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_ADC: avr8_set_irq_line(cpustate, AVR8_INT_ADC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_EE_RDY: avr8_set_irq_line(cpustate, AVR8_INT_EE_RDY, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_ANALOG_COMP: avr8_set_irq_line(cpustate, AVR8_INT_ANALOG_COMP, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_TWI: avr8_set_irq_line(cpustate, AVR8_INT_TWI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_SPM_RDY: avr8_set_irq_line(cpustate, AVR8_INT_SPM_RDY, info->i); break;
+
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + AVR8_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + AVR8_SREG: WRITE_IO_8(cpustate, AVR8_IO_SREG, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R0: WRITE_IO_8(cpustate, 0, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R1: WRITE_IO_8(cpustate, 1, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R2: WRITE_IO_8(cpustate, 2, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R3: WRITE_IO_8(cpustate, 3, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R4: WRITE_IO_8(cpustate, 4, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R5: WRITE_IO_8(cpustate, 5, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R6: WRITE_IO_8(cpustate, 6, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R7: WRITE_IO_8(cpustate, 7, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R8: WRITE_IO_8(cpustate, 8, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R9: WRITE_IO_8(cpustate, 9, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R10: WRITE_IO_8(cpustate, 10, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R11: WRITE_IO_8(cpustate, 11, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R12: WRITE_IO_8(cpustate, 12, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R13: WRITE_IO_8(cpustate, 13, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R14: WRITE_IO_8(cpustate, 14, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R15: WRITE_IO_8(cpustate, 15, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R16: WRITE_IO_8(cpustate, 16, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R17: WRITE_IO_8(cpustate, 17, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R18: WRITE_IO_8(cpustate, 18, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R19: WRITE_IO_8(cpustate, 19, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R20: WRITE_IO_8(cpustate, 20, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R21: WRITE_IO_8(cpustate, 21, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R22: WRITE_IO_8(cpustate, 22, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R23: WRITE_IO_8(cpustate, 23, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R24: WRITE_IO_8(cpustate, 24, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R25: WRITE_IO_8(cpustate, 25, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R26: WRITE_IO_8(cpustate, 26, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R27: WRITE_IO_8(cpustate, 27, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R28: WRITE_IO_8(cpustate, 28, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R29: WRITE_IO_8(cpustate, 29, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R30: WRITE_IO_8(cpustate, 30, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R31: WRITE_IO_8(cpustate, 31, info->i); break;
+ }
+}
+
+CPU_GET_INFO( avr8 )
+{
+ avr8_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(avr8_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 22; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + AVR8_PC: info->i = cpustate->pc << 1; break;
+ case CPUINFO_INT_REGISTER + AVR8_SREG: info->i = READ_IO_8(cpustate, AVR8_IO_SREG); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(avr8); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(avr8); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(avr8); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(avr8); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(avr8); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(avr8); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Atmel 8-bit AVR"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "AVR8"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + AVR8_SREG: sprintf(info->s, "SREG: %c%c%c%c%c%c%c%c", (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x80) ? 'I' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x40) ? 'T' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x20) ? 'H' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x10) ? 'S' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x08) ? 'V' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x04) ? 'N' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x02) ? 'Z' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x01) ? 'C' : '-'); break;
+ case CPUINFO_STR_REGISTER + AVR8_R0: sprintf(info->s, "R0: %02x", READ_IO_8(cpustate, 0) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R1: sprintf(info->s, "R1: %02x", READ_IO_8(cpustate, 1) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R2: sprintf(info->s, "R2: %02x", READ_IO_8(cpustate, 2) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R3: sprintf(info->s, "R3: %02x", READ_IO_8(cpustate, 3) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R4: sprintf(info->s, "R4: %02x", READ_IO_8(cpustate, 4) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R5: sprintf(info->s, "R5: %02x", READ_IO_8(cpustate, 5) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R6: sprintf(info->s, "R6: %02x", READ_IO_8(cpustate, 6) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R7: sprintf(info->s, "R7: %02x", READ_IO_8(cpustate, 7) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R8: sprintf(info->s, "R8: %02x", READ_IO_8(cpustate, 8) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R9: sprintf(info->s, "R9: %02x", READ_IO_8(cpustate, 9) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R10: sprintf(info->s, "R10: %02x", READ_IO_8(cpustate, 10) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R11: sprintf(info->s, "R11: %02x", READ_IO_8(cpustate, 11) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R12: sprintf(info->s, "R12: %02x", READ_IO_8(cpustate, 12) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R13: sprintf(info->s, "R13: %02x", READ_IO_8(cpustate, 13) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R14: sprintf(info->s, "R14: %02x", READ_IO_8(cpustate, 14) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R15: sprintf(info->s, "R15: %02x", READ_IO_8(cpustate, 15) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R16: sprintf(info->s, "R16: %02x", READ_IO_8(cpustate, 16) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R17: sprintf(info->s, "R17: %02x", READ_IO_8(cpustate, 17) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R18: sprintf(info->s, "R18: %02x", READ_IO_8(cpustate, 18) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R19: sprintf(info->s, "R19: %02x", READ_IO_8(cpustate, 19) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R20: sprintf(info->s, "R20: %02x", READ_IO_8(cpustate, 20) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R21: sprintf(info->s, "R21: %02x", READ_IO_8(cpustate, 21) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R22: sprintf(info->s, "R22: %02x", READ_IO_8(cpustate, 22) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R23: sprintf(info->s, "R23: %02x", READ_IO_8(cpustate, 23) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R24: sprintf(info->s, "R24: %02x", READ_IO_8(cpustate, 24) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R25: sprintf(info->s, "R25: %02x", READ_IO_8(cpustate, 25) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R26: sprintf(info->s, "R26: %02x", READ_IO_8(cpustate, 26) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R27: sprintf(info->s, "R27: %02x", READ_IO_8(cpustate, 27) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R28: sprintf(info->s, "R28: %02x", READ_IO_8(cpustate, 28) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R29: sprintf(info->s, "R29: %02x", READ_IO_8(cpustate, 29) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R30: sprintf(info->s, "R30: %02x", READ_IO_8(cpustate, 30) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R31: sprintf(info->s, "R31: %02x", READ_IO_8(cpustate, 31) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_X: sprintf(info->s, "X: %04x", XREG ); break;
+ case CPUINFO_STR_REGISTER + AVR8_Y: sprintf(info->s, "Y: %04x", YREG ); break;
+ case CPUINFO_STR_REGISTER + AVR8_Z: sprintf(info->s, "Z: %04x", ZREG ); break;
+ case CPUINFO_STR_REGISTER + AVR8_SP: sprintf(info->s, "SP: %04x", SPREG ); break;
+ }
+}
+
+static CPU_INIT( atmega88 )
+{
+ CPU_INIT_CALL(avr8);
+ avr8_state *cpustate = get_safe_token(device);
+ cpustate->addr_mask = 0x0fff;
+}
+
+static CPU_INIT( atmega644 )
+{
+ CPU_INIT_CALL(avr8);
+ avr8_state *cpustate = get_safe_token(device);
+ cpustate->addr_mask = 0xffff;
+}
+
+CPU_GET_INFO( atmega88 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(atmega88); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ATmega88"); break;
+
+ default: CPU_GET_INFO_CALL(avr8); break;
+ }
+}
+
+CPU_GET_INFO( atmega644 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(atmega644); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ATmega644"); break;
+
+ default: CPU_GET_INFO_CALL(avr8); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(ATMEGA88, atmega88);
+DEFINE_LEGACY_CPU_DEVICE(ATMEGA644, atmega644);