diff options
Diffstat (limited to 'trunk/src/emu/cpu/z8/z8ops.c')
-rw-r--r-- | trunk/src/emu/cpu/z8/z8ops.c | 746 |
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); } |