mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
cpu/z80/r800.cpp: (#12530)
- Removed undocumented Z80 instructions that are not supported by the R800 - Updated basic instruction timing - Implement MULUB and MULUW Other R800 features are not implemented
This commit is contained in:
parent
4183b96612
commit
2c479b20dd
6 changed files with 2194 additions and 44 deletions
|
@ -3001,11 +3001,13 @@ if CPUS["Z80"] or CPUS["KC80"] or CPUS["Z80N"] then
|
|||
dependency {
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.cpp", GEN_DIR .. "emu/cpu/z80/z80.hxx" },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.cpp", GEN_DIR .. "emu/cpu/z80/ncs800.hxx" },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/r800.cpp", GEN_DIR .. "emu/cpu/z80/r800.hxx" },
|
||||
}
|
||||
|
||||
custombuildtask {
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/z80.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating Z80 source file...", PYTHON .. " $(1) $(<) $(@)" } },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/ncs800.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating NSC800 source file...", PYTHON .. " $(1) ncs800 $(<) $(@)" } },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/r800.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating R800 source file...", PYTHON .. " $(1) r800 $(<) $(@)" } },
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -1,17 +1,33 @@
|
|||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
// copyright-holders:AJR,Wilbert Pol
|
||||
/***************************************************************************
|
||||
|
||||
ASCII R800 CPU
|
||||
|
||||
TODO: this uses a sped-up Z80 core with added multiply instructions
|
||||
('mulub', 'muluw').
|
||||
TODO:
|
||||
- Internal configuration registers.
|
||||
- External 24 bits address bus accessible through 9 memory mappers.
|
||||
- DMA channels.
|
||||
- Interrupt levels.
|
||||
- Bits 3 and 5 of the flag register behave differently from the z80.
|
||||
- Page break penalties.
|
||||
- Refresh delays.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "r800.h"
|
||||
#include "r800dasm.h"
|
||||
|
||||
#define LOG_UNDOC (1U << 1)
|
||||
#define LOG_INT (1U << 2)
|
||||
#define LOG_TIME (1U << 3)
|
||||
|
||||
//#define VERBOSE ( LOG_UNDOC /*| LOG_INT*/ )
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGUNDOC(...) LOGMASKED(LOG_UNDOC, __VA_ARGS__)
|
||||
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
|
@ -32,4 +48,135 @@ DEFINE_DEVICE_TYPE(R800, r800_device, "r800", "ASCII R800")
|
|||
r800_device::r800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: z80_device(mconfig, R800, tag, owner, clock)
|
||||
{
|
||||
z80_set_m1_cycles(1);
|
||||
z80_set_memrq_cycles(1);
|
||||
z80_set_iorq_cycles(1);
|
||||
}
|
||||
|
||||
std::unique_ptr<util::disasm_interface> r800_device::create_disassembler()
|
||||
{
|
||||
return std::make_unique<r800_disassembler>();
|
||||
}
|
||||
|
||||
void r800_device::device_validity_check(validity_checker &valid) const
|
||||
{
|
||||
cpu_device::device_validity_check(valid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define HAS_LDAIR_QUIRK 0
|
||||
|
||||
/****************************************************************************
|
||||
* The Z80 registers. halt is set to 1 when the CPU is halted, the refresh
|
||||
* register is calculated as follows: refresh = (r & 127) | (r2 & 128)
|
||||
****************************************************************************/
|
||||
#define CF 0x01
|
||||
#define NF 0x02
|
||||
#define PF 0x04
|
||||
#define VF PF
|
||||
#define XF 0x08
|
||||
#define HF 0x10
|
||||
#define YF 0x20
|
||||
#define ZF 0x40
|
||||
#define SF 0x80
|
||||
|
||||
#define INT_IRQ 0x01
|
||||
#define NMI_IRQ 0x02
|
||||
|
||||
#define PRVPC m_prvpc.d // previous program counter
|
||||
|
||||
#define PCD m_pc.d
|
||||
#define PC m_pc.w.l
|
||||
|
||||
#define SPD m_sp.d
|
||||
#define SP m_sp.w.l
|
||||
|
||||
#define AFD m_af.d
|
||||
#define AF m_af.w.l
|
||||
#define A m_af.b.h
|
||||
#define F m_af.b.l
|
||||
#define Q m_q
|
||||
#define QT m_qtemp
|
||||
#define I m_i
|
||||
#define R m_r
|
||||
#define R2 m_r2
|
||||
|
||||
#define BCD m_bc.d
|
||||
#define BC m_bc.w.l
|
||||
#define B m_bc.b.h
|
||||
#define C m_bc.b.l
|
||||
|
||||
#define DED m_de.d
|
||||
#define DE m_de.w.l
|
||||
#define D m_de.b.h
|
||||
#define E m_de.b.l
|
||||
|
||||
#define HLD m_hl.d
|
||||
#define HL m_hl.w.l
|
||||
#define H m_hl.b.h
|
||||
#define L m_hl.b.l
|
||||
|
||||
#define IXD m_ix.d
|
||||
#define IX m_ix.w.l
|
||||
#define HX m_ix.b.h
|
||||
#define LX m_ix.b.l
|
||||
|
||||
#define IYD m_iy.d
|
||||
#define IY m_iy.w.l
|
||||
#define HY m_iy.b.h
|
||||
#define LY m_iy.b.l
|
||||
|
||||
#define WZ m_wz.w.l
|
||||
#define WZ_H m_wz.b.h
|
||||
#define WZ_L m_wz.b.l
|
||||
|
||||
#define TADR m_shared_addr.w // Typically represents values from A0..15 pins. 16bit input in steps.
|
||||
#define TADR_H m_shared_addr.b.h
|
||||
#define TADR_L m_shared_addr.b.l
|
||||
#define TDAT m_shared_data.w // 16bit input(if use as second parameter) or output in steps.
|
||||
#define TDAT2 m_shared_data2.w
|
||||
#define TDAT_H m_shared_data.b.h
|
||||
#define TDAT_L m_shared_data.b.l
|
||||
#define TDAT8 m_shared_data.b.l // Typically represents values from D0..8 pins. 8bit input or output in steps.
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* adjust cycle count by n T-states
|
||||
***************************************************************/
|
||||
#define T(icount) { m_icount -= icount; }
|
||||
|
||||
/***************************************************************
|
||||
* SLL r8
|
||||
***************************************************************/
|
||||
u8 r800_device::r800_sll(u8 value)
|
||||
{
|
||||
const u8 c = (value & 0x80) ? CF : 0;
|
||||
const u8 res = u8(value << 1);
|
||||
set_f(SZP[res] | c);
|
||||
return res;
|
||||
}
|
||||
|
||||
void r800_device::mulub(u8 value)
|
||||
{
|
||||
const u16 res = A * value;
|
||||
HL = res;
|
||||
const u8 c = (H) ? CF : 0;
|
||||
const u8 z = (res) ? 0 : ZF;
|
||||
set_f((F & (HF|NF)) | z | c);
|
||||
}
|
||||
|
||||
void r800_device::muluw(u16 value)
|
||||
{
|
||||
const u32 res = HL * value;
|
||||
DE = res >> 16;
|
||||
HL = res & 0xffff;
|
||||
const u8 c = (DE) ? CF : 0;
|
||||
const u8 z = (res) ? 0 : ZF;
|
||||
set_f((F & (HF|NF)) | z | c);
|
||||
}
|
||||
|
||||
void r800_device::do_op()
|
||||
{
|
||||
#include "cpu/z80/r800.hxx"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
// copyright-holders:AJR,Wilbert Pol
|
||||
/***************************************************************************
|
||||
|
||||
ASCII R800 CPU
|
||||
|
@ -24,10 +24,25 @@ public:
|
|||
// device type constructor
|
||||
r800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
static constexpr feature_type imperfect_features() { return feature::TIMING; }
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_validity_check(validity_checker &valid) const override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual u32 execute_min_cycles() const noexcept override { return 1; }
|
||||
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
|
||||
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); }
|
||||
|
||||
// device_disasm_interface implementation
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
u8 r800_sll(u8 value);
|
||||
void mulub(u8 value);
|
||||
void muluw(u16 value);
|
||||
|
||||
virtual void do_op() override;
|
||||
};
|
||||
|
||||
// device type declaration
|
||||
|
|
|
@ -27,15 +27,14 @@ TODO:
|
|||
|
||||
#include "z80.inc"
|
||||
|
||||
static bool tables_initialised = false;
|
||||
std::unique_ptr<u8[]> z80_device::SZ = std::make_unique<u8[]>(0x100); // zero and sign flags
|
||||
std::unique_ptr<u8[]> z80_device::SZ_BIT = std::make_unique<u8[]>(0x100); // zero, sign and parity/overflow (=zero) flags for BIT opcode
|
||||
std::unique_ptr<u8[]> z80_device::SZP = std::make_unique<u8[]>(0x100); // zero, sign and parity flags
|
||||
std::unique_ptr<u8[]> z80_device::SZHV_inc = std::make_unique<u8[]>(0x100); // zero, sign, half carry and overflow flags INC r8
|
||||
std::unique_ptr<u8[]> z80_device::SZHV_dec = std::make_unique<u8[]>(0x100); // zero, sign, half carry and overflow flags DEC r8
|
||||
|
||||
std::unique_ptr<u8[]> z80_device::SZHVC_add = std::make_unique<u8[]>(2 * 0x100 * 0x100);
|
||||
std::unique_ptr<u8[]> z80_device::SZHVC_sub = std::make_unique<u8[]>(2 * 0x100 * 0x100);
|
||||
bool z80_device::tables_initialised = false;
|
||||
u8 z80_device::SZ[] = {}; // zero and sign flags
|
||||
u8 z80_device::SZ_BIT[] = {}; // zero, sign and parity/overflow (=zero) flags for BIT opcode
|
||||
u8 z80_device::SZP[] = {}; // zero, sign and parity flags
|
||||
u8 z80_device::SZHV_inc[] = {}; // zero, sign, half carry and overflow flags INC r8
|
||||
u8 z80_device::SZHV_dec[] = {}; // zero, sign, half carry and overflow flags DEC r8
|
||||
u8 z80_device::SZHVC_add[] = {};
|
||||
u8 z80_device::SZHVC_sub[] = {};
|
||||
|
||||
|
||||
/***************************************************************
|
||||
|
@ -501,36 +500,36 @@ void z80_device::device_start()
|
|||
int val = newval - oldval;
|
||||
*padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
|
||||
*padd |= (newval & (YF | XF)); // undocumented flag bits 5+3
|
||||
if( (newval & 0x0f) < (oldval & 0x0f) ) *padd |= HF;
|
||||
if( newval < oldval ) *padd |= CF;
|
||||
if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padd |= VF;
|
||||
if ((newval & 0x0f) < (oldval & 0x0f)) *padd |= HF;
|
||||
if (newval < oldval) *padd |= CF;
|
||||
if ((val^oldval^0x80) & (val^newval) & 0x80) *padd |= VF;
|
||||
padd++;
|
||||
|
||||
// adc with carry set
|
||||
val = newval - oldval - 1;
|
||||
*padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
|
||||
*padc |= (newval & (YF | XF)); // undocumented flag bits 5+3
|
||||
if( (newval & 0x0f) <= (oldval & 0x0f) ) *padc |= HF;
|
||||
if( newval <= oldval ) *padc |= CF;
|
||||
if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padc |= VF;
|
||||
if ((newval & 0x0f) <= (oldval & 0x0f)) *padc |= HF;
|
||||
if (newval <= oldval) *padc |= CF;
|
||||
if ((val^oldval^0x80) & (val^newval) & 0x80) *padc |= VF;
|
||||
padc++;
|
||||
|
||||
// cp, sub or sbc w/o carry set
|
||||
val = oldval - newval;
|
||||
*psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
|
||||
*psub |= (newval & (YF | XF)); // undocumented flag bits 5+3
|
||||
if( (newval & 0x0f) > (oldval & 0x0f) ) *psub |= HF;
|
||||
if( newval > oldval ) *psub |= CF;
|
||||
if( (val^oldval) & (oldval^newval) & 0x80 ) *psub |= VF;
|
||||
if ((newval & 0x0f) > (oldval & 0x0f)) *psub |= HF;
|
||||
if (newval > oldval) *psub |= CF;
|
||||
if ((val^oldval) & (oldval^newval) & 0x80) *psub |= VF;
|
||||
psub++;
|
||||
|
||||
// sbc with carry set
|
||||
val = oldval - newval - 1;
|
||||
*psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
|
||||
*psbc |= (newval & (YF | XF)); // undocumented flag bits 5+3
|
||||
if( (newval & 0x0f) >= (oldval & 0x0f) ) *psbc |= HF;
|
||||
if( newval >= oldval ) *psbc |= CF;
|
||||
if( (val^oldval) & (oldval^newval) & 0x80 ) *psbc |= VF;
|
||||
if ((newval & 0x0f) >= (oldval & 0x0f)) *psbc |= HF;
|
||||
if (newval >= oldval) *psbc |= CF;
|
||||
if ((val^oldval) & (oldval^newval) & 0x80) *psbc |= VF;
|
||||
psbc++;
|
||||
}
|
||||
}
|
||||
|
@ -538,25 +537,19 @@ void z80_device::device_start()
|
|||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
int p = 0;
|
||||
if( i&0x01 ) ++p;
|
||||
if( i&0x02 ) ++p;
|
||||
if( i&0x04 ) ++p;
|
||||
if( i&0x08 ) ++p;
|
||||
if( i&0x10 ) ++p;
|
||||
if( i&0x20 ) ++p;
|
||||
if( i&0x40 ) ++p;
|
||||
if( i&0x80 ) ++p;
|
||||
for (int b = 0; b < 8; b++)
|
||||
p += BIT(i, b);
|
||||
SZ[i] = i ? i & SF : ZF;
|
||||
SZ[i] |= (i & (YF | XF)); // undocumented flag bits 5+3
|
||||
SZ_BIT[i] = i ? i & SF : ZF | PF;
|
||||
SZ_BIT[i] |= (i & (YF | XF)); // undocumented flag bits 5+3
|
||||
SZP[i] = SZ[i] | ((p & 1) ? 0 : PF);
|
||||
SZHV_inc[i] = SZ[i];
|
||||
if( i == 0x80 ) SZHV_inc[i] |= VF;
|
||||
if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF;
|
||||
if (i == 0x80) SZHV_inc[i] |= VF;
|
||||
if ((i & 0x0f) == 0x00) SZHV_inc[i] |= HF;
|
||||
SZHV_dec[i] = SZ[i] | NF;
|
||||
if( i == 0x7f ) SZHV_dec[i] |= VF;
|
||||
if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF;
|
||||
if (i == 0x7f) SZHV_dec[i] |= VF;
|
||||
if ((i & 0x0f) == 0x0f) SZHV_dec[i] |= HF;
|
||||
}
|
||||
|
||||
tables_initialised = true;
|
||||
|
|
|
@ -181,14 +181,15 @@ protected:
|
|||
u8 m_memrq_cycles;
|
||||
u8 m_iorq_cycles;
|
||||
|
||||
static std::unique_ptr<u8[]> SZ; // zero and sign flags
|
||||
static std::unique_ptr<u8[]> SZ_BIT; // zero, sign and parity/overflow (=zero) flags for BIT opcode
|
||||
static std::unique_ptr<u8[]> SZP; // zero, sign and parity flags
|
||||
static std::unique_ptr<u8[]> SZHV_inc; // zero, sign, half carry and overflow flags INC r8
|
||||
static std::unique_ptr<u8[]> SZHV_dec; // zero, sign, half carry and overflow flags DEC r8
|
||||
static bool tables_initialised;
|
||||
static u8 SZ[0x100]; // zero and sign flags
|
||||
static u8 SZ_BIT[0x100]; // zero, sign and parity/overflow (=zero) flags for BIT opcode
|
||||
static u8 SZP[0x100]; // zero, sign and parity flags
|
||||
static u8 SZHV_inc[0x100]; // zero, sign, half carry and overflow flags INC r8
|
||||
static u8 SZHV_dec[0x100]; // zero, sign, half carry and overflow flags DEC r8
|
||||
|
||||
static std::unique_ptr<u8[]> SZHVC_add;
|
||||
static std::unique_ptr<u8[]> SZHVC_sub;
|
||||
static u8 SZHVC_add[2 * 0x100 * 0x100];
|
||||
static u8 SZHVC_sub[2 * 0x100 * 0x100];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(Z80, z80_device)
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue