summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/i8085/i8085.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/i8085/i8085.c')
-rw-r--r--trunk/src/emu/cpu/i8085/i8085.c1298
1 files changed, 1298 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/i8085/i8085.c b/trunk/src/emu/cpu/i8085/i8085.c
new file mode 100644
index 00000000000..84f6eaa992d
--- /dev/null
+++ b/trunk/src/emu/cpu/i8085/i8085.c
@@ -0,0 +1,1298 @@
+/*****************************************************************************
+ *
+ * i8085.c
+ * Portable I8085A emulator V1.2
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * Partially based on information out of Z80Em by Marcel De Kogel
+ *
+ * changes in V1.3
+ * - Added undocumented opcodes for the 8085A, based on a german
+ * book about microcomputers: "Mikrocomputertechnik mit dem
+ * Prozessor 8085A".
+ * - This book also suggest that INX/DCX should modify the X flag bit
+ * for a LSB to MSB carry and
+ * - that jumps take 10 T-states only when they're executed, 7 when
+ * they're skipped.
+ * Thanks for the info and a copy of the tables go to Timo Sachsenberg
+ * <timo.sachsenberg@student.uni-tuebingen.de>
+ * changes in V1.2
+ * - corrected cycle counts for these classes of opcodes
+ * Thanks go to Jim Battle <frustum@pacbell.bet>
+ *
+ * 808x Z80
+ * DEC A 5 4 \
+ * INC A 5 4 \
+ * LD A,B 5 4 >-- Z80 is faster
+ * JP (HL) 5 4 /
+ * CALL cc,nnnn: 11/17 10/17 /
+ *
+ * INC HL 5 6 \
+ * DEC HL 5 6 \
+ * LD SP,HL 5 6 \
+ * ADD HL,BC 10 11 \
+ * INC (HL) 10 11 >-- 8080 is faster
+ * DEC (HL) 10 11 /
+ * IN A,(#) 10 11 /
+ * OUT (#),A 10 11 /
+ * EX (SP),HL 18 19 /
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * You can contact me at juergen@mame.net or pullmoll@stop1984.com
+ *
+ * - This source code is released as freeware for non-commercial purposes
+ * as part of the M.A.M.E. (Multiple Arcade Machine Emulator) project.
+ * The licensing terms of MAME apply to this piece of code for the MAME
+ * project and derviative works, as defined by the MAME license. You
+ * may opt to make modifications, improvements or derivative works under
+ * that same conditions, and the MAME project may opt to keep
+ * modifications, improvements or derivatives under their terms exclusively.
+ *
+ * - Alternatively you can choose to apply the terms of the "GPL" (see
+ * below) to this - and only this - piece of code or your derivative works.
+ * Note that in no case your choice can have any impact on any other
+ * source code of the MAME project, or binary, or executable, be it closely
+ * or losely related to this piece of code.
+ *
+ * - At your choice you are also free to remove either licensing terms from
+ * this file and continue to use it under only one of the two licenses. Do this
+ * if you think that licenses are not compatible (enough) for you, or if you
+ * consider either license 'too restrictive' or 'too free'.
+ *
+ * - GPL (GNU General Public License)
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Revisions:
+ *
+ * xx-xx-2002 Acho A. Tang
+ *
+ * - 8085 emulation was in fact never used. It's been treated as a plain 8080.
+ * - protected IRQ0 vector from being overwritten
+ * - modified interrupt handler to properly process 8085-specific IRQ's
+ * - corrected interrupt masking, RIM and SIM behaviors according to Intel's documentation
+ *
+ * 20-Jul-2002 Krzysztof Strzecha
+ *
+ * - SBB r instructions should affect parity flag.
+ * Fixed only for non x86 asm version (#define i8080_EXACT 1).
+ * There are probably more opcodes which should affect this flag, but don't.
+ * - JPO nnnn and JPE nnnn opcodes in disassembler were misplaced. Fixed.
+ * - Undocumented i8080 opcodes added:
+ * 08h, 10h, 18h, 20h, 28h, 30h, 38h - NOP
+ * 0CBh - JMP
+ * 0D9h - RET
+ * 0DDh, 0EDh, 0FDh - CALL
+ * Thanks for the info go to Anton V. Ignatichev.
+ *
+ * 08-Dec-2002 Krzysztof Strzecha
+ *
+ * - ADC r instructions should affect parity flag.
+ * Fixed only for non x86 asm version (#define i8080_EXACT 1).
+ * There are probably more opcodes which should affect this flag, but don't.
+ *
+ * 05-Sep-2003 Krzysztof Strzecha
+ *
+ * - INR r, DCR r, ADD r, SUB r, CMP r instructions should affect parity flag.
+ * Fixed only for non x86 asm version (#define i8080_EXACT 1).
+ *
+ * 23-Dec-2006 Tomasz Slanina
+ *
+ * - SIM fixed
+ *
+ * 28-Jan-2007 Zsolt Vasvari
+ *
+ * - Removed archaic i8080_EXACT flag.
+ *
+ * 08-June-2008 Miodrag Milanovic
+ *
+ * - Flag setting fix for some instructions and cycle count update
+ *
+ * August 2009, hap
+ *
+ * - removed DAA table
+ * - fixed accidental double memory reads due to macro overuse
+ * - fixed cycle deduction on unconditional CALL / RET
+ * - added cycle tables and cleaned up big switch source layout (1 tab = 4 spaces)
+ * - removed HLT cycle eating (earlier, HLT after EI could theoretically fail)
+ * - fixed parity flag on add/sub/cmp
+ * - renamed temp register XX to official name WZ
+ * - renamed flags from Z80 style S Z Y H X V N C to S Z X5 H X3 P V C, and
+ * fixed X5 / V flags where accidentally broken due to flag names confusion
+ *
+ * 21-Aug-2009, Curt Coder
+ *
+ * - added 8080A variant
+ * - refactored callbacks to use devcb
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "i8085.h"
+#include "i8085cpu.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#define CPUTYPE_8080 0
+#define CPUTYPE_8085 1
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _i8085_state i8085_state;
+struct _i8085_state
+{
+ i8085_config config;
+
+ devcb_resolved_write8 out_status_func;
+ devcb_resolved_write_line out_inte_func;
+ devcb_resolved_read_line in_sid_func;
+ devcb_resolved_write_line out_sod_func;
+
+ int cputype; /* 0 8080, 1 8085A */
+ PAIR PC,SP,AF,BC,DE,HL,WZ;
+ UINT8 HALT;
+ UINT8 IM; /* interrupt mask (8085A only) */
+ UINT8 STATUS; /* status word */
+
+ UINT8 after_ei; /* post-EI processing; starts at 2, check for ints at 0 */
+ UINT8 nmi_state; /* raw NMI line state */
+ UINT8 irq_state[4]; /* raw IRQ line states */
+ UINT8 trap_pending; /* TRAP interrupt latched? */
+ UINT8 trap_im_copy; /* copy of IM register when TRAP was taken */
+ UINT8 sod_state; /* state of the SOD line */
+
+ UINT8 ietemp; /* import/export temp space */
+
+ device_irq_acknowledge_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define IS_8080(c) ((c)->cputype == CPUTYPE_8080)
+#define IS_8085(c) ((c)->cputype == CPUTYPE_8085)
+
+
+
+/***************************************************************************
+ STATIC TABLES
+***************************************************************************/
+
+/* cycles lookup */
+static const UINT8 lut_cycles_8080[256]={
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+/* 0 */ 4, 10,7, 5, 5, 5, 7, 4, 4, 10,7, 5, 5, 5, 7, 4,
+/* 1 */ 4, 10,7, 5, 5, 5, 7, 4, 4, 10,7, 5, 5, 5, 7, 4,
+/* 2 */ 4, 10,16,5, 5, 5, 7, 4, 4, 10,16,5, 5, 5, 7, 4,
+/* 3 */ 4, 10,13,5, 10,10,10,4, 4, 10,13,5, 5, 5, 7, 4,
+/* 4 */ 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 5 */ 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 6 */ 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 7 */ 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 8 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 9 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* A */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* B */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* C */ 5, 10,10,10,11,11,7, 11,5, 10,10,10,11,11,7, 11,
+/* D */ 5, 10,10,10,11,11,7, 11,5, 10,10,10,11,11,7, 11,
+/* E */ 5, 10,10,18,11,11,7, 11,5, 5, 10,5, 11,11,7, 11,
+/* F */ 5, 10,10,4, 11,11,7, 11,5, 5, 10,4, 11,11,7, 11 };
+static const UINT8 lut_cycles_8085[256]={
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+/* 0 */ 4, 10,7, 6, 4, 4, 7, 4, 10,10,7, 6, 4, 4, 7, 4,
+/* 1 */ 7, 10,7, 6, 4, 4, 7, 4, 10,10,7, 6, 4, 4, 7, 4,
+/* 2 */ 7, 10,16,6, 4, 4, 7, 4, 10,10,16,6, 4, 4, 7, 4,
+/* 3 */ 7, 10,13,6, 10,10,10,4, 10,10,13,6, 4, 4, 7, 4,
+/* 4 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 5 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 6 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 7 */ 7, 7, 7, 7, 7, 7, 5, 7, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 8 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 9 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* A */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* B */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* C */ 6, 10,10,10,11,12,7, 12,6, 10,10,12,11,11,7, 12,
+/* D */ 6, 10,10,10,11,12,7, 12,6, 10,10,10,11,10,7, 12,
+/* E */ 6, 10,10,16,11,12,7, 12,6, 6, 10,5, 11,10,7, 12,
+/* F */ 6, 10,10,4, 11,12,7, 12,6, 6, 10,4, 11,10,7, 12 };
+
+/* special cases (partially taken care of elsewhere):
+ base c taken? not taken?
+M_RET 8080 5 +6(11) -0 (conditional)
+M_RET 8085 6 +6(12) -0 (conditional)
+M_JMP 8080 10 +0 -0
+M_JMP 8085 10 +0 -3(7)
+M_CALL 8080 11 +6(17) -0
+M_CALL 8085 11 +7(18) -2(9)
+
+*/
+static UINT8 lut_cycles[256];
+
+/* flags lookup */
+static UINT8 ZS[256];
+static UINT8 ZSP[256];
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void execute_one(i8085_state *cpustate, int opcode);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE i8085_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I8080 ||
+ device->type() == I8080A||
+ device->type() == I8085A);
+ return (i8085_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void set_sod(i8085_state *cpustate, int state)
+{
+ if (state != 0 && cpustate->sod_state == 0)
+ {
+ cpustate->sod_state = 1;
+ cpustate->out_sod_func(cpustate->sod_state);
+ }
+ else if (state == 0 && cpustate->sod_state != 0)
+ {
+ cpustate->sod_state = 0;
+ cpustate->out_sod_func(cpustate->sod_state);
+ }
+}
+
+
+INLINE void set_inte(i8085_state *cpustate, int state)
+{
+ if (state != 0 && (cpustate->IM & IM_IE) == 0)
+ {
+ cpustate->IM |= IM_IE;
+ cpustate->out_inte_func(1);
+ }
+ else if (state == 0 && (cpustate->IM & IM_IE) != 0)
+ {
+ cpustate->IM &= ~IM_IE;
+ cpustate->out_inte_func(0);
+ }
+}
+
+
+INLINE void set_status(i8085_state *cpustate, UINT8 status)
+{
+ if (status != cpustate->STATUS)
+ cpustate->out_status_func(0, status);
+
+ cpustate->STATUS = status;
+}
+
+
+INLINE UINT8 get_rim_value(i8085_state *cpustate)
+{
+ UINT8 result = cpustate->IM;
+ int sid = cpustate->in_sid_func();
+
+ /* copy live RST5.5 and RST6.5 states */
+ result &= ~(IM_I65 | IM_I55);
+ if (cpustate->irq_state[I8085_RST65_LINE]) result |= IM_I65;
+ if (cpustate->irq_state[I8085_RST55_LINE]) result |= IM_I55;
+
+ /* fetch the SID bit if we have a callback */
+ result = (result & 0x7f) | (sid ? 0x80 : 0);
+
+ return result;
+}
+
+
+INLINE void break_halt_for_interrupt(i8085_state *cpustate)
+{
+ /* de-halt if necessary */
+ if (cpustate->HALT)
+ {
+ cpustate->PC.w.l++;
+ cpustate->HALT = 0;
+ set_status(cpustate, 0x26); /* int ack while halt */
+ }
+ else
+ set_status(cpustate, 0x23); /* int ack */
+}
+
+
+INLINE UINT8 ROP(i8085_state *cpustate)
+{
+ set_status(cpustate, 0xa2); // instruction fetch
+ return cpustate->direct->read_decrypted_byte(cpustate->PC.w.l++);
+}
+
+INLINE UINT8 ARG(i8085_state *cpustate)
+{
+ return cpustate->direct->read_raw_byte(cpustate->PC.w.l++);
+}
+
+INLINE UINT16 ARG16(i8085_state *cpustate)
+{
+ UINT16 w;
+ w = cpustate->direct->read_raw_byte(cpustate->PC.d);
+ cpustate->PC.w.l++;
+ w += cpustate->direct->read_raw_byte(cpustate->PC.d) << 8;
+ cpustate->PC.w.l++;
+ return w;
+}
+
+INLINE UINT8 RM(i8085_state *cpustate, UINT32 a)
+{
+ set_status(cpustate, 0x82); // memory read
+ return cpustate->program->read_byte(a);
+}
+
+INLINE void WM(i8085_state *cpustate, UINT32 a, UINT8 v)
+{
+ set_status(cpustate, 0x00); // memory write
+ cpustate->program->write_byte(a, v);
+}
+
+
+static void check_for_interrupts(i8085_state *cpustate)
+{
+ /* TRAP is the highest priority */
+ if (cpustate->trap_pending)
+ {
+ /* the first RIM after a TRAP reflects the original IE state; remember it here,
+ setting the high bit to indicate it is valid */
+ cpustate->trap_im_copy = cpustate->IM | 0x80;
+
+ /* reset the pending state */
+ cpustate->trap_pending = FALSE;
+
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, INPUT_LINE_NMI);
+
+ /* push the PC and jump to $0024 */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_TRAP;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by RST7.5 */
+ else if ((cpustate->IM & IM_I75) && !(cpustate->IM & IM_M75) && (cpustate->IM & IM_IE))
+ {
+ /* reset the pending state (which is CPU-visible via the RIM instruction) */
+ cpustate->IM &= ~IM_I75;
+
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, I8085_RST75_LINE);
+
+ /* push the PC and jump to $003C */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_RST75;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by RST6.5 */
+ else if (cpustate->irq_state[I8085_RST65_LINE] && !(cpustate->IM & IM_M65) && (cpustate->IM & IM_IE))
+ {
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, I8085_RST65_LINE);
+
+ /* push the PC and jump to $0034 */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_RST65;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by RST5.5 */
+ else if (cpustate->irq_state[I8085_RST55_LINE] && !(cpustate->IM & IM_M55) && (cpustate->IM & IM_IE))
+ {
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, I8085_RST55_LINE);
+
+ /* push the PC and jump to $002C */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_RST55;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by classic INTR */
+ else if (cpustate->irq_state[I8085_INTR_LINE] && (cpustate->IM & IM_IE))
+ {
+ UINT32 vector = 0;
+
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ vector = (*cpustate->irq_callback)(cpustate->device, I8085_INTR_LINE);
+
+ /* use the resulting vector as an opcode to execute */
+ set_inte(cpustate, 0);
+ switch (vector & 0xff0000)
+ {
+ case 0xcd0000: /* CALL nnnn */
+ cpustate->icount -= 7;
+ M_PUSH(PC);
+ case 0xc30000: /* JMP nnnn */
+ cpustate->icount -= 10;
+ cpustate->PC.d = vector & 0xffff;
+ break;
+
+ default:
+ LOG(("i8085 take int $%02x\n", vector));
+ execute_one(cpustate, vector & 0xff);
+ break;
+ }
+ }
+}
+
+
+static void execute_one(i8085_state *cpustate, int opcode)
+{
+ cpustate->icount -= lut_cycles[opcode];
+
+ switch (opcode)
+ {
+ case 0x00: break; /* NOP */
+ case 0x01: cpustate->BC.w.l = ARG16(cpustate); break; /* LXI B,nnnn */
+ case 0x02: WM(cpustate, cpustate->BC.d, cpustate->AF.b.h); break; /* STAX B */
+ case 0x03: cpustate->BC.w.l++; /* INX B */
+ if (IS_8085(cpustate)) { if (cpustate->BC.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x04: M_INR(cpustate->BC.b.h); break; /* INR B */
+ case 0x05: M_DCR(cpustate->BC.b.h); break; /* DCR B */
+ case 0x06: M_MVI(cpustate->BC.b.h); break; /* MVI B,nn */
+ case 0x07: M_RLC; break; /* RLC */
+
+ case 0x08: if (IS_8085(cpustate)) { M_DSUB(cpustate); } /* DSUB */
+ /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x09: M_DAD(BC); break; /* DAD B */
+ case 0x0a: cpustate->AF.b.h = RM(cpustate, cpustate->BC.d); break; /* LDAX B */
+ case 0x0b: cpustate->BC.w.l--; /* DCX B */
+ if (IS_8085(cpustate)) { if (cpustate->BC.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x0c: M_INR(cpustate->BC.b.l); break; /* INR C */
+ case 0x0d: M_DCR(cpustate->BC.b.l); break; /* DCR C */
+ case 0x0e: M_MVI(cpustate->BC.b.l); break; /* MVI C,nn */
+ case 0x0f: M_RRC; break; /* RRC */
+
+ case 0x10: if (IS_8085(cpustate)) { /* ASRH */
+ cpustate->AF.b.l = (cpustate->AF.b.l & ~CF) | (cpustate->HL.b.l & CF);
+ cpustate->HL.w.l = (cpustate->HL.w.l >> 1);
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x11: cpustate->DE.w.l = ARG16(cpustate); break; /* LXI D,nnnn */
+ case 0x12: WM(cpustate, cpustate->DE.d, cpustate->AF.b.h); break; /* STAX D */
+ case 0x13: cpustate->DE.w.l++; /* INX D */
+ if (IS_8085(cpustate)) { if (cpustate->DE.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x14: M_INR(cpustate->DE.b.h); break; /* INR D */
+ case 0x15: M_DCR(cpustate->DE.b.h); break; /* DCR D */
+ case 0x16: M_MVI(cpustate->DE.b.h); break; /* MVI D,nn */
+ case 0x17: M_RAL; break; /* RAL */
+
+ case 0x18: if (IS_8085(cpustate)) { /* RLDE */
+ cpustate->AF.b.l = (cpustate->AF.b.l & ~(CF | VF)) | (cpustate->DE.b.h >> 7);
+ cpustate->DE.w.l = (cpustate->DE.w.l << 1) | (cpustate->DE.w.l >> 15);
+ if (0 != (((cpustate->DE.w.l >> 15) ^ cpustate->AF.b.l) & CF)) cpustate->AF.b.l |= VF;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x19: M_DAD(DE); break; /* DAD D */
+ case 0x1a: cpustate->AF.b.h = RM(cpustate, cpustate->DE.d); break; /* LDAX D */
+ case 0x1b: cpustate->DE.w.l--; /* DCX D */
+ if (IS_8085(cpustate)) { if (cpustate->DE.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x1c: M_INR(cpustate->DE.b.l); break; /* INR E */
+ case 0x1d: M_DCR(cpustate->DE.b.l); break; /* DCR E */
+ case 0x1e: M_MVI(cpustate->DE.b.l); break; /* MVI E,nn */
+ case 0x1f: M_RAR; break; /* RAR */
+
+ case 0x20: if (IS_8085(cpustate)) { /* RIM */
+ cpustate->AF.b.h = get_rim_value(cpustate);
+
+ /* if we have remembered state from taking a TRAP, fix up the IE flag here */
+ if (cpustate->trap_im_copy & 0x80) cpustate->AF.b.h = (cpustate->AF.b.h & ~IM_IE) | (cpustate->trap_im_copy & IM_IE);
+ cpustate->trap_im_copy = 0;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x21: cpustate->HL.w.l = ARG16(cpustate); break; /* LXI H,nnnn */
+ case 0x22: cpustate->WZ.w.l = ARG16(cpustate); /* SHLD nnnn */
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.l); cpustate->WZ.w.l++;
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.h);
+ break;
+ case 0x23: cpustate->HL.w.l++; /* INX H */
+ if (IS_8085(cpustate)) { if (cpustate->HL.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x24: M_INR(cpustate->HL.b.h); break; /* INR H */
+ case 0x25: M_DCR(cpustate->HL.b.h); break; /* DCR H */
+ case 0x26: M_MVI(cpustate->HL.b.h); break; /* MVI H,nn */
+ case 0x27: cpustate->WZ.b.h = cpustate->AF.b.h; /* DAA */
+ if (cpustate->AF.b.l&VF) {
+ if ((cpustate->AF.b.l&HF) | ((cpustate->AF.b.h&0xf)>9)) cpustate->WZ.b.h-=6;
+ if ((cpustate->AF.b.l&CF) | (cpustate->AF.b.h>0x99)) cpustate->WZ.b.h-=0x60;
+ }
+ else {
+ if ((cpustate->AF.b.l&HF) | ((cpustate->AF.b.h&0xf)>9)) cpustate->WZ.b.h+=6;
+ if ((cpustate->AF.b.l&CF) | (cpustate->AF.b.h>0x99)) cpustate->WZ.b.h+=0x60;
+ }
+
+ cpustate->AF.b.l=(cpustate->AF.b.l&3) | (cpustate->AF.b.h&0x28) | (cpustate->AF.b.h>0x99) | ((cpustate->AF.b.h^cpustate->WZ.b.h)&0x10) | ZSP[cpustate->WZ.b.h];
+ cpustate->AF.b.h=cpustate->WZ.b.h;
+
+ if (IS_8080(cpustate)) cpustate->AF.b.l &= 0xd5; // Ignore not used flags
+ break;
+
+ case 0x28: if (IS_8085(cpustate)) { /* LDEH nn */
+ cpustate->WZ.d = ARG(cpustate);
+ cpustate->DE.d = (cpustate->HL.d + cpustate->WZ.d) & 0xffff;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x29: M_DAD(HL); break; /* DAD H */
+ case 0x2a: cpustate->WZ.d = ARG16(cpustate); /* LHLD nnnn */
+ cpustate->HL.b.l = RM(cpustate, cpustate->WZ.d); cpustate->WZ.w.l++;
+ cpustate->HL.b.h = RM(cpustate, cpustate->WZ.d);
+ break;
+ case 0x2b: cpustate->HL.w.l--; /* DCX H */
+ if (IS_8085(cpustate)) { if (cpustate->HL.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x2c: M_INR(cpustate->HL.b.l); break; /* INR L */
+ case 0x2d: M_DCR(cpustate->HL.b.l); break; /* DCR L */
+ case 0x2e: M_MVI(cpustate->HL.b.l); break; /* MVI L,nn */
+ case 0x2f: cpustate->AF.b.h ^= 0xff; /* CMA */
+ if (IS_8085(cpustate)) cpustate->AF.b.l |= HF | VF;
+ break;
+
+ case 0x30: if (IS_8085(cpustate)) { /* SIM */
+ /* if bit 3 is set, bits 0-2 become the new masks */
+ if (cpustate->AF.b.h & 0x08) {
+ cpustate->IM &= ~(IM_M55 | IM_M65 | IM_M75 | IM_I55 | IM_I65);
+ cpustate->IM |= cpustate->AF.b.h & (IM_M55 | IM_M65 | IM_M75);
+
+ /* update live state based on the new masks */
+ if ((cpustate->IM & IM_M55) == 0 && cpustate->irq_state[I8085_RST55_LINE]) cpustate->IM |= IM_I55;
+ if ((cpustate->IM & IM_M65) == 0 && cpustate->irq_state[I8085_RST65_LINE]) cpustate->IM |= IM_I65;
+ }
+
+ /* bit if 4 is set, the 7.5 flip-flop is cleared */
+ if (cpustate->AF.b.h & 0x10) cpustate->IM &= ~IM_I75;
+
+ /* if bit 6 is set, then bit 7 is the new SOD state */
+ if (cpustate->AF.b.h & 0x40) set_sod(cpustate, cpustate->AF.b.h >> 7);
+
+ /* check for revealed interrupts */
+ check_for_interrupts(cpustate);
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x31: cpustate->SP.w.l = ARG16(cpustate); break; /* LXI SP,nnnn */
+ case 0x32: cpustate->WZ.d = ARG16(cpustate); /* STAX nnnn */
+ WM(cpustate, cpustate->WZ.d, cpustate->AF.b.h);
+ break;
+ case 0x33: cpustate->SP.w.l++; /* INX SP */
+ if (IS_8085(cpustate)) { if (cpustate->SP.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x34: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); /* INR M */
+ M_INR(cpustate->WZ.b.l);
+ WM(cpustate, cpustate->HL.d, cpustate->WZ.b.l);
+ break;
+ case 0x35: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); /* DCR M */
+ M_DCR(cpustate->WZ.b.l);
+ WM(cpustate, cpustate->HL.d, cpustate->WZ.b.l);
+ break;
+ case 0x36: cpustate->WZ.b.l = ARG(cpustate); /* MVI M,nn */
+ WM(cpustate, cpustate->HL.d, cpustate->WZ.b.l);
+ break;
+ case 0x37: cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | CF; break; /* STC */
+
+ case 0x38: if (IS_8085(cpustate)) { /* LDES nn */
+ cpustate->WZ.d = ARG(cpustate);
+ cpustate->DE.d = (cpustate->SP.d + cpustate->WZ.d) & 0xffff;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x39: M_DAD(SP); break; /* DAD SP */
+ case 0x3a: cpustate->WZ.d = ARG16(cpustate); /* LDAX nnnn */
+ cpustate->AF.b.h = RM(cpustate, cpustate->WZ.d);
+ break;
+ case 0x3b: cpustate->SP.w.l--; /* DCX SP */
+ if (IS_8085(cpustate)) { if (cpustate->SP.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x3c: M_INR(cpustate->AF.b.h); break; /* INR A */
+ case 0x3d: M_DCR(cpustate->AF.b.h); break; /* DCR A */
+ case 0x3e: M_MVI(cpustate->AF.b.h); break; /* MVI A,nn */
+ case 0x3f: cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | (~cpustate->AF.b.l & CF); break; /* CMC */
+
+ case 0x40: break; /* MOV B,B */
+ case 0x41: cpustate->BC.b.h = cpustate->BC.b.l; break; /* MOV B,C */
+ case 0x42: cpustate->BC.b.h = cpustate->DE.b.h; break; /* MOV B,D */
+ case 0x43: cpustate->BC.b.h = cpustate->DE.b.l; break; /* MOV B,E */
+ case 0x44: cpustate->BC.b.h = cpustate->HL.b.h; break; /* MOV B,H */
+ case 0x45: cpustate->BC.b.h = cpustate->HL.b.l; break; /* MOV B,L */
+ case 0x46: cpustate->BC.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV B,M */
+ case 0x47: cpustate->BC.b.h = cpustate->AF.b.h; break; /* MOV B,A */
+
+ case 0x48: cpustate->BC.b.l = cpustate->BC.b.h; break; /* MOV C,B */
+ case 0x49: break; /* MOV C,C */
+ case 0x4a: cpustate->BC.b.l = cpustate->DE.b.h; break; /* MOV C,D */
+ case 0x4b: cpustate->BC.b.l = cpustate->DE.b.l; break; /* MOV C,E */
+ case 0x4c: cpustate->BC.b.l = cpustate->HL.b.h; break; /* MOV C,H */
+ case 0x4d: cpustate->BC.b.l = cpustate->HL.b.l; break; /* MOV C,L */
+ case 0x4e: cpustate->BC.b.l = RM(cpustate, cpustate->HL.d); break; /* MOV C,M */
+ case 0x4f: cpustate->BC.b.l = cpustate->AF.b.h; break; /* MOV C,A */
+
+ case 0x50: cpustate->DE.b.h = cpustate->BC.b.h; break; /* MOV D,B */
+ case 0x51: cpustate->DE.b.h = cpustate->BC.b.l; break; /* MOV D,C */
+ case 0x52: break; /* MOV D,D */
+ case 0x53: cpustate->DE.b.h = cpustate->DE.b.l; break; /* MOV D,E */
+ case 0x54: cpustate->DE.b.h = cpustate->HL.b.h; break; /* MOV D,H */
+ case 0x55: cpustate->DE.b.h = cpustate->HL.b.l; break; /* MOV D,L */
+ case 0x56: cpustate->DE.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV D,M */
+ case 0x57: cpustate->DE.b.h = cpustate->AF.b.h; break; /* MOV D,A */
+
+ case 0x58: cpustate->DE.b.l = cpustate->BC.b.h; break; /* MOV E,B */
+ case 0x59: cpustate->DE.b.l = cpustate->BC.b.l; break; /* MOV E,C */
+ case 0x5a: cpustate->DE.b.l = cpustate->DE.b.h; break; /* MOV E,D */
+ case 0x5b: break; /* MOV E,E */
+ case 0x5c: cpustate->DE.b.l = cpustate->HL.b.h; break; /* MOV E,H */
+ case 0x5d: cpustate->DE.b.l = cpustate->HL.b.l; break; /* MOV E,L */
+ case 0x5e: cpustate->DE.b.l = RM(cpustate, cpustate->HL.d); break; /* MOV E,M */
+ case 0x5f: cpustate->DE.b.l = cpustate->AF.b.h; break; /* MOV E,A */
+
+ case 0x60: cpustate->HL.b.h = cpustate->BC.b.h; break; /* MOV H,B */
+ case 0x61: cpustate->HL.b.h = cpustate->BC.b.l; break; /* MOV H,C */
+ case 0x62: cpustate->HL.b.h = cpustate->DE.b.h; break; /* MOV H,D */
+ case 0x63: cpustate->HL.b.h = cpustate->DE.b.l; break; /* MOV H,E */
+ case 0x64: break; /* MOV H,H */
+ case 0x65: cpustate->HL.b.h = cpustate->HL.b.l; break; /* MOV H,L */
+ case 0x66: cpustate->HL.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV H,M */
+ case 0x67: cpustate->HL.b.h = cpustate->AF.b.h; break; /* MOV H,A */
+
+ case 0x68: cpustate->HL.b.l = cpustate->BC.b.h; break; /* MOV L,B */
+ case 0x69: cpustate->HL.b.l = cpustate->BC.b.l; break; /* MOV L,C */
+ case 0x6a: cpustate->HL.b.l = cpustate->DE.b.h; break; /* MOV L,D */
+ case 0x6b: cpustate->HL.b.l = cpustate->DE.b.l; break; /* MOV L,E */
+ case 0x6c: cpustate->HL.b.l = cpustate->HL.b.h; break; /* MOV L,H */
+ case 0x6d: break; /* MOV L,L */
+ case 0x6e: cpustate->HL.b.l = RM(cpustate, cpustate->HL.d); break; /* MOV L,M */
+ case 0x6f: cpustate->HL.b.l = cpustate->AF.b.h; break; /* MOV L,A */
+
+ case 0x70: WM(cpustate, cpustate->HL.d, cpustate->BC.b.h); break; /* MOV M,B */
+ case 0x71: WM(cpustate, cpustate->HL.d, cpustate->BC.b.l); break; /* MOV M,C */
+ case 0x72: WM(cpustate, cpustate->HL.d, cpustate->DE.b.h); break; /* MOV M,D */
+ case 0x73: WM(cpustate, cpustate->HL.d, cpustate->DE.b.l); break; /* MOV M,E */
+ case 0x74: WM(cpustate, cpustate->HL.d, cpustate->HL.b.h); break; /* MOV M,H */
+ case 0x75: WM(cpustate, cpustate->HL.d, cpustate->HL.b.l); break; /* MOV M,L */
+ case 0x76: cpustate->PC.w.l--; cpustate->HALT = 1; /* HLT */
+ set_status(cpustate, 0x8a); // halt acknowledge
+ break;
+ case 0x77: WM(cpustate, cpustate->HL.d, cpustate->AF.b.h); break; /* MOV M,A */
+
+ case 0x78: cpustate->AF.b.h = cpustate->BC.b.h; break; /* MOV A,B */
+ case 0x79: cpustate->AF.b.h = cpustate->BC.b.l; break; /* MOV A,C */
+ case 0x7a: cpustate->AF.b.h = cpustate->DE.b.h; break; /* MOV A,D */
+ case 0x7b: cpustate->AF.b.h = cpustate->DE.b.l; break; /* MOV A,E */
+ case 0x7c: cpustate->AF.b.h = cpustate->HL.b.h; break; /* MOV A,H */
+ case 0x7d: cpustate->AF.b.h = cpustate->HL.b.l; break; /* MOV A,L */
+ case 0x7e: cpustate->AF.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV A,M */
+ case 0x7f: break; /* MOV A,A */
+
+ case 0x80: M_ADD(cpustate->BC.b.h); break; /* ADD B */
+ case 0x81: M_ADD(cpustate->BC.b.l); break; /* ADD C */
+ case 0x82: M_ADD(cpustate->DE.b.h); break; /* ADD D */
+ case 0x83: M_ADD(cpustate->DE.b.l); break; /* ADD E */
+ case 0x84: M_ADD(cpustate->HL.b.h); break; /* ADD H */
+ case 0x85: M_ADD(cpustate->HL.b.l); break; /* ADD L */
+ case 0x86: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ADD(cpustate->WZ.b.l); break; /* ADD M */
+ case 0x87: M_ADD(cpustate->AF.b.h); break; /* ADD A */
+
+ case 0x88: M_ADC(cpustate->BC.b.h); break; /* ADC B */
+ case 0x89: M_ADC(cpustate->BC.b.l); break; /* ADC C */
+ case 0x8a: M_ADC(cpustate->DE.b.h); break; /* ADC D */
+ case 0x8b: M_ADC(cpustate->DE.b.l); break; /* ADC E */
+ case 0x8c: M_ADC(cpustate->HL.b.h); break; /* ADC H */
+ case 0x8d: M_ADC(cpustate->HL.b.l); break; /* ADC L */
+ case 0x8e: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ADC(cpustate->WZ.b.l); break; /* ADC M */
+ case 0x8f: M_ADC(cpustate->AF.b.h); break; /* ADC A */
+
+ case 0x90: M_SUB(cpustate->BC.b.h); break; /* SUB B */
+ case 0x91: M_SUB(cpustate->BC.b.l); break; /* SUB C */
+ case 0x92: M_SUB(cpustate->DE.b.h); break; /* SUB D */
+ case 0x93: M_SUB(cpustate->DE.b.l); break; /* SUB E */
+ case 0x94: M_SUB(cpustate->HL.b.h); break; /* SUB H */
+ case 0x95: M_SUB(cpustate->HL.b.l); break; /* SUB L */
+ case 0x96: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_SUB(cpustate->WZ.b.l); break; /* SUB M */
+ case 0x97: M_SUB(cpustate->AF.b.h); break; /* SUB A */
+
+ case 0x98: M_SBB(cpustate->BC.b.h); break; /* SBB B */
+ case 0x99: M_SBB(cpustate->BC.b.l); break; /* SBB C */
+ case 0x9a: M_SBB(cpustate->DE.b.h); break; /* SBB D */
+ case 0x9b: M_SBB(cpustate->DE.b.l); break; /* SBB E */
+ case 0x9c: M_SBB(cpustate->HL.b.h); break; /* SBB H */
+ case 0x9d: M_SBB(cpustate->HL.b.l); break; /* SBB L */
+ case 0x9e: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_SBB(cpustate->WZ.b.l); break; /* SBB M */
+ case 0x9f: M_SBB(cpustate->AF.b.h); break; /* SBB A */
+
+ case 0xa0: M_ANA(cpustate->BC.b.h); break; /* ANA B */
+ case 0xa1: M_ANA(cpustate->BC.b.l); break; /* ANA C */
+ case 0xa2: M_ANA(cpustate->DE.b.h); break; /* ANA D */
+ case 0xa3: M_ANA(cpustate->DE.b.l); break; /* ANA E */
+ case 0xa4: M_ANA(cpustate->HL.b.h); break; /* ANA H */
+ case 0xa5: M_ANA(cpustate->HL.b.l); break; /* ANA L */
+ case 0xa6: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ANA(cpustate->WZ.b.l); break; /* ANA M */
+ case 0xa7: M_ANA(cpustate->AF.b.h); break; /* ANA A */
+
+ case 0xa8: M_XRA(cpustate->BC.b.h); break; /* XRA B */
+ case 0xa9: M_XRA(cpustate->BC.b.l); break; /* XRA C */
+ case 0xaa: M_XRA(cpustate->DE.b.h); break; /* XRA D */
+ case 0xab: M_XRA(cpustate->DE.b.l); break; /* XRA E */
+ case 0xac: M_XRA(cpustate->HL.b.h); break; /* XRA H */
+ case 0xad: M_XRA(cpustate->HL.b.l); break; /* XRA L */
+ case 0xae: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_XRA(cpustate->WZ.b.l); break; /* XRA M */
+ case 0xaf: M_XRA(cpustate->AF.b.h); break; /* XRA A */
+
+ case 0xb0: M_ORA(cpustate->BC.b.h); break; /* ORA B */
+ case 0xb1: M_ORA(cpustate->BC.b.l); break; /* ORA C */
+ case 0xb2: M_ORA(cpustate->DE.b.h); break; /* ORA D */
+ case 0xb3: M_ORA(cpustate->DE.b.l); break; /* ORA E */
+ case 0xb4: M_ORA(cpustate->HL.b.h); break; /* ORA H */
+ case 0xb5: M_ORA(cpustate->HL.b.l); break; /* ORA L */
+ case 0xb6: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ORA(cpustate->WZ.b.l); break; /* ORA M */
+ case 0xb7: M_ORA(cpustate->AF.b.h); break; /* ORA A */
+
+ case 0xb8: M_CMP(cpustate->BC.b.h); break; /* CMP B */
+ case 0xb9: M_CMP(cpustate->BC.b.l); break; /* CMP C */
+ case 0xba: M_CMP(cpustate->DE.b.h); break; /* CMP D */
+ case 0xbb: M_CMP(cpustate->DE.b.l); break; /* CMP E */
+ case 0xbc: M_CMP(cpustate->HL.b.h); break; /* CMP H */
+ case 0xbd: M_CMP(cpustate->HL.b.l); break; /* CMP L */
+ case 0xbe: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_CMP(cpustate->WZ.b.l); break; /* CMP M */
+ case 0xbf: M_CMP(cpustate->AF.b.h); break; /* CMP A */
+
+ case 0xc0: M_RET( !(cpustate->AF.b.l & ZF) ); break; /* RNZ */
+ case 0xc1: M_POP(BC); break; /* POP B */
+ case 0xc2: M_JMP( !(cpustate->AF.b.l & ZF) ); break; /* JNZ nnnn */
+ case 0xc3: M_JMP(1); break; /* JMP nnnn */
+ case 0xc4: M_CALL( !(cpustate->AF.b.l & ZF) ); break; /* CNZ nnnn */
+ case 0xc5: M_PUSH(BC); break; /* PUSH B */
+ case 0xc6: cpustate->WZ.b.l = ARG(cpustate); M_ADD(cpustate->WZ.b.l); break; /* ADI nn */
+ case 0xc7: M_RST(0); break; /* RST 0 */
+
+ case 0xc8: M_RET( cpustate->AF.b.l & ZF ); break; /* RZ */
+ case 0xc9: M_POP(PC); break; /* RET */
+ case 0xca: M_JMP( cpustate->AF.b.l & ZF ); break; /* JZ nnnn */
+ case 0xcb: if (IS_8085(cpustate)) { /* RST V */
+ if (cpustate->AF.b.l & VF) { M_RST(8); }
+ else cpustate->icount += 6; // RST not taken
+ } else { M_JMP(1); } /* JMP nnnn undocumented */
+ break;
+ case 0xcc: M_CALL( cpustate->AF.b.l & ZF ); break; /* CZ nnnn */
+ case 0xcd: M_CALL(1); break; /* CALL nnnn */
+ case 0xce: cpustate->WZ.b.l = ARG(cpustate); M_ADC(cpustate->WZ.b.l); break; /* ACI nn */
+ case 0xcf: M_RST(1); break; /* RST 1 */
+
+ case 0xd0: M_RET( !(cpustate->AF.b.l & CF) ); break; /* RNC */
+ case 0xd1: M_POP(DE); break; /* POP D */
+ case 0xd2: M_JMP( !(cpustate->AF.b.l & CF) ); break; /* JNC nnnn */
+ case 0xd3: M_OUT; break; /* OUT nn */
+ case 0xd4: M_CALL( !(cpustate->AF.b.l & CF) ); break; /* CNC nnnn */
+ case 0xd5: M_PUSH(DE); break; /* PUSH D */
+ case 0xd6: cpustate->WZ.b.l = ARG(cpustate); M_SUB(cpustate->WZ.b.l); break; /* SUI nn */
+ case 0xd7: M_RST(2); break; /* RST 2 */
+
+ case 0xd8: M_RET( cpustate->AF.b.l & CF ); break; /* RC */
+ case 0xd9: if (IS_8085(cpustate)) { /* SHLX */
+ cpustate->WZ.w.l = cpustate->DE.w.l;
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.l); cpustate->WZ.w.l++;
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.h);
+ } else { M_POP(PC); } /* RET undocumented */
+ break;
+ case 0xda: M_JMP( cpustate->AF.b.l & CF ); break; /* JC nnnn */
+ case 0xdb: M_IN; break; /* IN nn */
+ case 0xdc: M_CALL( cpustate->AF.b.l & CF ); break; /* CC nnnn */
+ case 0xdd: if (IS_8085(cpustate)) { M_JMP( !(cpustate->AF.b.l & X5F) ); } /* JNX nnnn */
+ else { M_CALL(1); } /* CALL nnnn undocumented */
+ break;
+ case 0xde: cpustate->WZ.b.l = ARG(cpustate); M_SBB(cpustate->WZ.b.l); break; /* SBI nn */
+ case 0xdf: M_RST(3); break; /* RST 3 */
+
+ case 0xe0: M_RET( !(cpustate->AF.b.l & PF) ); break; /* RPO */
+ case 0xe1: M_POP(HL); break; /* POP H */
+ case 0xe2: M_JMP( !(cpustate->AF.b.l & PF) ); break; /* JPO nnnn */
+ case 0xe3: M_POP(WZ); M_PUSH(HL); /* XTHL */
+ cpustate->HL.d = cpustate->WZ.d;
+ break;
+ case 0xe4: M_CALL( !(cpustate->AF.b.l & PF) ); break; /* CPO nnnn */
+ case 0xe5: M_PUSH(HL); break; /* PUSH H */
+ case 0xe6: cpustate->WZ.b.l = ARG(cpustate); M_ANA(cpustate->WZ.b.l); break; /* ANI nn */
+ case 0xe7: M_RST(4); break; /* RST 4 */
+
+ case 0xe8: M_RET( cpustate->AF.b.l & PF ); break; /* RPE */
+ case 0xe9: cpustate->PC.d = cpustate->HL.w.l; break; /* PCHL */
+ case 0xea: M_JMP( cpustate->AF.b.l & PF ); break; /* JPE nnnn */
+ case 0xeb: cpustate->WZ.d = cpustate->DE.d; /* XCHG */
+ cpustate->DE.d = cpustate->HL.d;
+ cpustate->HL.d = cpustate->WZ.d;
+ break;
+ case 0xec: M_CALL( cpustate->AF.b.l & PF ); break; /* CPE nnnn */
+ case 0xed: if (IS_8085(cpustate)) { /* LHLX */
+ cpustate->WZ.w.l = cpustate->DE.w.l;
+ cpustate->HL.b.l = RM(cpustate, cpustate->WZ.d); cpustate->WZ.w.l++;
+ cpustate->HL.b.h = RM(cpustate, cpustate->WZ.d);
+ } else { M_CALL(1); } /* CALL nnnn undocumented */
+ break;
+ case 0xee: cpustate->WZ.b.l = ARG(cpustate); M_XRA(cpustate->WZ.b.l); break; /* XRI nn */
+ case 0xef: M_RST(5); break; /* RST 5 */
+
+ case 0xf0: M_RET( !(cpustate->AF.b.l&SF) ); break; /* RP */
+ case 0xf1: M_POP(AF); break; /* POP A */
+ case 0xf2: M_JMP( !(cpustate->AF.b.l & SF) ); break; /* JP nnnn */
+ case 0xf3: set_inte(cpustate, 0); break; /* DI */
+ case 0xf4: M_CALL( !(cpustate->AF.b.l & SF) ); break; /* CP nnnn */
+ case 0xf5: M_PUSH(AF); break; /* PUSH A */
+ case 0xf6: cpustate->WZ.b.l = ARG(cpustate); M_ORA(cpustate->WZ.b.l); break; /* ORI nn */
+ case 0xf7: M_RST(6); break; /* RST 6 */
+
+ case 0xf8: M_RET( cpustate->AF.b.l & SF ); break; /* RM */
+ case 0xf9: cpustate->SP.d = cpustate->HL.d; break; /* SPHL */
+ case 0xfa: M_JMP( cpustate->AF.b.l & SF ); break; /* JM nnnn */
+ case 0xfb: set_inte(cpustate, 1); cpustate->after_ei = 2; break; /* EI */
+ case 0xfc: M_CALL( cpustate->AF.b.l & SF ); break; /* CM nnnn */
+ case 0xfd: if (IS_8085(cpustate)) { M_JMP( cpustate->AF.b.l & X5F ); } /* JX nnnn */
+ else { M_CALL(1); } /* CALL nnnn undocumented */
+ break;
+ case 0xfe: cpustate->WZ.b.l = ARG(cpustate); M_CMP(cpustate->WZ.b.l); break; /* CPI nn */
+ case 0xff: M_RST(7); break; /* RST 7 */
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+
+static CPU_EXECUTE( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ /* check for TRAPs before diving in (can't do others because of after_ei) */
+ if (cpustate->trap_pending || cpustate->after_ei == 0)
+ check_for_interrupts(cpustate);
+
+ do
+ {
+ debugger_instruction_hook(device, cpustate->PC.d);
+
+ /* the instruction after an EI does not take an interrupt, so
+ we cannot check immediately; handle post-EI behavior here */
+ if (cpustate->after_ei != 0 && --cpustate->after_ei == 0)
+ check_for_interrupts(cpustate);
+
+ /* here we go... */
+ execute_one(cpustate, ROP(cpustate));
+
+ } while (cpustate->icount > 0);
+}
+
+
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+
+static void init_tables (int type)
+{
+ UINT8 zs;
+ int i, p;
+ for (i = 0; i < 256; i++)
+ {
+ /* cycles */
+ lut_cycles[i] = type?lut_cycles_8085[i]:lut_cycles_8080[i];
+
+ /* flags */
+ zs = 0;
+ if (i==0) zs |= ZF;
+ if (i&128) zs |= SF;
+ p = 0;
+ if (i&1) ++p;
+ if (i&2) ++p;
+ if (i&4) ++p;
+ if (i&8) ++p;
+ if (i&16) ++p;
+ if (i&32) ++p;
+ if (i&64) ++p;
+ if (i&128) ++p;
+ ZS[i] = zs;
+ ZSP[i] = zs | ((p&1) ? 0 : PF);
+ }
+}
+
+
+static void init_808x_common(legacy_cpu_device *device, device_irq_acknowledge_callback irqcallback, int type)
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ init_tables(type);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(I8085_PC, "PC", cpustate->PC.w.l);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->PC.w.l).noshow();
+ state->state_add(I8085_SP, "SP", cpustate->SP.w.l);
+ state->state_add(STATE_GENSP, "GENSP", cpustate->SP.w.l).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->AF.b.l).noshow().formatstr("%8s");
+ state->state_add(I8085_A, "A", cpustate->AF.b.h).noshow();
+ state->state_add(I8085_B, "B", cpustate->BC.b.h).noshow();
+ state->state_add(I8085_C, "C", cpustate->BC.b.l).noshow();
+ state->state_add(I8085_D, "D", cpustate->DE.b.h).noshow();
+ state->state_add(I8085_E, "E", cpustate->DE.b.l).noshow();
+ state->state_add(I8085_F, "F", cpustate->AF.b.l).noshow();
+ state->state_add(I8085_H, "H", cpustate->HL.b.h).noshow();
+ state->state_add(I8085_L, "L", cpustate->HL.b.l).noshow();
+ state->state_add(I8085_AF, "AF", cpustate->AF.w.l);
+ state->state_add(I8085_BC, "BC", cpustate->BC.w.l);
+ state->state_add(I8085_DE, "DE", cpustate->DE.w.l);
+ state->state_add(I8085_HL, "HL", cpustate->HL.w.l);
+ state->state_add(I8085_STATUS, "STATUS", cpustate->STATUS);
+ state->state_add(I8085_SOD, "SOD", cpustate->sod_state).mask(0x1);
+ state->state_add(I8085_SID, "SID", cpustate->ietemp).mask(0x1).callimport().callexport();
+ state->state_add(I8085_INTE, "INTE", cpustate->ietemp).mask(0x1).callimport().callexport();
+ }
+
+ if (device->static_config() != NULL)
+ cpustate->config = *(i8085_config *)device->static_config();
+ cpustate->cputype = type;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ /* resolve callbacks */
+ cpustate->out_status_func.resolve(cpustate->config.out_status_func, *device);
+ cpustate->out_inte_func.resolve(cpustate->config.out_inte_func, *device);
+ cpustate->in_sid_func.resolve(cpustate->config.in_sid_func, *device);
+ cpustate->out_sod_func.resolve(cpustate->config.out_sod_func, *device);
+
+ /* register for state saving */
+ device->save_item(NAME(cpustate->PC.w.l));
+ device->save_item(NAME(cpustate->SP.w.l));
+ device->save_item(NAME(cpustate->AF.w.l));
+ device->save_item(NAME(cpustate->BC.w.l));
+ device->save_item(NAME(cpustate->DE.w.l));
+ device->save_item(NAME(cpustate->HL.w.l));
+ device->save_item(NAME(cpustate->HALT));
+ device->save_item(NAME(cpustate->IM));
+ device->save_item(NAME(cpustate->STATUS));
+ device->save_item(NAME(cpustate->after_ei));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->trap_pending));
+ device->save_item(NAME(cpustate->trap_im_copy));
+ device->save_item(NAME(cpustate->sod_state));
+}
+
+static CPU_INIT( i8080 )
+{
+ init_808x_common(device, irqcallback, CPUTYPE_8080);
+}
+
+static CPU_INIT( i8085 )
+{
+ init_808x_common(device, irqcallback, CPUTYPE_8085);
+}
+
+
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+static CPU_RESET( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ cpustate->PC.d = 0;
+ cpustate->HALT = 0;
+ cpustate->IM &= ~IM_I75;
+ cpustate->IM |= IM_M55 | IM_M65 | IM_M75;
+ cpustate->after_ei = FALSE;
+ cpustate->trap_pending = FALSE;
+ cpustate->trap_im_copy = 0;
+ set_inte(cpustate, 0);
+ set_sod(cpustate, 0);
+}
+
+
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+static CPU_IMPORT_STATE( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8085_SID:
+ if (cpustate->ietemp)
+ cpustate->IM |= IM_SID;
+ else
+ cpustate->IM &= ~IM_SID;
+ break;
+
+ case I8085_INTE:
+ if (cpustate->ietemp)
+ cpustate->IM |= IM_IE;
+ else
+ cpustate->IM &= ~IM_IE;
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(i808x) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STATE( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8085_SID:
+ {
+ int sid = cpustate->in_sid_func();
+
+ cpustate->ietemp = ((cpustate->IM & IM_SID) != 0);
+ cpustate->ietemp = (sid != 0);
+ }
+ break;
+
+ case I8085_INTE:
+ cpustate->ietemp = ((cpustate->IM & IM_IE) != 0);
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(i808x) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ cpustate->AF.b.l & 0x80 ? 'S':'.',
+ cpustate->AF.b.l & 0x40 ? 'Z':'.',
+ cpustate->AF.b.l & 0x20 ? 'X':'.', // X5
+ cpustate->AF.b.l & 0x10 ? 'H':'.',
+ cpustate->AF.b.l & 0x08 ? '?':'.',
+ cpustate->AF.b.l & 0x04 ? 'P':'.',
+ cpustate->AF.b.l & 0x02 ? 'V':'.',
+ cpustate->AF.b.l & 0x01 ? 'C':'.');
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ COMMON SET INFO
+***************************************************************************/
+
+static void i808x_set_irq_line(i8085_state *cpustate, int irqline, int state)
+{
+ int newstate = (state != CLEAR_LINE);
+
+ /* NMI is edge-triggered */
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (!cpustate->nmi_state && newstate)
+ cpustate->trap_pending = TRUE;
+ cpustate->nmi_state = newstate;
+ }
+
+ /* RST7.5 is edge-triggered */
+ else if (irqline == I8085_RST75_LINE)
+ {
+ if (!cpustate->irq_state[I8085_RST75_LINE] && newstate)
+ cpustate->IM |= IM_I75;
+ cpustate->irq_state[I8085_RST75_LINE] = newstate;
+ }
+
+ /* remaining sources are level triggered */
+ else if (irqline < ARRAY_LENGTH(cpustate->irq_state))
+ cpustate->irq_state[irqline] = state;
+}
+
+
+static CPU_SET_INFO( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + I8085_INTR_LINE:
+ case CPUINFO_INT_INPUT_STATE + I8085_RST55_LINE:
+ case CPUINFO_INT_INPUT_STATE + I8085_RST65_LINE:
+ case CPUINFO_INT_INPUT_STATE + I8085_RST75_LINE:
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ i808x_set_irq_line(cpustate, state - CPUINFO_INT_INPUT_STATE, info->i);
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ 8085/COMMON GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8085 )
+{
+ i8085_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(i8085_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; 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 = 2; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 4; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i808x); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8085); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i808x); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i808x); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8085); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(i808x); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(i808x); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(i808x); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ 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, "8085A"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-85"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break;
+ break;
+ }
+}
+
+
+/***************************************************************************
+ 8080-SPECIFIC GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8080 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8080); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8080"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-80"); break;
+
+ default: CPU_GET_INFO_CALL(i8085); break;
+ }
+}
+
+
+/***************************************************************************
+ 8080A-SPECIFIC GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8080a )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8080); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8080A"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-80"); break;
+
+ default: CPU_GET_INFO_CALL(i8085); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I8080, i8080);
+DEFINE_LEGACY_CPU_DEVICE(I8080A, i8080a);
+DEFINE_LEGACY_CPU_DEVICE(I8085A, i8085);