mame/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp
2018-08-26 13:50:14 +10:00

950 lines
28 KiB
C++

// license:BSD-3-Clause
// copyright-holders:David Haywood
/*************************************************************************************************************
Toshiba TLCS-870 Series MCUs
(reg) prefix ops (e8 to ef subtable)
(reg) implies one of the follow registers
(8-bit mode operations)
E8 A
E9 W
EA C
EB B
EC E
ED D
EE L
EF H
(16-bit mode operations)
E8 WA
E9 BC
EA DE
EB HL
EC WA
ED BC
EE DE
EF HL
(RETN operation - special)
E8 RETN
E9-EF invalid
*************************************************************************************************************/
#include "emu.h"
#include "tlcs870.h"
#include "tlcs870d.h"
#include "debugger.h"
// Main dispatch handlers for these
void tlcs870_device::do_regprefixtype_opcode(const uint8_t opbyte0)
{
// register prefix: g/gg
uint8_t opbyte1 = READ8();
switch (opbyte1)
{
case 0x01:
do_SWAP_g(opbyte0, opbyte1); break;
case 0x02:
do_MUL_gg(opbyte0, opbyte1); break;
case 0x03:
do_DIV_gg_C(opbyte0, opbyte1); break;
case 0x04:
do_RETN(opbyte0, opbyte1); break;
case 0x06:
do_POP_gg(opbyte0, opbyte1); break;
case 0x07:
do_PUSH_gg(opbyte0, opbyte1); break;
case 0x0a:
do_DAA_g(opbyte0, opbyte1); break;
case 0x0b:
do_DAS_g(opbyte0, opbyte1); break;
case 0x10: case 0x11: case 0x12: case 0x13:
do_XCH_rr_gg(opbyte0, opbyte1); break;
case 0x14: case 0x15: case 0x16: case 0x17:
do_LD_rr_gg(opbyte0, opbyte1); break;
case 0x1c:
do_SHLC_g(opbyte0, opbyte1); break;
case 0x1d:
do_SHRC_g(opbyte0, opbyte1); break;
case 0x1e:
do_ROLC_g(opbyte0, opbyte1); break;
case 0x1f:
do_RORC_g(opbyte0, opbyte1); break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
do_ALUOP_WA_gg(opbyte0, opbyte1); break;
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
do_ALUOP_gg_mn(opbyte0, opbyte1); break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
do_SET_gbit(opbyte0, opbyte1); break;
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
do_CLR_gbit(opbyte0, opbyte1); break;
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
do_LD_r_g(opbyte0, opbyte1); break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
do_ALUOP_A_g(opbyte0, opbyte1); break;
case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
do_ALUOP_g_A(opbyte0, opbyte1); break;
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
do_ALUOP_g_n(opbyte0, opbyte1); break;
case 0x82: case 0x83:
do_SET_inppbit(opbyte0, opbyte1); break;
case 0x8a: case 0x8b:
do_CLR_inppbit(opbyte0, opbyte1); break;
case 0x92: case 0x93:
do_CPL_inpp_indirectbit(opbyte0, opbyte1); break;
case 0x9a: case 0x9b:
do_LD_inpp_indirectbit_CF(opbyte0, opbyte1); break;
case 0x9e: case 0x9f:
do_LD_CF_inpp_indirectbit(opbyte0, opbyte1); break;
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
do_XCH_r_g(opbyte0, opbyte1); break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
do_CPL_gbit(opbyte0, opbyte1); break;
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
do_LD_gbit_CF(opbyte0, opbyte1); break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
do_XOR_CF_gbit(opbyte0, opbyte1); break;
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
do_LD_CF_gbit(opbyte0, opbyte1); break;
case 0xfa:
do_LD_SP_gg(opbyte0, opbyte1); break;
case 0xfb:
do_LD_gg_SP(opbyte0, opbyte1); break;
case 0xfc:
do_CALL_gg(opbyte0, opbyte1); break;
case 0xfe:
do_JP_gg(opbyte0, opbyte1); break;
default:
do_regprefixtype_oprand_illegal(opbyte0, opbyte1); break;
}
}
// Actual handlers
/**********************************************************************************************************************/
// (Special)
/**********************************************************************************************************************/
void tlcs870_device::do_regprefixtype_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1)
{
m_cycles = 1;
logerror("illegal reg prefix opcode %02x %02x\n", opbyte0, opbyte1);
}
void tlcs870_device::do_RETN(const uint8_t opbyte0, const uint8_t opbyte1)
{
// with E8 only
if (opbyte0 == 0xe8)
{
/*
Return from non-maskable interrupt service (how does this differ from RETI?)
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
RETN 1110 1000 0000 0100 * * * * 7
*/
m_cycles = 7;
m_sp.d += 3;
m_addr = RM16(m_sp.d - 2);
set_PSW(RM8(m_sp.d - 1));
}
else
{
do_regprefixtype_oprand_illegal(opbyte0, opbyte1);
}
}
/**********************************************************************************************************************/
// (8-bit)
/**********************************************************************************************************************/
void tlcs870_device::do_SWAP_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
SWAP g 1110 1ggg 0000 0001 1 - - - 4
*/
m_cycles = 4;
const uint8_t reg = opbyte0 & 0x7;
handle_swap(reg);
}
void tlcs870_device::do_DAA_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
DAS g 1110 1ggg 0000 1010 C Z C H 3
*/
m_cycles = 3;
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_DAA(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_DAS_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
DAS g 1110 1ggg 0000 1011 C Z C H 3
*/
m_cycles = 3;
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_DAS(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_SHLC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
Logical Shift Left with Carry Flag
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
SHLC g 1110 1ggg 0001 1100 C Z * - 2
*/
m_cycles = 2;
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_SHLC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_SHRC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
Logical Shift Right with Carry Flag
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
SHRC g 1110 1ggg 0001 1101 C Z * - 2
*/
m_cycles = 2;
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_SHRC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_ROLC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
Rotate Left through Carry flag
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
ROLC g 1110 1ggg 0001 1110 C Z * - 2
*/
m_cycles = 2;
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_ROLC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_RORC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
Rotate Right through Carry flag
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
RORC g 1110 1ggg 0001 1111 C Z * - 2
*/
m_cycles = 2;
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_RORC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_LD_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD r, g 1110 1ggg 0101 1rrr 1 Z - - 2
*/
m_cycles = 2;
const uint8_t val = get_reg8(opbyte0 & 0x7);
set_reg8(opbyte1 & 0x7, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_XCH_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
XCG r, g 1110 1ggg 1010 1rrr 1 Z - - 3
*/
m_cycles = 3;
const uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t r = get_reg8(opbyte1 & 0x7);
set_reg8(opbyte1 & 0x7, val);
set_reg8(opbyte0 & 0x7, r);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
/**********************************************************************************************************************/
// (ALU handlers)
/**********************************************************************************************************************/
void tlcs870_device::do_ALUOP_A_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
ADDC A, g 1110 1ggg 0110 0000 C Z C H 2
ADD A, g 1110 1ggg 0110 0001 C Z C H 2
SUBB A, g 1110 1ggg 0110 0010 C Z C H 2
SUB A, g 1110 1ggg 0110 0011 C Z C H 2
AND A, g 1110 1ggg 0110 0100 Z Z - - 2
XOR A, g 1110 1ggg 0110 0101 Z Z - - 2
OR A, g 1110 1ggg 0110 0110 Z Z - - 2
CMP A, g 1110 1ggg 0110 0111 Z Z C H 2
*/
m_cycles = 2;
const int aluop = (opbyte1 & 0x7);
const uint8_t result = do_alu_8bit(aluop, get_reg8(REG_A), get_reg8(opbyte0 & 0x7));
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(REG_A, result);
}
}
void tlcs870_device::do_ALUOP_g_A(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
ADDC g, A 1110 1ggg 0110 1000 C Z C H 3
ADD g, A 1110 1ggg 0110 1001 C Z C H 3
SUBB g, A 1110 1ggg 0110 1010 C Z C H 3
SUB g, A 1110 1ggg 0110 1011 C Z C H 3
AND g, A 1110 1ggg 0110 1100 Z Z - - 3
XOR g, A 1110 1ggg 0110 1101 Z Z - - 3
OR g, A 1110 1ggg 0110 1110 Z Z - - 3
CMP g, A 1110 1ggg 0110 1111 Z Z C H 3
*/
m_cycles = 3;
const int aluop = (opbyte1 & 0x7);
const uint8_t result = do_alu_8bit(aluop, get_reg8(opbyte0 & 0x7), get_reg8(REG_A));
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(opbyte0 & 0x7, result);
}
}
void tlcs870_device::do_ALUOP_g_n(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
ADDC g, n 1110 1ggg 0111 0000 nnnn nnnn C Z C H 3
ADD g, n 1110 1ggg 0111 0001 nnnn nnnn C Z C H 3
SUBB g, n 1110 1ggg 0111 0010 nnnn nnnn C Z C H 3
SUB g, n 1110 1ggg 0111 0011 nnnn nnnn C Z C H 3
AND g, n 1110 1ggg 0111 0100 nnnn nnnn Z Z - - 3
XOR g, n 1110 1ggg 0111 0101 nnnn nnnn Z Z - - 3
OR g, n 1110 1ggg 0111 0110 nnnn nnnn Z Z - - 3
CMP g, n 1110 1ggg 0111 0111 nnnn nnnn Z Z C H 3
*/
m_cycles = 3;
const int aluop = (opbyte1 & 0x7);
const uint8_t n = READ8();
const uint8_t result = do_alu_8bit(aluop, get_reg8(opbyte0 & 0x7), n);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(opbyte0 & 0x7, result);
}
}
/**********************************************************************************************************************/
// (16-bit ALU handlers)
/**********************************************************************************************************************/
void tlcs870_device::do_ALUOP_WA_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
ADDC WA, gg 1110 10gg 0011 0000 C Z C U 4
ADD WA, gg 1110 10gg 0011 0001 C Z C U 4
SUBB WA, gg 1110 10gg 0011 0010 C Z C U 4
SUB WA, gg 1110 10gg 0011 0011 C Z C U 4
AND WA, gg 1110 10gg 0011 0100 Z Z - - 4
XOR WA, gg 1110 10gg 0011 0101 Z Z - - 4
OR WA, gg 1110 10gg 0011 0110 Z Z - - 4
CMP WA, gg 1110 10gg 0011 0111 Z Z C U 4
*/
m_cycles = 4;
const int aluop = (opbyte1 & 0x7);
const uint16_t result = do_alu_16bit(aluop, get_reg16(REG_WA), get_reg16(opbyte0 & 0x3));
if (aluop != 0x07) // CMP doesn't write back
{
set_reg16(REG_WA, result);
}
}
void tlcs870_device::do_ALUOP_gg_mn(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
ADDC gg, mn 1110 10gg 0011 1000 nnnn nnnn mmmm mmmm C Z C U 4
ADD gg, mn 1110 10gg 0011 1001 nnnn nnnn mmmm mmmm C Z C U 4
SUBB gg, mn 1110 10gg 0011 1010 nnnn nnnn mmmm mmmm C Z C U 4
SUB gg, mn 1110 10gg 0011 1011 nnnn nnnn mmmm mmmm C Z C U 4
AND gg, mn 1110 10gg 0011 1100 nnnn nnnn mmmm mmmm Z Z - - 4
XOR gg, mn 1110 10gg 0011 1101 nnnn nnnn mmmm mmmm Z Z - - 4
OR gg, mn 1110 10gg 0011 1110 nnnn nnnn mmmm mmmm Z Z - - 4
CMP gg, mn 1110 10gg 0011 1111 nnnn nnnn mmmm mmmm Z Z C U 4
*/
m_cycles = 4;
const int aluop = (opbyte1 & 0x7);
const uint16_t mn = READ16();
const uint16_t result = do_alu_16bit(aluop, get_reg16(opbyte0 & 0x3), mn);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg16(opbyte0 & 0x3, result);
}
}
/**********************************************************************************************************************/
// bit accesses
/**********************************************************************************************************************/
// ops using (pp).g
void tlcs870_device::do_SET_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
SET (DE).g 1110 1ggg 1000 0010 Z * - - 5
SET (HL).g 1110 1ggg 1000 0011 Z * - - 5
*/
m_cycles = 5;
const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
uint8_t val = RM8(addr);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val |= bitused;
WM8(addr, val);
}
void tlcs870_device::do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
CLR (DE).g 1110 1ggg 1000 1010 Z * - - 5
CLR (HL).g 1110 1ggg 1000 1011 Z * - - 5
*/
m_cycles = 5;
const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports
uint8_t val = RM8(addr);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val &= ~bitused;
WM8(addr, val);
}
void tlcs870_device::do_CPL_inpp_indirectbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
CPL (DE).g 1110 1ggg 1001 0010 Z * - - 5
CPL (HL).g 1110 1ggg 1001 0011 Z * - - 5
*/
m_cycles = 5;
const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports
uint8_t val = RM8(addr);
uint8_t bit = val & bitused;
if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
{
clear_ZF();
clear_JF();
val &= ~bitused;
}
else // if the bit isn't set, set the zero/jump flags and set the bit
{
set_ZF();
set_JF();
val |= bitused;
}
WM8(addr, val);
}
void tlcs870_device::do_LD_inpp_indirectbit_CF(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD (DE).g, CF 1110 1ggg 1001 1010 1 - - - 5
LD (HL).g, CF 1110 1ggg 1001 1011 1 - - - 5
*/
m_cycles = 5;
const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
uint8_t val = RM8(addr);
if (is_CF()) // if carry flag is set, set the bit in val
{
val |= bitused;
}
else // if carry flag isn't set, clear the bit in val
{
val &= ~bitused;
}
// for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
set_JF();
WM8(addr, val);
}
void tlcs870_device::do_LD_CF_inpp_indirectbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD CF, (DE).g 1110 1ggg 1001 1110 ~C - * - 4
LD CF, (HL).g 1110 1ggg 1001 1111 ~C - * - 4
aka aka TEST (pp).g
*/
m_cycles = 4;
const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
const uint8_t val = RM8(addr);
const uint8_t bit = val & bitused;
bit ? set_CF() : clear_CF();
// for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
bit ? clear_JF() : set_JF();
}
// ops using g.b
void tlcs870_device::do_SET_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
SET g.b 1110 1ggg 0100 0bbb Z * - - 3
*/
m_cycles = 3;
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val |= bitused;
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_CLR_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
CLR g.b 1110 1ggg 0100 1bbb Z * - - 3
*/
m_cycles = 3;
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val &= ~bitused;
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_CPL_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
CPL g.b 1110 1ggg 1100 0bbb Z * - - 3
*/
m_cycles = 3;
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
uint8_t bit = val & bitused;
if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
{
clear_ZF();
clear_JF();
val &= ~bitused;
}
else // if the bit isn't set, set the zero/jump flags and set the bit
{
set_ZF();
set_JF();
val |= bitused;
}
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_LD_gbit_CF(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD g.b, CF 1110 1ggg 1100 1bbb 1 - - - 2
*/
m_cycles = 2;
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (is_CF()) // if carry flag is set, set the bit in val
{
val |= bitused;
}
else // if carry flag isn't set, clear the bit in val
{
val &= ~bitused;
}
// for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
set_JF();
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_XOR_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
XOR CF, g.b 1110 1ggg 1101 0bbb ~C - * - 2
*/
m_cycles = 2;
const uint8_t bitpos = opbyte1 & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint8_t g = get_reg8(opbyte0 & 0x7);
const uint8_t bit = g & bitused;
if (is_CF())
{
if (bit)
{
clear_CF();
}
else
{
set_CF();
}
}
else
{
if (bit)
{
set_CF();
}
else
{
clear_CF();
}
}
// JF ends up being whatever the new value of CF is
if (is_CF())
set_JF();
else
clear_JF();
}
void tlcs870_device::do_LD_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD CF, g.b 1110 1ggg 1101 1bbb ~C - * - 2
aka TEST g.b
*/
m_cycles = 2;
const uint8_t bitpos = opbyte1 & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint8_t g = get_reg8(opbyte0 & 0x7);
const uint8_t bit = g & bitused;
bit ? set_CF() : clear_CF();
// for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
bit ? clear_JF() : set_JF();
}
/**********************************************************************************************************************/
// 16-bit
/**********************************************************************************************************************/
void tlcs870_device::do_MUL_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
MUL W, A not listed (redundant encoding?) ? ? ? ? ?
MUL B, C 1110 1010 0000 0010 Z Z - - 8
MUL D, E 1110 1010 0000 0010 Z Z - - 8
MUL H, L 1110 1011 0000 0010 Z Z - - 8
aka MUL ggH, ggL (odd syntax, basically MUL gg)
*/
m_cycles = 8;
const uint8_t reg = opbyte0 & 0x3; // opbyte0 & 4 = invalid?
handle_mul(reg); // flag changes in handler
}
void tlcs870_device::do_DIV_gg_C(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
DIV WA, C not listed (redundant encoding?) ? ? ? ? ?
DIV BC, C not listed (illegal?) ? ? ? ? ?
DIV DE, C 1110 1010 0000 0011 Z Z C - 8
DIV HL, C 1110 1011 0000 0011 Z Z C - 8
*/
m_cycles = 8;
const uint8_t reg = opbyte0 & 0x3; // opbyte0 & 4 = invalid?
handle_div(reg); // flag changes in handler
}
void tlcs870_device::do_POP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
POP gg 1110 10gg 0000 0110 - - - - 5
*/
m_cycles = 5;
m_sp.d += 2;
const uint16_t val = RM16(m_sp.d - 1);
set_reg16(opbyte0 & 3, val);
// no flag changes
}
void tlcs870_device::do_PUSH_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
PUSH gg 1110 10gg 0000 0111 - - - - 4
*/
m_cycles = 4;
const uint16_t val = get_reg16(opbyte0 & 3);
WM16(m_sp.d - 1, val);
m_sp.d -= 2;
// no flag changes
}
void tlcs870_device::do_LD_SP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD SP, gg 1110 10gg 1111 1010 1 - - - 3
*/
m_cycles = 3;
m_sp.d = get_reg16(opbyte0 & 0x3);
set_JF(); // no other flag changes for this type of LD
}
void tlcs870_device::do_LD_gg_SP(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD gg, SP 1110 10gg 1111 1011 1 - - - 3
*/
m_cycles = 3;
set_reg16(opbyte0 & 0x3, m_sp.d);
set_JF(); // no other flag changes for this type of LD
}
void tlcs870_device::do_LD_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
LD rr, gg 1110 10gg 0001 00rr 1 - - - 2
*/
m_cycles = 2;
const uint16_t gg = get_reg16(opbyte0 & 0x3);
set_reg16(opbyte1 & 0x3, gg);
set_JF(); // no other flag changes for this type of LD
}
void tlcs870_device::do_XCH_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
XCH rr, gg 1110 10gg 0001 01rr 1 - - - 3
*/
m_cycles = 3;
const uint16_t gg = get_reg16(opbyte0 & 0x3);
const uint16_t rr = get_reg16(opbyte1 & 0x3);
set_reg16(opbyte1 & 0x3, gg);
set_reg16(opbyte0 & 0x3, rr);
set_JF();
}
void tlcs870_device::do_CALL_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
CALL gg 1110 10gg 1111 1100 - - - - 6
*/
m_cycles = 6;
const uint16_t val = get_reg16(opbyte0 & 3);
WM16(m_sp.d - 1, m_addr);
m_sp.d -= 2;
m_addr = val;
// no flag changes on call
}
void tlcs870_device::do_JP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
/*
OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles
JP gg 1110 10gg 1111 1110 1 - - - 3
*/
m_cycles = 3;
const uint16_t val = get_reg16(opbyte0 & 3);
m_addr = val;
set_JF();
}