mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
hmcs400: fill in most of the opcodes
This commit is contained in:
parent
351dfca54b
commit
df4c6d166b
@ -159,6 +159,8 @@ void hmcs40_cpu_device::device_start()
|
||||
m_eint_line = 0;
|
||||
m_halt = 0;
|
||||
m_prescaler = 0;
|
||||
m_block_int = false;
|
||||
|
||||
m_pc = 0;
|
||||
m_prev_pc = 0;
|
||||
m_page = 0;
|
||||
@ -170,6 +172,7 @@ void hmcs40_cpu_device::device_start()
|
||||
m_spy = 0;
|
||||
m_s = 1;
|
||||
m_c = 0;
|
||||
|
||||
m_tc = 0;
|
||||
m_cf = 0;
|
||||
m_ie = 0;
|
||||
@ -177,7 +180,6 @@ void hmcs40_cpu_device::device_start()
|
||||
memset(m_if, 0, sizeof(m_if));
|
||||
m_tf = 0;
|
||||
memset(m_int, 0, sizeof(m_int));
|
||||
m_block_int = false;
|
||||
memset(m_r, 0, sizeof(m_r));
|
||||
m_d = 0;
|
||||
|
||||
@ -188,6 +190,9 @@ void hmcs40_cpu_device::device_start()
|
||||
save_item(NAME(m_i));
|
||||
save_item(NAME(m_eint_line));
|
||||
save_item(NAME(m_halt));
|
||||
save_item(NAME(m_prescaler));
|
||||
save_item(NAME(m_block_int));
|
||||
|
||||
save_item(NAME(m_pc));
|
||||
save_item(NAME(m_prev_pc));
|
||||
save_item(NAME(m_page));
|
||||
@ -199,8 +204,8 @@ void hmcs40_cpu_device::device_start()
|
||||
save_item(NAME(m_spy));
|
||||
save_item(NAME(m_s));
|
||||
save_item(NAME(m_c));
|
||||
|
||||
save_item(NAME(m_tc));
|
||||
save_item(NAME(m_prescaler));
|
||||
save_item(NAME(m_cf));
|
||||
save_item(NAME(m_ie));
|
||||
save_item(NAME(m_iri));
|
||||
@ -208,7 +213,6 @@ void hmcs40_cpu_device::device_start()
|
||||
save_item(NAME(m_if));
|
||||
save_item(NAME(m_tf));
|
||||
save_item(NAME(m_int));
|
||||
save_item(NAME(m_block_int));
|
||||
save_item(NAME(m_r));
|
||||
save_item(NAME(m_d));
|
||||
|
||||
@ -226,6 +230,9 @@ void hmcs40_cpu_device::device_start()
|
||||
state_add(++m_state_count, "Y", m_y).formatstr("%01X"); // 6
|
||||
state_add(++m_state_count, "SPY", m_spy).formatstr("%01X"); // 7
|
||||
|
||||
state_add(++m_state_count, "S", m_s).formatstr("%01X").noshow(); // 8
|
||||
state_add(++m_state_count, "C", m_c).formatstr("%01X").noshow(); // 9
|
||||
|
||||
set_icountptr(m_icount);
|
||||
}
|
||||
|
||||
|
@ -139,45 +139,47 @@ protected:
|
||||
int m_icount;
|
||||
int m_state_count;
|
||||
|
||||
const int m_pcwidth; // Program Counter bit-width
|
||||
const int m_pcwidth; // program counter bit-width
|
||||
const int m_prgwidth;
|
||||
const int m_datawidth;
|
||||
const int m_family; // MCU family (42-47)
|
||||
const u16 m_polarity; // i/o polarity (pmos vs cmos)
|
||||
const int m_stack_levels; // number of callstack levels
|
||||
const int m_family; // MCU family (42-47)
|
||||
const u16 m_polarity; // i/o polarity (pmos vs cmos)
|
||||
const int m_stack_levels; // number of callstack levels
|
||||
int m_pcmask;
|
||||
int m_prgmask;
|
||||
int m_datamask;
|
||||
u16 m_stack[4]; // max 4
|
||||
u16 m_op; // current opcode
|
||||
u16 m_prev_op;
|
||||
u8 m_i; // 4-bit immediate opcode param
|
||||
int m_eint_line; // which input_line caused an interrupt
|
||||
int m_halt; // internal HLT state
|
||||
u8 m_prescaler; // internal timer prescaler
|
||||
bool m_block_int; // block interrupt on next cycle
|
||||
|
||||
u16 m_pc; // Program Counter
|
||||
u16 m_stack[4]; // max 4
|
||||
u16 m_op; // current opcode
|
||||
u16 m_prev_op;
|
||||
u8 m_i; // 4-bit immediate opcode param
|
||||
int m_eint_line; // which input_line caused an interrupt
|
||||
int m_halt; // internal HLT state
|
||||
u8 m_prescaler; // internal timer prescaler
|
||||
bool m_block_int; // block interrupt on next cycle
|
||||
|
||||
u16 m_pc; // program counter
|
||||
u16 m_prev_pc;
|
||||
u8 m_page; // LPU prepared page
|
||||
u8 m_a; // 4-bit Accumulator
|
||||
u8 m_b; // 4-bit B register
|
||||
u8 m_x; // 1/3/4-bit X register
|
||||
u8 m_spx; // 1/3/4-bit SPX register
|
||||
u8 m_y; // 4-bit Y register
|
||||
u8 m_spy; // 4-bit SPY register
|
||||
u8 m_s; // Status F/F (F/F = flip-flop)
|
||||
u8 m_c; // Carry F/F
|
||||
u8 m_tc; // Timer/Counter
|
||||
u8 m_cf; // CF F/F (timer mode or counter mode)
|
||||
u8 m_ie; // I/E(Interrupt Enable) F/F
|
||||
u8 m_iri; // external interrupt pending I/RI F/F
|
||||
u8 m_irt; // timer interrupt pending I/RT F/F
|
||||
u8 m_if[2]; // external interrupt mask IF0,1 F/F
|
||||
u8 m_tf; // timer interrupt mask TF F/F
|
||||
u8 m_int[2]; // INT0/1 pins state
|
||||
u8 m_r[8]; // R outputs state
|
||||
u16 m_d; // D pins state
|
||||
u8 m_page; // LPU prepared page
|
||||
u8 m_a; // 4-bit accumulator
|
||||
u8 m_b; // 4-bit B register
|
||||
u8 m_x; // 1/3/4-bit X register
|
||||
u8 m_spx; // 1/3/4-bit SPX register
|
||||
u8 m_y; // 4-bit Y register
|
||||
u8 m_spy; // 4-bit SPY register
|
||||
u8 m_s; // status F/F (F/F = flip-flop)
|
||||
u8 m_c; // carry F/F
|
||||
|
||||
u8 m_tc; // timer/counter
|
||||
u8 m_cf; // CF F/F (timer mode or counter mode)
|
||||
u8 m_ie; // I/E (interrupt enable) F/F
|
||||
u8 m_iri; // external interrupt pending I/RI F/F
|
||||
u8 m_irt; // timer interrupt pending I/RT F/F
|
||||
u8 m_if[2]; // external interrupt mask IF0,1 F/F
|
||||
u8 m_tf; // timer interrupt mask TF F/F
|
||||
u8 m_int[2]; // INT0/1 pins state
|
||||
u8 m_r[8]; // R outputs state
|
||||
u16 m_d; // D pins state
|
||||
|
||||
// I/O handlers
|
||||
devcb_read8::array<8> m_read_r;
|
||||
|
@ -36,7 +36,6 @@ void hmcs40_cpu_device::push_stack()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// instruction set
|
||||
|
||||
void hmcs40_cpu_device::op_illegal()
|
||||
@ -144,7 +143,7 @@ void hmcs40_cpu_device::op_ayy()
|
||||
{
|
||||
// AYY: Add A to Y
|
||||
m_y += m_a;
|
||||
m_s = m_y >> 4 & 1;
|
||||
m_s = BIT(m_y, 4);
|
||||
m_y &= 0xf;
|
||||
}
|
||||
|
||||
@ -152,7 +151,7 @@ void hmcs40_cpu_device::op_syy()
|
||||
{
|
||||
// SYY: Subtract A from Y
|
||||
m_y -= m_a;
|
||||
m_s = ~m_y >> 4 & 1;
|
||||
m_s = BIT(~m_y, 4);
|
||||
m_y &= 0xf;
|
||||
}
|
||||
|
||||
@ -253,7 +252,7 @@ void hmcs40_cpu_device::op_ai()
|
||||
{
|
||||
// AI i: Add Immediate to A
|
||||
m_a += m_i;
|
||||
m_s = m_a >> 4 & 1;
|
||||
m_s = BIT(m_a, 4);
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
@ -275,7 +274,7 @@ void hmcs40_cpu_device::op_amc()
|
||||
{
|
||||
// AMC: Add A to Memory with Carry
|
||||
m_a += ram_r() + m_c;
|
||||
m_c = m_a >> 4 & 1;
|
||||
m_c = BIT(m_a, 4);
|
||||
m_s = m_c;
|
||||
m_a &= 0xf;
|
||||
}
|
||||
@ -284,7 +283,7 @@ void hmcs40_cpu_device::op_smc()
|
||||
{
|
||||
// SMC: Subtract A from Memory with Carry
|
||||
m_a = ram_r() - m_a - (m_c ^ 1);
|
||||
m_c = ~m_a >> 4 & 1;
|
||||
m_c = BIT(~m_a, 4);
|
||||
m_s = m_c;
|
||||
m_a &= 0xf;
|
||||
}
|
||||
@ -293,7 +292,7 @@ void hmcs40_cpu_device::op_am()
|
||||
{
|
||||
// AM: Add A to Memory
|
||||
m_a += ram_r();
|
||||
m_s = m_a >> 4 & 1;
|
||||
m_s = BIT(m_a, 4);
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
@ -351,7 +350,7 @@ void hmcs40_cpu_device::op_rotl()
|
||||
{
|
||||
// ROTL: Rotate Left A with Carry
|
||||
m_a = m_a << 1 | m_c;
|
||||
m_c = m_a >> 4 & 1;
|
||||
m_c = BIT(m_a, 4);
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
@ -375,7 +374,7 @@ void hmcs40_cpu_device::op_or()
|
||||
void hmcs40_cpu_device::op_mnei()
|
||||
{
|
||||
// MNEI i: Memory Not Equal to Immediate
|
||||
m_s = (ram_r() != m_i);
|
||||
m_s = (m_i != ram_r());
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_ynei()
|
||||
@ -432,7 +431,7 @@ void hmcs40_cpu_device::op_rem()
|
||||
void hmcs40_cpu_device::op_tm()
|
||||
{
|
||||
// TM n: Test Memory Bit
|
||||
m_s = ram_r() >> (m_op & 3) & 1;
|
||||
m_s = BIT(ram_r(), m_op & 3);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,8 +4,13 @@
|
||||
|
||||
Hitachi HMCS400 MCU family cores
|
||||
|
||||
It's the successor to HMCS40, around 5 times faster, and more versatile peripherals,
|
||||
like a serial interface. It was mainly used in consumer electronics, not much in games.
|
||||
It's the successor to HMCS40, it was mainly used in consumer electronics, not
|
||||
much in games.
|
||||
|
||||
Compared to HMCS40, it accepts a higher clock speed, and it has more versatile
|
||||
peripherals, like a serial interface. The opcodes were mostly kept the same.
|
||||
They added an extra RAM addressing mode, and interrupt-related opcodes were
|
||||
removed (interrupt flags are via memory-mapped I/O).
|
||||
|
||||
TODO:
|
||||
- do the LAW/LWA opcodes not work on early revisions of HMCS400? the 1988 user
|
||||
@ -160,21 +165,57 @@ void hmcs400_cpu_device::device_start()
|
||||
// zerofill
|
||||
m_pc = 0;
|
||||
m_prev_pc = 0;
|
||||
m_sp = 0;
|
||||
m_op = 0;
|
||||
m_param = 0;
|
||||
m_i = 0;
|
||||
|
||||
m_a = 0;
|
||||
m_b = 0;
|
||||
m_w = 0;
|
||||
m_x = 0;
|
||||
m_spx = 0;
|
||||
m_y = 0;
|
||||
m_spy = 0;
|
||||
m_st = 0;
|
||||
m_ca = 0;
|
||||
|
||||
// register for savestates
|
||||
save_item(NAME(m_pc));
|
||||
save_item(NAME(m_prev_pc));
|
||||
save_item(NAME(m_sp));
|
||||
save_item(NAME(m_op));
|
||||
save_item(NAME(m_param));
|
||||
save_item(NAME(m_i));
|
||||
|
||||
save_item(NAME(m_a));
|
||||
save_item(NAME(m_b));
|
||||
save_item(NAME(m_w));
|
||||
save_item(NAME(m_x));
|
||||
save_item(NAME(m_spx));
|
||||
save_item(NAME(m_y));
|
||||
save_item(NAME(m_spy));
|
||||
save_item(NAME(m_st));
|
||||
save_item(NAME(m_ca));
|
||||
|
||||
// register state for debugger
|
||||
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow();
|
||||
state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow();
|
||||
state_add(STATE_GENFLAGS, "GENFLAGS", m_st).formatstr("%2s").noshow();
|
||||
|
||||
int state_count = 0;
|
||||
state_add(++state_count, "PC", m_pc).formatstr("%04X"); // 1
|
||||
m_state_count = 0;
|
||||
state_add(++m_state_count, "PC", m_pc).formatstr("%04X"); // 1
|
||||
state_add(++m_state_count, "SP", m_sp).formatstr("%03X"); // 2
|
||||
state_add(++m_state_count, "A", m_a).formatstr("%01X"); // 3
|
||||
state_add(++m_state_count, "B", m_b).formatstr("%01X"); // 4
|
||||
state_add(++m_state_count, "W", m_w).formatstr("%01X"); // 5
|
||||
state_add(++m_state_count, "X", m_x).formatstr("%01X"); // 6
|
||||
state_add(++m_state_count, "SPX", m_spx).formatstr("%01X"); // 7
|
||||
state_add(++m_state_count, "Y", m_y).formatstr("%01X"); // 8
|
||||
state_add(++m_state_count, "SPY", m_spy).formatstr("%01X"); // 9
|
||||
|
||||
state_add(++m_state_count, "ST", m_st).formatstr("%01X").noshow(); // 10
|
||||
state_add(++m_state_count, "CA", m_ca).formatstr("%01X").noshow(); // 11
|
||||
|
||||
set_icountptr(m_icount);
|
||||
}
|
||||
@ -182,6 +223,28 @@ void hmcs400_cpu_device::device_start()
|
||||
void hmcs400_cpu_device::device_reset()
|
||||
{
|
||||
m_pc = 0;
|
||||
m_sp = 0x3ff;
|
||||
m_st = 1;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// disasm
|
||||
//-------------------------------------------------
|
||||
|
||||
void hmcs400_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
|
||||
{
|
||||
switch (entry.index())
|
||||
{
|
||||
case STATE_GENFLAGS:
|
||||
str = string_format("%c%c",
|
||||
m_ca ? 'C':'c',
|
||||
m_st ? 'S':'s'
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<util::disasm_interface> hmcs400_cpu_device::create_disassembler()
|
||||
@ -219,11 +282,16 @@ device_memory_interface::space_config_vector hmcs400_cpu_device::memory_space_co
|
||||
// execute
|
||||
//-------------------------------------------------
|
||||
|
||||
void hmcs400_cpu_device::cycle()
|
||||
{
|
||||
m_icount--;
|
||||
}
|
||||
|
||||
u16 hmcs400_cpu_device::fetch()
|
||||
{
|
||||
u16 data = m_program->read_word(m_pc);
|
||||
m_pc = (m_pc + 1) & 0x3fff;
|
||||
m_icount--;
|
||||
cycle();
|
||||
|
||||
return data & 0x3ff;
|
||||
}
|
||||
@ -236,12 +304,13 @@ void hmcs400_cpu_device::execute_run()
|
||||
m_prev_pc = m_pc;
|
||||
debugger_instruction_hook(m_pc);
|
||||
m_op = fetch();
|
||||
m_i = m_op & 0xf;
|
||||
|
||||
// 2-byte opcodes / RAM address
|
||||
if ((m_op >= 0x100 && m_op < 0x140) || (m_op >= 0x150 && m_op < 0x1b0))
|
||||
m_param = fetch();
|
||||
else
|
||||
m_param = 0;
|
||||
m_param = (m_w << 8 | m_x << 4 | m_y) & 0x3ff;
|
||||
|
||||
// handle opcode
|
||||
switch (m_op & 0x3f0)
|
||||
@ -255,7 +324,7 @@ void hmcs400_cpu_device::execute_run()
|
||||
case 0x150: op_jmpl(); break;
|
||||
case 0x160: op_call(); break;
|
||||
case 0x170: op_brl(); break;
|
||||
case 0x1a0: op_lmid(); break;
|
||||
case 0x1a0: op_lmi(); break;
|
||||
case 0x1b0: op_p(); break;
|
||||
|
||||
case 0x200: op_lbi(); break;
|
||||
|
@ -45,6 +45,7 @@ protected:
|
||||
|
||||
// device_disasm_interface implementation
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
|
||||
|
||||
// memory maps
|
||||
void program_map(address_map &map);
|
||||
@ -55,26 +56,47 @@ protected:
|
||||
address_space *m_program;
|
||||
address_space *m_data;
|
||||
|
||||
int m_icount;
|
||||
int m_state_count;
|
||||
|
||||
const u32 m_rom_size; // ROM size in 16-bit words
|
||||
const u32 m_ram_size; // RAM size minus the 64-byte stack
|
||||
bool m_has_div; // MCU supports divider mask option
|
||||
u8 m_divider; // system clock divider
|
||||
|
||||
u16 m_pc;
|
||||
u16 m_pc; // program counter
|
||||
u16 m_prev_pc;
|
||||
u16 m_op;
|
||||
u16 m_param;
|
||||
u16 m_sp; // stack pointer
|
||||
u16 m_op; // current opcode
|
||||
u16 m_param; // 2-byte opcode param or RAM address
|
||||
u8 m_i; // 4-bit immediate opcode param
|
||||
|
||||
int m_icount;
|
||||
u8 m_a; // 4-bit accumulator
|
||||
u8 m_b; // 4-bit B register
|
||||
u8 m_w; // 2-bit W register
|
||||
u8 m_x; // 4-bit X register
|
||||
u8 m_spx; // 4-bit SPX register
|
||||
u8 m_y; // 4-bit Y register
|
||||
u8 m_spy; // 4-bit SPY register
|
||||
u8 m_st; // status flag
|
||||
u8 m_ca; // carry flag
|
||||
|
||||
u16 fetch();
|
||||
|
||||
// misc internal helpers
|
||||
u8 ram_r(u8 mem_mask = 0xf);
|
||||
void ram_w(u8 data, u8 mem_mask = 0xf);
|
||||
void pop_stack();
|
||||
void push_stack();
|
||||
|
||||
void cycle();
|
||||
|
||||
// opcode handlers
|
||||
void op_illegal();
|
||||
|
||||
void op_lai();
|
||||
void op_lbi();
|
||||
void op_lmid();
|
||||
void op_lmi();
|
||||
void op_lmiiy();
|
||||
|
||||
void op_lab();
|
||||
|
@ -9,6 +9,46 @@
|
||||
|
||||
// internal helpers
|
||||
|
||||
inline u8 hmcs400_cpu_device::ram_r(u8 mem_mask)
|
||||
{
|
||||
return m_data->read_byte(m_param & 0x3ff, mem_mask & 0xf) & 0xf;
|
||||
}
|
||||
|
||||
inline void hmcs400_cpu_device::ram_w(u8 data, u8 mem_mask)
|
||||
{
|
||||
m_data->write_byte(m_param & 0x3ff, data & 0xf, mem_mask & 0xf);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::pop_stack()
|
||||
{
|
||||
u16 data = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_sp = ((m_sp + 1) | 0x3c0) & 0x3ff;
|
||||
data = data << 4 | (m_data->read_byte(m_sp) & 0xf);
|
||||
}
|
||||
|
||||
if (m_op & 1)
|
||||
{
|
||||
// RTNI restores CA and ST
|
||||
m_ca = BIT(data, 7);
|
||||
m_st = BIT(data, 15);
|
||||
}
|
||||
m_pc = (data & 0x7f00) >> 1 | (data & 0x7f);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::push_stack()
|
||||
{
|
||||
u16 data = (m_pc << 1 & 0x7f00) | (m_pc & 0x7f) | m_ca << 7 | m_st << 15;
|
||||
m_sp |= 0x3c0;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_data->write_byte(m_sp, data & 0xf);
|
||||
data >>= 4;
|
||||
m_sp = ((m_sp - 1) | 0x3c0) & 0x3ff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// instruction set
|
||||
@ -24,21 +64,26 @@ void hmcs400_cpu_device::op_illegal()
|
||||
void hmcs400_cpu_device::op_lai()
|
||||
{
|
||||
// LAI i: Load A from Immediate
|
||||
m_a = m_i;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lbi()
|
||||
{
|
||||
// LBI i: Load B from Immediate
|
||||
m_b = m_i;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lmid()
|
||||
void hmcs400_cpu_device::op_lmi()
|
||||
{
|
||||
// LMID i,d: Load Memory from Immediate
|
||||
ram_w(m_i);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lmiiy()
|
||||
{
|
||||
// LMIIY i: Load Memory from Immediate, Increment Y
|
||||
op_lmi();
|
||||
op_iy();
|
||||
}
|
||||
|
||||
|
||||
@ -47,41 +92,53 @@ void hmcs400_cpu_device::op_lmiiy()
|
||||
void hmcs400_cpu_device::op_lab()
|
||||
{
|
||||
// LAB: Load A from B
|
||||
m_a = m_b;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lba()
|
||||
{
|
||||
// LBA: Load B from A
|
||||
m_b = m_a;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_law()
|
||||
{
|
||||
// LAW: Load A from W
|
||||
m_a = m_w;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lay()
|
||||
{
|
||||
// LAY: Load A from Y
|
||||
m_a = m_y;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_laspx()
|
||||
{
|
||||
// LASPX: Load A from SPX
|
||||
m_a = m_spx;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_laspy()
|
||||
{
|
||||
// LASPY: Load A from SPY
|
||||
m_a = m_spy;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lamr()
|
||||
{
|
||||
// LAMR m: Load A from MR
|
||||
m_param = 0x20 | m_i;
|
||||
m_a = ram_r();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_xmra()
|
||||
{
|
||||
// XMRA m: Exchange MR and A
|
||||
m_param = 0x20 | m_i;
|
||||
u8 old_a = m_a;
|
||||
m_a = ram_r();
|
||||
ram_w(old_a);
|
||||
}
|
||||
|
||||
|
||||
@ -90,56 +147,84 @@ void hmcs400_cpu_device::op_xmra()
|
||||
void hmcs400_cpu_device::op_lwi()
|
||||
{
|
||||
// LWI i: Load W from Immediate
|
||||
m_w = m_i;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lxi()
|
||||
{
|
||||
// LXI i: Load X from Immediate
|
||||
m_x = m_i;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lyi()
|
||||
{
|
||||
// LYI i: Load Y from Immediate
|
||||
m_y = m_i;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lwa()
|
||||
{
|
||||
// LWA: Load W from A
|
||||
m_w = m_a & 3;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lxa()
|
||||
{
|
||||
// LXA: Load X from A
|
||||
m_x = m_a;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lya()
|
||||
{
|
||||
// LYA: Load Y from A
|
||||
m_y = m_a;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_iy()
|
||||
{
|
||||
// IY: Increment Y
|
||||
m_y = (m_y + 1) & 0xf;
|
||||
m_st = (m_y != 0);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_dy()
|
||||
{
|
||||
// DY: Decrement Y
|
||||
m_y = (m_y - 1) & 0xf;
|
||||
m_st = (m_y != 0xf);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_ayy()
|
||||
{
|
||||
// AYY: Add A to Y
|
||||
m_y += m_a;
|
||||
m_st = BIT(m_y, 4);
|
||||
m_y &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_syy()
|
||||
{
|
||||
// SYY: Subtract A from Y
|
||||
m_y -= m_a;
|
||||
m_st = BIT(~m_y, 4);
|
||||
m_y &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_xsp()
|
||||
{
|
||||
// XSP(XY): Exchange X and SPX, Y and SPY, or NOP if 0
|
||||
if (m_op & 1)
|
||||
{
|
||||
u8 old_x = m_x;
|
||||
m_x = m_spx;
|
||||
m_spx = old_x;
|
||||
}
|
||||
if (m_op & 2)
|
||||
{
|
||||
u8 old_y = m_y;
|
||||
m_y = m_spy;
|
||||
m_spy = old_y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -148,36 +233,54 @@ void hmcs400_cpu_device::op_xsp()
|
||||
void hmcs400_cpu_device::op_lam()
|
||||
{
|
||||
// LAM(XY) / LAMD d: Load A from Memory
|
||||
m_a = ram_r();
|
||||
op_xsp();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lbm()
|
||||
{
|
||||
// LBM(XY): Load B from Memory
|
||||
m_b = ram_r();
|
||||
op_xsp();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lma()
|
||||
{
|
||||
// LMA(XY) / LMAD d: Load Memory from A
|
||||
ram_w(m_a);
|
||||
op_xsp();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lmaiy()
|
||||
{
|
||||
// LMAIY(X): Load Memory from A, Increment Y
|
||||
op_lma();
|
||||
op_iy();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_lmady()
|
||||
{
|
||||
// LMADY(X): Load Memory from A, Decrement Y
|
||||
op_lma();
|
||||
op_dy();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_xma()
|
||||
{
|
||||
// XMA(XY) / XMAD d: Exchange Memory and A
|
||||
u8 old_a = m_a;
|
||||
m_a = ram_r();
|
||||
ram_w(old_a);
|
||||
op_xsp();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_xmb()
|
||||
{
|
||||
// XMB(XY): Exchange Memory and B
|
||||
u8 old_b = m_b;
|
||||
m_b = ram_r();
|
||||
ram_w(old_b);
|
||||
op_xsp();
|
||||
}
|
||||
|
||||
|
||||
@ -186,157 +289,217 @@ void hmcs400_cpu_device::op_xmb()
|
||||
void hmcs400_cpu_device::op_ai()
|
||||
{
|
||||
// AI i: Add Immediate to A
|
||||
m_a += m_i;
|
||||
m_st = BIT(m_a, 4);
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_ib()
|
||||
{
|
||||
// IB: Increment B
|
||||
m_b = (m_b + 1) & 0xf;
|
||||
m_st = (m_b != 0);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_db()
|
||||
{
|
||||
// DB: Decrement B
|
||||
m_b = (m_b - 1) & 0xf;
|
||||
m_st = (m_b != 0xf);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_daa()
|
||||
{
|
||||
// DAA: Decimal Adjust for Addition
|
||||
if (m_ca || m_a > 9)
|
||||
{
|
||||
m_a = (m_a + 6) & 0xf;
|
||||
m_ca = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_das()
|
||||
{
|
||||
// DAS: Decimal Adjust for Subtraction
|
||||
if (!m_ca || m_a > 9)
|
||||
{
|
||||
m_a = (m_a + 10) & 0xf;
|
||||
m_ca = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_nega()
|
||||
{
|
||||
// NEGA: Negate A
|
||||
m_a = (0 - m_a) & 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_comb()
|
||||
{
|
||||
// COMB: Complement B
|
||||
m_b ^= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_rotr()
|
||||
{
|
||||
// ROTR: Rotate Right with Carry
|
||||
u8 ca = m_a & 1;
|
||||
m_a = m_a >> 1 | m_ca << 3;
|
||||
m_ca = ca;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_rotl()
|
||||
{
|
||||
// ROTL: Rotate Left with Carry
|
||||
m_a = m_a << 1 | m_ca;
|
||||
m_ca = BIT(m_a, 4);
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_sec()
|
||||
{
|
||||
// SEC: Set Carry
|
||||
m_ca = 1;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_rec()
|
||||
{
|
||||
// REC: Reset Carry
|
||||
m_ca = 0;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_tc()
|
||||
{
|
||||
// TC: Test Carry
|
||||
m_st = m_ca;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_am()
|
||||
{
|
||||
// AM / AMD d: Add A to Memory
|
||||
m_a += ram_r();
|
||||
m_st = BIT(m_a, 4);
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_amc()
|
||||
{
|
||||
// AMC / AMCD d: Add A to Memory with Carry
|
||||
m_a += ram_r() + m_ca;
|
||||
m_ca = BIT(m_a, 4);
|
||||
m_st = m_ca;
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_smc()
|
||||
{
|
||||
// SMC / SMCD d: Subtract A from Memory with Carry
|
||||
m_a = ram_r() - m_a - (m_ca ^ 1);
|
||||
m_ca = BIT(~m_a, 4);
|
||||
m_st = m_ca;
|
||||
m_a &= 0xf;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_or()
|
||||
{
|
||||
// OR: Or A with B
|
||||
m_a |= m_b;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_anm()
|
||||
{
|
||||
// ANM / ANMD d: And Memory with A
|
||||
m_a &= ram_r();
|
||||
m_st = (m_a != 0);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_orm()
|
||||
{
|
||||
// ORM / ORMD d: Or Memory with A
|
||||
m_a |= ram_r();
|
||||
m_st = (m_a != 0);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_eorm()
|
||||
{
|
||||
// EORM / EORMD d: Exclusive Or Memory with A
|
||||
}
|
||||
|
||||
|
||||
// RAM bit manipulation instructions
|
||||
|
||||
void hmcs400_cpu_device::op_inem()
|
||||
{
|
||||
// INEM i / INEMD i,d: Immediate Not Equal to Memory
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_anem()
|
||||
{
|
||||
// ANEM / ANEMD d: A Not Equal to Memory
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_bnem()
|
||||
{
|
||||
// BNEM: B Not Equal to Memory
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_ynei()
|
||||
{
|
||||
// YNEI i: Y Not Equal to Immediate
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_ilem()
|
||||
{
|
||||
// ILEM i / ILEMD i,d: Immediate Less or Equal to Memory
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_alem()
|
||||
{
|
||||
// ALEM / ALEMD d: A Less or Equal to Memory
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_blem()
|
||||
{
|
||||
// BLEM: B Less or Equal to Memory
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_alei()
|
||||
{
|
||||
// ALEI i: A Less or Equal to Immediate
|
||||
m_a ^= ram_r();
|
||||
m_st = (m_a != 0);
|
||||
}
|
||||
|
||||
|
||||
// compare instructions
|
||||
|
||||
void hmcs400_cpu_device::op_inem()
|
||||
{
|
||||
// INEM i / INEMD i,d: Immediate Not Equal to Memory
|
||||
m_st = (m_i != ram_r());
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_anem()
|
||||
{
|
||||
// ANEM / ANEMD d: A Not Equal to Memory
|
||||
m_st = (m_a != ram_r());
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_bnem()
|
||||
{
|
||||
// BNEM: B Not Equal to Memory
|
||||
m_st = (m_b != ram_r());
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_ynei()
|
||||
{
|
||||
// YNEI i: Y Not Equal to Immediate
|
||||
m_st = (m_y != m_i);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_ilem()
|
||||
{
|
||||
// ILEM i / ILEMD i,d: Immediate Less or Equal to Memory
|
||||
m_st = (m_i <= ram_r());
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_alem()
|
||||
{
|
||||
// ALEM / ALEMD d: A Less or Equal to Memory
|
||||
m_st = (m_a <= ram_r());
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_blem()
|
||||
{
|
||||
// BLEM: B Less or Equal to Memory
|
||||
m_st = (m_b <= ram_r());
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_alei()
|
||||
{
|
||||
// ALEI i: A Less or Equal to Immediate
|
||||
m_st = (m_a <= m_i);
|
||||
}
|
||||
|
||||
|
||||
// RAM bit manipulation instructions
|
||||
|
||||
void hmcs400_cpu_device::op_sem()
|
||||
{
|
||||
// SEM n / SEMD n,d: Set Memory Bit
|
||||
u8 mask = 1 << (m_op & 3);
|
||||
ram_w(ram_r(~mask) | mask, mask);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_rem()
|
||||
{
|
||||
// REM n / REMD n,d: Reset Memory Bit
|
||||
u8 mask = 1 << (m_op & 3);
|
||||
ram_w(ram_r(~mask) & ~mask, mask);
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_tm()
|
||||
{
|
||||
// TM n / TMD n,d: Test Memory Bit
|
||||
u8 mask = 1 << (m_op & 3);
|
||||
m_st = (ram_r(mask) & mask) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
@ -345,41 +508,70 @@ void hmcs400_cpu_device::op_tm()
|
||||
void hmcs400_cpu_device::op_br()
|
||||
{
|
||||
// BR b: Branch on Status 1
|
||||
if (m_st)
|
||||
m_pc = (m_pc & ~0xff) | (m_op & 0xff);
|
||||
else
|
||||
m_st = 1;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_brl()
|
||||
{
|
||||
// BRL u: Long Branch on Status 1
|
||||
if (m_st)
|
||||
op_jmpl();
|
||||
else
|
||||
m_st = 1;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_jmpl()
|
||||
{
|
||||
// JMPL u: Long Jump Unconditionally
|
||||
m_pc = m_i << 10 | m_param;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_cal()
|
||||
{
|
||||
// CAL a: Subroutine Jump on Status 1
|
||||
if (m_st)
|
||||
{
|
||||
push_stack();
|
||||
m_pc = m_op & 0x3f;
|
||||
cycle();
|
||||
}
|
||||
else
|
||||
m_st = 1;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_call()
|
||||
{
|
||||
// CALL u: Long Subroutine Jump on Status 1
|
||||
if (m_st)
|
||||
{
|
||||
push_stack();
|
||||
op_jmpl();
|
||||
}
|
||||
else
|
||||
m_st = 1;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_tbr()
|
||||
{
|
||||
// TBR p: Table Branch
|
||||
m_pc = m_i << 8 | m_b << 4 | m_a;
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_rtn()
|
||||
{
|
||||
// RTN: Return from Subroutine
|
||||
pop_stack();
|
||||
cycle();
|
||||
cycle();
|
||||
}
|
||||
|
||||
void hmcs400_cpu_device::op_rtni()
|
||||
{
|
||||
// RTNI: Return from Interrupt
|
||||
op_rtn();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user