summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/z8/z8ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/z8/z8ops.c')
-rw-r--r--trunk/src/emu/cpu/z8/z8ops.c746
1 files changed, 746 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/z8/z8ops.c b/trunk/src/emu/cpu/z8/z8ops.c
new file mode 100644
index 00000000000..43ef894235e
--- /dev/null
+++ b/trunk/src/emu/cpu/z8/z8ops.c
@@ -0,0 +1,746 @@
+/**********************************************************************
+
+ Zilog Z8 Single-Chip MCU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define read(_reg) register_read(cpustate, _reg)
+#define r(_data) get_working_register(cpustate, _data)
+#define Ir(_data) get_intermediate_register(cpustate, get_working_register(cpustate, _data))
+#define R get_register(cpustate, fetch(cpustate))
+#define IR get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
+#define RR get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
+#define IM fetch(cpustate)
+#define flag(_flag) ((cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS##_##_flag) ? 1 : 0)
+
+#define mode_r1_r2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = r(dst_src >> 4);\
+ UINT8 src = read(r(dst_src & 0x0f));\
+ _func(cpustate, dst, src);
+
+#define mode_r1_Ir2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = r(dst_src >> 4);\
+ UINT8 src = read(Ir(dst_src & 0x0f));\
+ _func(cpustate, dst, src);
+
+#define mode_R2_R1(_func) \
+ UINT8 src = read(R);\
+ UINT8 dst = R;\
+ _func(cpustate, dst, src);
+
+#define mode_IR2_R1(_func) \
+ UINT8 src = read(R);\
+ UINT8 dst = IR;\
+ _func(cpustate, dst, src);
+
+#define mode_R1_IM(_func) \
+ UINT8 dst = R;\
+ UINT8 src = IM;\
+ _func(cpustate, dst, src);
+
+#define mode_IR1_IM(_func) \
+ UINT8 dst = IR;\
+ UINT8 src = IM;\
+ _func(cpustate, dst, src);
+
+#define mode_r1(_func) \
+ UINT8 dst = r(opcode >> 4);\
+ _func(cpustate, dst);
+
+#define mode_R1(_func) \
+ UINT8 dst = R;\
+ _func(cpustate, dst);
+
+#define mode_RR1(_func) \
+ UINT8 dst = R;\
+ _func(cpustate, dst);
+
+#define mode_IR1(_func) \
+ UINT8 dst = IR;\
+ _func(cpustate, dst);
+
+#define mode_r1_IM(_func) \
+ UINT8 dst = r(opcode >> 4);\
+ UINT8 src = IM;\
+ _func(cpustate, dst, src);
+
+#define mode_r1_R2(_func) \
+ UINT8 dst = r(opcode >> 4);\
+ UINT8 src = read(R);\
+ _func(cpustate, dst, src);
+
+#define mode_r2_R1(_func) \
+ UINT8 src = read(r(opcode >> 4));\
+ UINT8 dst = R;\
+ _func(cpustate, dst, src);
+
+#define mode_Ir1_r2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = Ir(dst_src >> 4);\
+ UINT8 src = read(r(dst_src & 0x0f));\
+ _func(cpustate, dst, src);
+
+#define mode_R2_IR1(_func) \
+ UINT8 src = read(R);\
+ UINT8 dst = IR;\
+ _func(cpustate, dst, src);
+
+#define mode_r1_x_R2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = r(dst_src >> 4);\
+ UINT8 src = read(read(r(dst_src & 0x0f)) + R);\
+ _func(cpustate, dst, src);
+
+#define mode_r2_x_R1(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = R + read(r(dst_src & 0x0f));\
+ UINT8 src = read(r(dst_src >> 4));\
+ _func(cpustate, dst, src);
+
+/***************************************************************************
+ LOAD INSTRUCTIONS
+***************************************************************************/
+
+static void clear(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- 0 */
+ register_write(cpustate, dst, 0);
+}
+
+INSTRUCTION( clr_R1 ) { mode_R1(clear) }
+INSTRUCTION( clr_IR1 ) { mode_IR1(clear) }
+
+static void load(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- src */
+ register_write(cpustate, dst, src);
+}
+
+INSTRUCTION( ld_r1_IM ) { mode_r1_IM(load) }
+INSTRUCTION( ld_r1_R2 ) { mode_r1_R2(load) }
+INSTRUCTION( ld_r2_R1 ) { mode_r2_R1(load) }
+INSTRUCTION( ld_Ir1_r2 ) { mode_Ir1_r2(load) }
+INSTRUCTION( ld_R2_IR1 ) { mode_R2_IR1(load) }
+INSTRUCTION( ld_r1_x_R2 ) { mode_r1_x_R2(load) }
+INSTRUCTION( ld_r2_x_R1 ) { mode_r2_x_R1(load) }
+
+INSTRUCTION( ld_r1_r2 ) { mode_r1_r2(load) }
+INSTRUCTION( ld_r1_Ir2 ) { mode_r1_Ir2(load) }
+INSTRUCTION( ld_R2_R1 ) { mode_R2_R1(load) }
+INSTRUCTION( ld_IR2_R1 ) { mode_IR2_R1(load) }
+INSTRUCTION( ld_R1_IM ) { mode_R1_IM(load) }
+INSTRUCTION( ld_IR1_IM ) { mode_IR1_IM(load) }
+
+static void load_from_memory(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 dst = get_working_register(cpustate, operands >> 4);
+ UINT8 src = get_working_register(cpustate, operands & 0x0f);
+
+ UINT16 address = register_pair_read(cpustate, src);
+ UINT8 data = cpustate->direct->read_decrypted_byte(address);
+
+ register_write(cpustate, dst, data);
+}
+
+static void load_to_memory(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 src = get_working_register(cpustate, operands >> 4);
+ UINT8 dst = get_working_register(cpustate, operands & 0x0f);
+
+ UINT16 address = register_pair_read(cpustate, dst);
+ UINT8 data = register_read(cpustate, src);
+
+ cpustate->program->write_byte(address, data);
+}
+
+static void load_from_memory_autoinc(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 dst = get_working_register(cpustate, operands >> 4);
+ UINT8 real_dst = get_intermediate_register(cpustate, dst);
+ UINT8 src = get_working_register(cpustate, operands & 0x0f);
+
+ UINT16 address = register_pair_read(cpustate, src);
+ UINT8 data = cpustate->direct->read_decrypted_byte(address);
+
+ register_write(cpustate, real_dst, data);
+
+ register_write(cpustate, dst, real_dst + 1);
+ register_pair_write(cpustate, src, address + 1);
+}
+
+static void load_to_memory_autoinc(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 src = get_working_register(cpustate, operands >> 4);
+ UINT8 dst = get_working_register(cpustate, operands & 0x0f);
+ UINT8 real_src = get_intermediate_register(cpustate, src);
+
+ UINT16 address = register_pair_read(cpustate, dst);
+ UINT8 data = register_read(cpustate, real_src);
+
+ cpustate->program->write_byte(address, data);
+
+ register_pair_write(cpustate, dst, address + 1);
+ register_write(cpustate, src, real_src + 1);
+}
+
+INSTRUCTION( ldc_r1_Irr2 ) { load_from_memory(cpustate, cpustate->program); }
+INSTRUCTION( ldc_r2_Irr1 ) { load_to_memory(cpustate, cpustate->program); }
+INSTRUCTION( ldci_Ir1_Irr2 ) { load_from_memory_autoinc(cpustate, cpustate->program); }
+INSTRUCTION( ldci_Ir2_Irr1 ) { load_to_memory_autoinc(cpustate, cpustate->program); }
+INSTRUCTION( lde_r1_Irr2 ) { load_from_memory(cpustate, cpustate->data); }
+INSTRUCTION( lde_r2_Irr1 ) { load_to_memory(cpustate, cpustate->data); }
+INSTRUCTION( ldei_Ir1_Irr2 ) { load_from_memory_autoinc(cpustate, cpustate->data); }
+INSTRUCTION( ldei_Ir2_Irr1 ) { load_to_memory_autoinc(cpustate, cpustate->data); }
+
+static void pop(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- @SP
+ SP <- SP + 1 */
+ register_write(cpustate, dst, stack_pop_byte(cpustate));
+}
+
+INSTRUCTION( pop_R1 ) { mode_R1(pop) }
+INSTRUCTION( pop_IR1 ) { mode_IR1(pop) }
+
+static void push(z8_state *cpustate, UINT8 src)
+{
+ /* SP <- SP - 1
+ @SP <- src */
+ stack_push_byte(cpustate, read(src));
+}
+
+INSTRUCTION( push_R2 ) { mode_R1(push) }
+INSTRUCTION( push_IR2 ) { mode_IR1(push) }
+
+/***************************************************************************
+ ARITHMETIC INSTRUCTIONS
+***************************************************************************/
+
+static void add_carry(z8_state *cpustate, UINT8 dst, INT8 src)
+{
+ /* dst <- dst + src + C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data + src + flag(C);
+
+ set_flag_c(new_data & 0x100);
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
+ set_flag_d(0);
+ set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( adc_r1_r2 ) { mode_r1_r2(add_carry) }
+INSTRUCTION( adc_r1_Ir2 ) { mode_r1_Ir2(add_carry) }
+INSTRUCTION( adc_R2_R1 ) { mode_R2_R1(add_carry) }
+INSTRUCTION( adc_IR2_R1 ) { mode_IR2_R1(add_carry) }
+INSTRUCTION( adc_R1_IM ) { mode_R1_IM(add_carry) }
+INSTRUCTION( adc_IR1_IM ) { mode_IR1_IM(add_carry) }
+
+static void add(z8_state *cpustate, UINT8 dst, INT8 src)
+{
+ /* dst <- dst + src */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data + src;
+
+ set_flag_c(new_data & 0x100);
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
+ set_flag_d(0);
+ set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( add_r1_r2 ) { mode_r1_r2(add) }
+INSTRUCTION( add_r1_Ir2 ) { mode_r1_Ir2(add) }
+INSTRUCTION( add_R2_R1 ) { mode_R2_R1(add) }
+INSTRUCTION( add_IR2_R1 ) { mode_IR2_R1(add) }
+INSTRUCTION( add_R1_IM ) { mode_R1_IM(add) }
+INSTRUCTION( add_IR1_IM ) { mode_IR1_IM(add) }
+
+static void compare(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst - src */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data - src;
+
+ set_flag_c(!(new_data & 0x100));
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
+}
+
+INSTRUCTION( cp_r1_r2 ) { mode_r1_r2(compare) }
+INSTRUCTION( cp_r1_Ir2 ) { mode_r1_Ir2(compare) }
+INSTRUCTION( cp_R2_R1 ) { mode_R2_R1(compare) }
+INSTRUCTION( cp_IR2_R1 ) { mode_IR2_R1(compare) }
+INSTRUCTION( cp_R1_IM ) { mode_R1_IM(compare) }
+INSTRUCTION( cp_IR1_IM ) { mode_IR1_IM(compare) }
+
+static void decimal_adjust(z8_state *cpustate, UINT8 dst)
+{
+}
+
+INSTRUCTION( da_R1 ) { mode_R1(decimal_adjust) }
+INSTRUCTION( da_IR1 ) { mode_IR1(decimal_adjust) }
+
+static void decrement(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst - 1 */
+ UINT8 data = register_read(cpustate, dst) - 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(data == 0x7f);
+
+ register_write(cpustate, dst, data);
+}
+
+INSTRUCTION( dec_R1 ) { mode_R1(decrement) }
+INSTRUCTION( dec_IR1 ) { mode_IR1(decrement) }
+
+static void decrement_word(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst - 1 */
+ UINT16 data = register_pair_read(cpustate, dst) - 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x8000);
+ set_flag_v(data == 0x7fff);
+
+ register_pair_write(cpustate, dst, data);
+}
+
+INSTRUCTION( decw_RR1 ) { mode_RR1(decrement_word) }
+INSTRUCTION( decw_IR1 ) { mode_IR1(decrement_word) }
+
+static void increment(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst + 1 */
+ UINT8 data = register_read(cpustate, dst) + 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(data == 0x80);
+
+ register_write(cpustate, dst, data);
+}
+
+INSTRUCTION( inc_r1 ) { mode_r1(increment) }
+INSTRUCTION( inc_R1 ) { mode_R1(increment) }
+INSTRUCTION( inc_IR1 ) { mode_IR1(increment) }
+
+static void increment_word(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst + 1 */
+ UINT16 data = register_pair_read(cpustate, dst) + 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x8000);
+ set_flag_v(data == 0x8000);
+
+ register_pair_write(cpustate, dst, data);
+}
+
+INSTRUCTION( incw_RR1 ) { mode_RR1(increment_word) }
+INSTRUCTION( incw_IR1 ) { mode_IR1(increment_word) }
+
+static void subtract_carry(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst - src - C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data - src;
+
+ set_flag_c(!(new_data & 0x100));
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
+ set_flag_d(1);
+ set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( sbc_r1_r2 ) { mode_r1_r2(subtract_carry) }
+INSTRUCTION( sbc_r1_Ir2 ) { mode_r1_Ir2(subtract_carry) }
+INSTRUCTION( sbc_R2_R1 ) { mode_R2_R1(subtract_carry) }
+INSTRUCTION( sbc_IR2_R1 ) { mode_IR2_R1(subtract_carry) }
+INSTRUCTION( sbc_R1_IM ) { mode_R1_IM(subtract_carry) }
+INSTRUCTION( sbc_IR1_IM ) { mode_IR1_IM(subtract_carry) }
+
+static void subtract(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst - src */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data - src;
+
+ set_flag_c(!(new_data & 0x100));
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
+ set_flag_d(1);
+ set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( sub_r1_r2 ) { mode_r1_r2(subtract) }
+INSTRUCTION( sub_r1_Ir2 ) { mode_r1_Ir2(subtract) }
+INSTRUCTION( sub_R2_R1 ) { mode_R2_R1(subtract) }
+INSTRUCTION( sub_IR2_R1 ) { mode_IR2_R1(subtract) }
+INSTRUCTION( sub_R1_IM ) { mode_R1_IM(subtract) }
+INSTRUCTION( sub_IR1_IM ) { mode_IR1_IM(subtract) }
+
+/***************************************************************************
+ LOGICAL INSTRUCTIONS
+***************************************************************************/
+
+static void _and(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst AND src */
+ UINT8 data = register_read(cpustate, dst) & src;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( and_r1_r2 ) { mode_r1_r2(_and) }
+INSTRUCTION( and_r1_Ir2 ) { mode_r1_Ir2(_and) }
+INSTRUCTION( and_R2_R1 ) { mode_R2_R1(_and) }
+INSTRUCTION( and_IR2_R1 ) { mode_IR2_R1(_and) }
+INSTRUCTION( and_R1_IM ) { mode_R1_IM(_and) }
+INSTRUCTION( and_IR1_IM ) { mode_IR1_IM(_and) }
+
+static void complement(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- NOT dst */
+ UINT8 data = register_read(cpustate, dst) ^ 0xff;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( com_R1 ) { mode_R1(complement) }
+INSTRUCTION( com_IR1 ) { mode_IR1(complement) }
+
+static void _or(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst OR src */
+ UINT8 data = register_read(cpustate, dst) | src;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( or_r1_r2 ) { mode_r1_r2(_or) }
+INSTRUCTION( or_r1_Ir2 ) { mode_r1_Ir2(_or) }
+INSTRUCTION( or_R2_R1 ) { mode_R2_R1(_or) }
+INSTRUCTION( or_IR2_R1 ) { mode_IR2_R1(_or) }
+INSTRUCTION( or_R1_IM ) { mode_R1_IM(_or) }
+INSTRUCTION( or_IR1_IM ) { mode_IR1_IM(_or) }
+
+static void _xor(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst XOR src */
+ UINT8 data = register_read(cpustate, dst) ^ src;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( xor_r1_r2 ) { mode_r1_r2(_xor) }
+INSTRUCTION( xor_r1_Ir2 ) { mode_r1_Ir2(_xor) }
+INSTRUCTION( xor_R2_R1 ) { mode_R2_R1(_xor) }
+INSTRUCTION( xor_IR2_R1 ) { mode_IR2_R1(_xor) }
+INSTRUCTION( xor_R1_IM ) { mode_R1_IM(_xor) }
+INSTRUCTION( xor_IR1_IM ) { mode_IR1_IM(_xor) }
+
+/***************************************************************************
+ PROGRAM CONTROL INSTRUCTIONS
+***************************************************************************/
+
+static void call(z8_state *cpustate, UINT16 dst)
+{
+ stack_push_word(cpustate, cpustate->pc);
+ cpustate->pc = dst;
+}
+
+INSTRUCTION( call_IRR1 ) { UINT16 dst = register_pair_read(cpustate, get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))); call(cpustate, dst); }
+INSTRUCTION( call_DA ) { UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate); call(cpustate, dst); }
+
+INSTRUCTION( djnz_r1_RA )
+{
+ INT8 ra = (INT8)fetch(cpustate);
+
+ /* r <- r - 1 */
+ int r = get_working_register(cpustate, opcode >> 4);
+ UINT8 data = register_read(cpustate, r) - 1;
+ register_write(cpustate, r, data);
+
+ /* if r<>0, PC <- PC + dst */
+ if (data != 0)
+ {
+ cpustate->pc += ra;
+ *cycles += 2;
+ }
+}
+
+INSTRUCTION( iret )
+{
+ /* FLAGS <- @SP
+ SP <- SP + 1 */
+ register_write(cpustate, Z8_REGISTER_FLAGS, stack_pop_byte(cpustate));
+
+ /* PC <- @SP
+ SP <- SP + 2 */
+ cpustate->pc = stack_pop_word(cpustate);
+
+ /* IMR (7) <- 1 */
+ cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE;
+}
+
+INSTRUCTION( ret )
+{
+ /* PC <- @SP
+ SP <- SP + 2 */
+ cpustate->pc = stack_pop_word(cpustate);
+}
+
+static void jump(z8_state *cpustate, UINT16 dst)
+{
+ /* PC <- dst */
+ cpustate->pc = dst;
+}
+
+INSTRUCTION( jp_IRR1 ) { jump(cpustate, register_pair_read(cpustate, IR)); }
+
+static int check_condition_code(z8_state *cpustate, int cc)
+{
+ int truth = 0;
+
+ switch (cc)
+ {
+ case CC_F: truth = 0; break;
+ case CC_LT: truth = flag(S) ^ flag(V); break;
+ case CC_LE: truth = (flag(Z) | (flag(S) ^ flag(V))); break;
+ case CC_ULE: truth = flag(C) | flag(Z); break;
+ case CC_OV: truth = flag(V); break;
+ case CC_MI: truth = flag(S); break;
+ case CC_Z: truth = flag(Z); break;
+ case CC_C: truth = flag(C); break;
+ case CC_T: truth = 1; break;
+ case CC_GE: truth = !(flag(S) ^ flag(V)); break;
+ case CC_GT: truth = !(flag(Z) | (flag(S) ^ flag(V))); break;
+ case CC_UGT: truth = ((!flag(C)) & (!flag(Z))); break;
+ case CC_NOV: truth = !flag(V); break;
+ case CC_PL: truth = !flag(S); break;
+ case CC_NZ: truth = !flag(Z); break;
+ case CC_NC: truth = !flag(C); break;
+ }
+
+ return truth;
+}
+
+INSTRUCTION( jp_cc_DA )
+{
+ UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate);
+
+ /* if cc is true, then PC <- dst */
+ if (check_condition_code(cpustate, opcode >> 4))
+ {
+ jump(cpustate, dst);
+ *cycles += 2;
+ }
+}
+
+INSTRUCTION( jr_cc_RA )
+{
+ INT8 ra = (INT8)fetch(cpustate);
+ UINT16 dst = cpustate->pc + ra;
+
+ /* if cc is true, then PC <- dst */
+ if (check_condition_code(cpustate, opcode >> 4))
+ {
+ jump(cpustate, dst);
+ *cycles += 2;
+ }
+}
+
+/***************************************************************************
+ BIT MANIPULATION INSTRUCTIONS
+***************************************************************************/
+
+static void test_complement_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* NOT(dst) AND src */
+ UINT8 data = (register_read(cpustate, dst) ^ 0xff) & src;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( tcm_r1_r2 ) { mode_r1_r2(test_complement_under_mask) }
+INSTRUCTION( tcm_r1_Ir2 ) { mode_r1_Ir2(test_complement_under_mask) }
+INSTRUCTION( tcm_R2_R1 ) { mode_R2_R1(test_complement_under_mask) }
+INSTRUCTION( tcm_IR2_R1 ) { mode_IR2_R1(test_complement_under_mask) }
+INSTRUCTION( tcm_R1_IM ) { mode_R1_IM(test_complement_under_mask) }
+INSTRUCTION( tcm_IR1_IM ) { mode_IR1_IM(test_complement_under_mask) }
+
+static void test_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst AND src */
+ UINT8 data = register_read(cpustate, dst) & src;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( tm_r1_r2 ) { mode_r1_r2(test_under_mask) }
+INSTRUCTION( tm_r1_Ir2 ) { mode_r1_Ir2(test_under_mask) }
+INSTRUCTION( tm_R2_R1 ) { mode_R2_R1(test_under_mask) }
+INSTRUCTION( tm_IR2_R1 ) { mode_IR2_R1(test_under_mask) }
+INSTRUCTION( tm_R1_IM ) { mode_R1_IM(test_under_mask) }
+INSTRUCTION( tm_IR1_IM ) { mode_IR1_IM(test_under_mask) }
+
+/***************************************************************************
+ ROTATE AND SHIFT INSTRUCTIONS
+***************************************************************************/
+
+static void rotate_left(z8_state *cpustate, UINT8 dst)
+{
+ /* << */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (data << 1) | BIT(data, 7);
+
+ set_flag_c(data & 0x80);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rl_R1 ) { mode_R1(rotate_left) }
+INSTRUCTION( rl_IR1 ) { mode_IR1(rotate_left) }
+
+static void rotate_left_carry(z8_state *cpustate, UINT8 dst)
+{
+ /* << C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (data << 1) | flag(C);
+
+ set_flag_c(data & 0x80);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rlc_R1 ) { mode_R1(rotate_left_carry) }
+INSTRUCTION( rlc_IR1 ) { mode_IR1(rotate_left_carry) }
+
+static void rotate_right(z8_state *cpustate, UINT8 dst)
+{
+ /* >> */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = ((data & 0x01) << 7) | (data >> 1);
+
+ set_flag_c(data & 0x01);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rr_R1 ) { mode_R1(rotate_right) }
+INSTRUCTION( rr_IR1 ) { mode_IR1(rotate_right) }
+
+static void rotate_right_carry(z8_state *cpustate, UINT8 dst)
+{
+ /* >> C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (flag(C) << 7) | (data >> 1);
+
+ set_flag_c(data & 0x01);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rrc_R1 ) { mode_R1(rotate_right_carry) }
+INSTRUCTION( rrc_IR1 ) { mode_IR1(rotate_right_carry) }
+
+static void shift_right_arithmetic(z8_state *cpustate, UINT8 dst)
+{
+ /* */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (data & 0x80) | ((data >> 1) & 0x7f);
+
+ set_flag_c(data & 0x01);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(0);
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( sra_R1 ) { mode_R1(shift_right_arithmetic) }
+INSTRUCTION( sra_IR1 ) { mode_IR1(shift_right_arithmetic) }
+
+static void swap(z8_state *cpustate, UINT8 dst)
+{
+ /* dst(7-4) <-> dst(3-0) */
+ UINT8 data = register_read(cpustate, dst);
+ data = (data << 4) | (data >> 4);
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+// set_flag_v(0); undefined
+}
+
+INSTRUCTION( swap_R1 ) { mode_R1(swap) }
+INSTRUCTION( swap_IR1 ) { mode_IR1(swap) }
+
+/***************************************************************************
+ CPU CONTROL INSTRUCTIONS
+***************************************************************************/
+
+INSTRUCTION( ccf ) { cpustate->r[Z8_REGISTER_FLAGS] ^= Z8_FLAGS_C; }
+INSTRUCTION( di ) { cpustate->r[Z8_REGISTER_IMR] &= ~Z8_IMR_ENABLE; }
+INSTRUCTION( ei ) { cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE; }
+INSTRUCTION( nop ) { /* no operation */ }
+INSTRUCTION( rcf ) { set_flag_c(0); }
+INSTRUCTION( scf ) { set_flag_c(1); }
+INSTRUCTION( srp_IM ) { cpustate->r[Z8_REGISTER_RP] = fetch(cpustate); }