mame/src/devices/cpu/e132xs/e132xs.cpp
2018-01-28 14:25:52 +11:00

1947 lines
63 KiB
C++

// license:BSD-3-Clause
// copyright-holders:Pierpaolo Prazzoli
/********************************************************************
Hyperstone cpu emulator
written by Pierpaolo Prazzoli
All the types are compatible, but they have different IRAM size and cycles
Hyperstone models:
16 bits
- E1-16T
- E1-16XT
- E1-16XS
- E1-16XSR
32bits
- E1-32N or E1-32T
- E1-32XN or E1-32XT
- E1-32XS
- E1-32XSR
Hynix models:
16 bits
- GMS30C2116
- GMS30C2216
32bits
- GMS30C2132
- GMS30C2232
TODO:
- some wrong cycle counts
- verify register wrapping with sregf/dregf on hardware
CHANGELOG:
Pierpaolo Prazzoli
- Fixed LDxx.N/P/S opcodes not to increment the destination register when
it's the same as the source or "next source" one.
Pierpaolo Prazzoli
- Removed nested delays
- Added better delay branch support
- Fixed PC seen by a delay instruction, because a delay instruction
should use the delayed PC (thus allowing the execution of software
opcodes too)
Tomasz Slanina
- Fixed delayed branching for delay instructions longer than 2 bytes
Pierpaolo Prazzoli
- Added and fixed Timer without hack
Tomasz Slanina
- Fixed MULU/MULS
- Fixed Carry in ADDC/SUBC
Pierpaolo Prazzoli
- Fixed software opcodes used as delay instructions
- Added nested delays
Tomasz Slanina
- Added "undefined" C flag to shift left instructions
Pierpaolo Prazzoli
- Added interrupts-block for delay instructions
- Fixed get_emu_code_addr
- Added LDW.S and STW.S instructions
- Fixed floating point opcodes
Tomasz Slanina
- interrputs after call and before frame are prohibited now
- emulation of FCR register
- Floating point opcodes (preliminary)
- Fixed stack addressing in RET/FRAME opcodes
- Fixed bug in SET_RS macro
- Fixed bug in return opcode (S flag)
- Added C/N flags calculation in add/adc/addi/adds/addsi and some shift opcodes
- Added writeback to ROL
- Fixed ROL/SAR/SARD/SHR/SHRD/SHL/SHLD opcode decoding (Local/Global regs)
- Fixed I and T flag in RET opcode
- Fixed XX/XM opcodes
- Fixed MOV opcode, when RD = PC
- Fixed execute_trap()
- Fixed ST opcodes, when when RS = SR
- Added interrupts
- Fixed I/O addressing
Pierpaolo Prazzoli
- Fixed fetch
- Fixed decode of hyperstone_xm opcode
- Fixed 7 bits difference number in FRAME / RET instructions
- Some debbugger fixes
- Added generic registers decode function
- Some other little fixes.
Ryan Holtz 29/03/2004
- Changed MOVI to use unsigned values instead of signed, correcting
an ugly glitch when loading 32-bit immediates.
Pierpaolo Prazzoli
- Same fix in get_const
Pierpaolo Prazzoli - 02/25/04
- Fixed some wrong addresses to address local registers instead of memory
- Fixed FRAME and RET instruction
- Added preliminary I/O space
- Fixed some load / store instructions
Pierpaolo Prazzoli - 02/20/04
- Added execute_exception function
- Added FL == 0 always interpreted as 16
Pierpaolo Prazzoli - 02/19/04
- Changed the reset to use the execute_trap(reset) which should be right to set
the initiale state of the cpu
- Added Trace exception
- Set of T flag in RET instruction
- Set I flag in interrupts entries and resetted by a RET instruction
- Added correct set instruction for SR
Pierpaolo Prazzoli - 10/26/03
- Changed get_lrconst to get_const and changed it to use the removed GET_CONST_RR
macro.
- Removed the High flag used in some opcodes, it should be used only in
MOV and MOVI instruction.
- Fixed MOV and MOVI instruction.
- Set to 1 FP is SR register at reset.
(From the doc: A Call, Trap or Software instruction increments the FP and sets FL
to 6, thus creating a new stack frame with the length of 6 registers).
Pierpaolo Prazzoli - 08/19/03
- Added check for D_BIT and S_BIT where PC or SR must or must not be denoted.
(movd, divu, divs, ldxx1, ldxx2, stxx1, stxx2, mulu, muls, set, mul
call, chk)
Pierpaolo Prazzoli - 08/17/03
- Fixed get_pcrel() when OP & 0x80 is set.
- Decremented PC by 2 also in MOV, ADD, ADDI, SUM, SUB and added the check if
D_BIT is not set. (when pc is changed they are implicit branch)
*********************************************************************/
#include "emu.h"
#include "e132xs.h"
#include "e132xsfe.h"
#include "debugger.h"
#include "32xsdefs.h"
//#define VERBOSE 1
#include "logmacro.h"
/* size of the execution code cache */
#define CACHE_SIZE (32 * 1024 * 1024)
//**************************************************************************
// INTERNAL ADDRESS MAP
//**************************************************************************
// 4Kb IRAM (On-Chip Memory)
static ADDRESS_MAP_START( e116_4k_iram_map, AS_PROGRAM, 16, hyperstone_device )
AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM AM_MIRROR(0x1ffff000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( e132_4k_iram_map, AS_PROGRAM, 32, hyperstone_device )
AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM AM_MIRROR(0x1ffff000)
ADDRESS_MAP_END
// 8Kb IRAM (On-Chip Memory)
static ADDRESS_MAP_START( e116_8k_iram_map, AS_PROGRAM, 16, hyperstone_device )
AM_RANGE(0xc0000000, 0xc0001fff) AM_RAM AM_MIRROR(0x1fffe000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( e132_8k_iram_map, AS_PROGRAM, 32, hyperstone_device )
AM_RANGE(0xc0000000, 0xc0001fff) AM_RAM AM_MIRROR(0x1fffe000)
ADDRESS_MAP_END
// 16Kb IRAM (On-Chip Memory)
static ADDRESS_MAP_START( e116_16k_iram_map, AS_PROGRAM, 16, hyperstone_device )
AM_RANGE(0xc0000000, 0xc0003fff) AM_RAM AM_MIRROR(0x1fffc000)
ADDRESS_MAP_END
static ADDRESS_MAP_START( e132_16k_iram_map, AS_PROGRAM, 32, hyperstone_device )
AM_RANGE(0xc0000000, 0xc0003fff) AM_RAM AM_MIRROR(0x1fffc000)
ADDRESS_MAP_END
//-------------------------------------------------
// hyperstone_device - constructor
//-------------------------------------------------
hyperstone_device::hyperstone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
const device_type type, uint32_t prg_data_width, uint32_t io_data_width, address_map_constructor internal_map)
: cpu_device(mconfig, type, tag, owner, clock)
, m_program_config("program", ENDIANNESS_BIG, prg_data_width, 32, 0, internal_map)
, m_io_config("io", ENDIANNESS_BIG, io_data_width, 15)
, m_cache(CACHE_SIZE + sizeof(hyperstone_device))
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
, m_cache_dirty(0)
, m_entry(nullptr)
, m_nocode(nullptr)
, m_out_of_cycles(nullptr)
, m_mem_read8(nullptr)
, m_mem_write8(nullptr)
, m_mem_read16(nullptr)
, m_mem_write16(nullptr)
, m_mem_read32(nullptr)
, m_mem_write32(nullptr)
, m_io_read32(nullptr)
, m_io_write32(nullptr)
, m_enable_drc(false)
{
}
//-------------------------------------------------
// e116t_device - constructor
//-------------------------------------------------
e116t_device::e116t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E116T, 16, 16, ADDRESS_MAP_NAME(e116_4k_iram_map))
{
}
//-------------------------------------------------
// e116xt_device - constructor
//-------------------------------------------------
e116xt_device::e116xt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E116XT, 16, 16, ADDRESS_MAP_NAME(e116_8k_iram_map))
{
}
//-------------------------------------------------
// e116xs_device - constructor
//-------------------------------------------------
e116xs_device::e116xs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E116XS, 16, 16, ADDRESS_MAP_NAME(e116_16k_iram_map))
{
}
//-------------------------------------------------
// e116xsr_device - constructor
//-------------------------------------------------
e116xsr_device::e116xsr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E116XSR, 16, 16, ADDRESS_MAP_NAME(e116_16k_iram_map))
{
}
//-------------------------------------------------
// e132n_device - constructor
//-------------------------------------------------
e132n_device::e132n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E132N, 32, 32, ADDRESS_MAP_NAME(e132_4k_iram_map))
{
}
//-------------------------------------------------
// e132t_device - constructor
//-------------------------------------------------
e132t_device::e132t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E132T, 32, 32, ADDRESS_MAP_NAME(e132_4k_iram_map))
{
}
//-------------------------------------------------
// e132xn_device - constructor
//-------------------------------------------------
e132xn_device::e132xn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E132XN, 32, 32, ADDRESS_MAP_NAME(e132_8k_iram_map))
{
}
//-------------------------------------------------
// e132xt_device - constructor
//-------------------------------------------------
e132xt_device::e132xt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E132XT, 32, 32, ADDRESS_MAP_NAME(e132_8k_iram_map))
{
}
//-------------------------------------------------
// e132xs_device - constructor
//-------------------------------------------------
e132xs_device::e132xs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E132XS, 32, 32, ADDRESS_MAP_NAME(e132_16k_iram_map))
{
}
//-------------------------------------------------
// e132xsr_device - constructor
//-------------------------------------------------
e132xsr_device::e132xsr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, E132XSR, 32, 32, ADDRESS_MAP_NAME(e132_16k_iram_map))
{
}
//-------------------------------------------------
// gms30c2116_device - constructor
//-------------------------------------------------
gms30c2116_device::gms30c2116_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, GMS30C2116, 16, 16, ADDRESS_MAP_NAME(e116_4k_iram_map))
{
}
//-------------------------------------------------
// gms30c2132_device - constructor
//-------------------------------------------------
gms30c2132_device::gms30c2132_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, GMS30C2132, 32, 32, ADDRESS_MAP_NAME(e132_4k_iram_map))
{
}
//-------------------------------------------------
// gms30c2216_device - constructor
//-------------------------------------------------
gms30c2216_device::gms30c2216_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, GMS30C2216, 16, 16, ADDRESS_MAP_NAME(e116_8k_iram_map))
{
}
//-------------------------------------------------
// gms30c2232_device - constructor
//-------------------------------------------------
gms30c2232_device::gms30c2232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: hyperstone_device(mconfig, tag, owner, clock, GMS30C2232, 32, 32, ADDRESS_MAP_NAME(e132_8k_iram_map))
{
}
/* Return the entry point for a determinated trap */
uint32_t hyperstone_device::get_trap_addr(uint8_t trapno)
{
uint32_t addr;
if( m_core->trap_entry == 0xffffff00 ) /* @ MEM3 */
{
addr = trapno * 4;
}
else
{
addr = (63 - trapno) * 4;
}
addr |= m_core->trap_entry;
return addr;
}
/* Return the entry point for a determinated emulated code (the one for "extend" opcode is reserved) */
uint32_t hyperstone_device::get_emu_code_addr(uint8_t num) /* num is OP */
{
uint32_t addr;
if( m_core->trap_entry == 0xffffff00 ) /* @ MEM3 */
{
addr = (m_core->trap_entry - 0x100) | ((num & 0xf) << 4);
}
else
{
addr = m_core->trap_entry | (0x10c | ((0xcf - num) << 4));
}
return addr;
}
/*static*/ const uint32_t hyperstone_device::s_trap_entries[8] = {
0x00000000, // MEM0
0x40000000, // MEM1
0x80000000, // MEM2
0xc0000000, // IRAM
0,
0,
0,
0xffffff00, // MEM3
};
#if E132XS_LOG_INTERPRETER_REGS
void hyperstone_device::dump_registers()
{
static uint64_t total_ops = 0;
//static uint64_t total_11094 = 0;
total_ops++;
if (total_ops < 0ULL)
{
//if (m_core->global_regs[0] == 0x11094)
//{
// total_11094++;
//}
return;
} else if (total_ops == 0ULL) {
//printf("Total non-log hits of 0x11094: %d\n", (uint32_t)total_11094);
}
uint8_t packed[4];
packed[0] = (uint8_t)m_core->intblock;
packed[1] = (uint8_t)(m_core->icount >> 16);
packed[2] = (uint8_t)(m_core->icount >> 8);
packed[3] = (uint8_t)(m_core->icount >> 0);
fwrite(packed, 1, 4, m_trace_log);
fwrite(m_core->global_regs, 4, 32, m_trace_log);
fwrite(m_core->local_regs, 4, 64, m_trace_log);
}
#endif
void hyperstone_device::compute_tr()
{
uint64_t cycles_since_base = total_cycles() - m_core->tr_base_cycles;
uint64_t clocks_since_base = cycles_since_base >> m_core->clck_scale;
m_core->tr_result = m_core->tr_base_value + (clocks_since_base / m_core->tr_clocks_per_tick);
}
void hyperstone_device::update_timer_prescale()
{
TPR &= ~0x80000000;
m_core->clck_scale = (TPR >> 26) & m_core->clock_scale_mask;
m_core->clock_cycles_1 = 1 << m_core->clck_scale;
m_core->clock_cycles_2 = 2 << m_core->clck_scale;
m_core->clock_cycles_3 = 3 << m_core->clck_scale;
m_core->clock_cycles_4 = 4 << m_core->clck_scale;
m_core->clock_cycles_6 = 6 << m_core->clck_scale;
m_core->clock_cycles_36 = 36 << m_core->clck_scale;
m_core->tr_clocks_per_tick = ((TPR >> 16) & 0xff) + 2;
m_core->tr_base_value = m_core->tr_result;
m_core->tr_base_cycles = total_cycles();
}
void hyperstone_device::adjust_timer_interrupt()
{
uint64_t cycles_since_base = total_cycles() - m_core->tr_base_cycles;
uint64_t clocks_since_base = cycles_since_base >> m_core->clck_scale;
uint64_t cycles_until_next_clock = cycles_since_base - (clocks_since_base << m_core->clck_scale);
if (cycles_until_next_clock == 0)
cycles_until_next_clock = (uint64_t)(1 << m_core->clck_scale);
/* special case: if we have a change pending, set a timer to fire then */
if (TPR & 0x80000000)
{
uint64_t clocks_until_int = m_core->tr_clocks_per_tick - (clocks_since_base % m_core->tr_clocks_per_tick);
uint64_t cycles_until_int = (clocks_until_int << m_core->clck_scale) + cycles_until_next_clock;
m_timer->adjust(cycles_to_attotime(cycles_until_int + 1), 1);
}
/* else if the timer interrupt is enabled, configure it to fire at the appropriate time */
else if (!(FCR & 0x00800000))
{
uint32_t curtr = m_core->tr_base_value + (clocks_since_base / m_core->tr_clocks_per_tick);
uint32_t delta = TCR - curtr;
if (delta > 0x80000000)
{
if (!m_core->timer_int_pending)
m_timer->adjust(attotime::zero);
}
else
{
uint64_t clocks_until_int = mulu_32x32(delta, m_core->tr_clocks_per_tick);
uint64_t cycles_until_int = (clocks_until_int << m_core->clck_scale) + cycles_until_next_clock;
m_timer->adjust(cycles_to_attotime(cycles_until_int));
}
}
/* otherwise, disable the timer */
else
m_timer->adjust(attotime::never);
}
TIMER_CALLBACK_MEMBER( hyperstone_device::timer_callback )
{
int update = param;
/* update the values if necessary */
if (update)
{
update_timer_prescale();
}
/* see if the timer is right for firing */
compute_tr();
if (!((m_core->tr_result - TCR) & 0x80000000))
m_core->timer_int_pending = 1;
/* adjust ourselves for the next time */
else
adjust_timer_interrupt();
}
uint32_t hyperstone_device::get_global_register(uint8_t code)
{
/*
if( code >= 16 )
{
switch( code )
{
case 16:
case 17:
case 28:
case 29:
case 30:
case 31:
LOG("read _Reserved_ Global Register %d @ %08X\n",code,PC);
break;
case BCR_REGISTER:
LOG("read write-only BCR register @ %08X\n",PC);
return 0;
case TPR_REGISTER:
LOG("read write-only TPR register @ %08X\n",PC);
return 0;
case FCR_REGISTER:
LOG("read write-only FCR register @ %08X\n",PC);
return 0;
case MCR_REGISTER:
LOG("read write-only MCR register @ %08X\n",PC);
return 0;
}
}
*/
if (code == TR_REGISTER)
{
/* it is common to poll this in a loop */
if (m_core->icount > m_core->tr_clocks_per_tick / 2)
m_core->icount -= m_core->tr_clocks_per_tick / 2;
compute_tr();
return m_core->tr_result;
}
return m_core->global_regs[code & 0x1f];
}
void hyperstone_device::set_local_register(uint8_t code, uint32_t val)
{
m_core->local_regs[(code + GET_FP) & 0x3f] = val;
}
void hyperstone_device::set_global_register(uint8_t code, uint32_t val)
{
//TODO: add correct FER set instruction
code &= 0x1f;
switch (code)
{
case PC_REGISTER:
SET_PC(val);
return;
case SR_REGISTER:
SET_LOW_SR(val); // only a RET instruction can change the full content of SR
SR &= ~0x40; //reserved bit 6 always zero
if (m_core->intblock < 1)
m_core->intblock = 1;
return;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
// are the below ones set only when privilege bit is set?
case 17:
m_core->global_regs[code] = val;
return;
case SP_REGISTER:
case UB_REGISTER:
m_core->global_regs[code] = val & ~3;
return;
case BCR_REGISTER:
m_core->global_regs[code] = val;
return;
case TPR_REGISTER:
m_core->global_regs[code] = val;
if (!(val & 0x80000000)) /* change immediately */
{
compute_tr();
update_timer_prescale();
}
adjust_timer_interrupt();
return;
case TCR_REGISTER:
if (m_core->global_regs[code] != val)
{
m_core->global_regs[code] = val;
adjust_timer_interrupt();
if (m_core->intblock < 1)
m_core->intblock = 1;
}
return;
case TR_REGISTER:
m_core->global_regs[code] = val;
m_core->tr_base_value = val;
m_core->tr_base_cycles = total_cycles();
adjust_timer_interrupt();
return;
case WCR_REGISTER:
m_core->global_regs[code] = val;
return;
case ISR_REGISTER:
return;
case FCR_REGISTER:
if ((m_core->global_regs[code] ^ val) & 0x00800000)
adjust_timer_interrupt();
m_core->global_regs[code] = val;
if (m_core->intblock < 1)
m_core->intblock = 1;
return;
case MCR_REGISTER:
{
// bits 14..12 EntryTableMap
const int which = (val & 0x7000) >> 12;
assert(which < 4 || which == 7);
m_core->trap_entry = s_trap_entries[which];
m_core->global_regs[code] = val;
return;
}
case 28:
case 29:
case 30:
case 31:
m_core->global_regs[code] = val;
return;
}
}
/*static*/ const int32_t hyperstone_device::s_immediate_values[16] =
{
16, 0, 0, 0, 32, 64, 128, int32_t(0x80000000),
-8, -7, -6, -5, -4, -3, -2, -1
};
constexpr uint32_t WRITE_ONLY_REGMASK = (1 << BCR_REGISTER) | (1 << TPR_REGISTER) | (1 << FCR_REGISTER) | (1 << MCR_REGISTER);
#define check_delay_PC() \
do \
{ \
/* if PC is used in a delay instruction, the delayed PC should be used */ \
if (m_core->delay_slot) \
{ \
PC = m_core->delay_pc; \
m_core->delay_slot = 0; \
} \
} while (0)
void hyperstone_device::ignore_immediate_s()
{
static const uint32_t lengths[16] = { 1<<19, 3<<19, 2<<19, 2<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19 };
static const uint32_t offsets[16] = { 0, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const uint8_t nybble = m_op & 0x0f;
m_instruction_length = lengths[nybble];
PC += offsets[nybble];
}
uint32_t hyperstone_device::decode_immediate_s()
{
const uint8_t nybble = m_op & 0x0f;
switch (nybble)
{
case 0:
return 16;
case 1:
{
m_instruction_length = (3<<19);
uint32_t extra_u = (READ_OP(PC) << 16) | READ_OP(PC + 2);
PC += 4;
return extra_u;
}
case 2:
{
m_instruction_length = (2<<19);
uint32_t extra_u = READ_OP(PC);
PC += 2;
return extra_u;
}
case 3:
{
m_instruction_length = (2<<19);
uint32_t extra_u = 0xffff0000 | READ_OP(PC);
PC += 2;
return extra_u;
}
default:
return s_immediate_values[nybble];
}
}
uint32_t hyperstone_device::decode_const()
{
const uint16_t imm_1 = READ_OP(PC);
PC += 2;
m_instruction_length = (2<<19);
if (imm_1 & 0x8000)
{
const uint16_t imm_2 = READ_OP(PC);
PC += 2;
m_instruction_length = (3<<19);
uint32_t imm = imm_2;
imm |= ((imm_1 & 0x3fff) << 16);
if (imm_1 & 0x4000)
imm |= 0xc0000000;
return imm;
}
else
{
uint32_t imm = imm_1 & 0x3fff;
if (imm_1 & 0x4000)
imm |= 0xffffc000;
return imm;
}
}
int32_t hyperstone_device::decode_pcrel()
{
if (OP & 0x80)
{
uint16_t next = READ_OP(PC);
PC += 2;
m_instruction_length = (2<<19);
int32_t offset = (OP & 0x7f) << 16;
offset |= (next & 0xfffe);
if (next & 1)
offset |= 0xff800000;
return offset;
}
else
{
int32_t offset = OP & 0x7e;
if (OP & 1)
offset |= 0xffffff80;
return offset;
}
}
void hyperstone_device::ignore_pcrel()
{
if (m_op & 0x80)
{
PC += 2;
m_instruction_length = (2<<19);
}
}
void hyperstone_device::hyperstone_br()
{
const int32_t offset = decode_pcrel();
check_delay_PC();
PC += offset;
SR &= ~M_MASK;
m_core->icount -= m_core->clock_cycles_2;
}
void hyperstone_device::execute_trap(uint32_t addr)
{
const uint8_t reg = GET_FP + GET_FL;
SET_ILC(m_instruction_length);
const uint32_t oldSR = SR;
SET_FL(6);
SET_FP(reg);
m_core->local_regs[(0 + reg) & 0x3f] = (PC & ~1) | GET_S;
m_core->local_regs[(1 + reg) & 0x3f] = oldSR;
SR &= ~(M_MASK | T_MASK);
SR |= (L_MASK | S_MASK);
PC = addr;
m_core->icount -= m_core->clock_cycles_2;
}
void hyperstone_device::execute_int(uint32_t addr)
{
const uint8_t reg = GET_FP + GET_FL;
SET_ILC(m_instruction_length);
const uint32_t oldSR = SR;
SET_FL(2);
SET_FP(reg);
m_core->local_regs[(0 + reg) & 0x3f] = (PC & ~1) | GET_S;
m_core->local_regs[(1 + reg) & 0x3f] = oldSR;
SR &= ~(M_MASK | T_MASK);
SR |= (L_MASK | S_MASK | I_MASK);
PC = addr;
m_core->icount -= m_core->clock_cycles_2;
}
/* TODO: mask Parity Error and Extended Overflow exceptions */
void hyperstone_device::execute_exception(uint32_t addr)
{
const uint8_t reg = GET_FP + GET_FL;
SET_ILC(m_instruction_length);
const uint32_t oldSR = SR;
SET_FL(2);
SET_FP(reg);
m_core->local_regs[(0 + reg) & 0x3f] = (PC & ~1) | GET_S;
m_core->local_regs[(1 + reg) & 0x3f] = oldSR;
SR &= ~(M_MASK | T_MASK);
SR |= (L_MASK | S_MASK);
PC = addr;
m_core->icount -= m_core->clock_cycles_2;
}
void hyperstone_device::execute_software()
{
check_delay_PC();
const uint32_t fp = GET_FP;
const uint32_t src_code = SRC_CODE;
const uint32_t sreg = m_core->local_regs[(src_code + fp) & 0x3f];
const uint32_t sregf = m_core->local_regs[(src_code + 1 + fp) & 0x3f];
SET_ILC(1<<19);
const uint32_t addr = get_emu_code_addr((m_op & 0xff00) >> 8);
const uint8_t reg = fp + GET_FL;
//since it's sure the register is in the register part of the stack,
//set the stack address to a value above the highest address
//that can be set by a following frame instruction
const uint32_t stack_of_dst = (SP & ~0xff) + 0x100 + (((fp + DST_CODE) & 0x3f) << 2); //converted to 32bits offset
m_core->local_regs[(reg + 0) & 0x3f] = stack_of_dst;
m_core->local_regs[(reg + 1) & 0x3f] = sreg;
m_core->local_regs[(reg + 2) & 0x3f] = sregf;
m_core->local_regs[(reg + 3) & 0x3f] = (PC & ~1) | GET_S;
m_core->local_regs[(reg + 4) & 0x3f] = SR;
SET_FL(6);
SET_FP(reg);
SR &= ~(M_MASK | T_MASK);
SR |= L_MASK;
PC = addr;
m_core->icount -= m_core->clock_cycles_6;
}
/*
IRQ lines :
0 - IO2 (trap 48)
1 - IO1 (trap 49)
2 - INT4 (trap 50)
3 - INT3 (trap 51)
4 - INT2 (trap 52)
5 - INT1 (trap 53)
6 - IO3 (trap 54)
7 - TIMER (trap 55)
*/
#define INT1_LINE_STATE (ISR & 0x01)
#define INT2_LINE_STATE (ISR & 0x02)
#define INT3_LINE_STATE (ISR & 0x04)
#define INT4_LINE_STATE (ISR & 0x08)
#define IO1_LINE_STATE (ISR & 0x10)
#define IO2_LINE_STATE (ISR & 0x20)
#define IO3_LINE_STATE (ISR & 0x40)
template <hyperstone_device::is_timer TIMER>
void hyperstone_device::check_interrupts()
{
/* Interrupt-Lock flag isn't set */
if (GET_L || m_core->intblock > 0)
return;
/* quick exit if nothing */
if (TIMER == NO_TIMER && (ISR & 0x7f) == 0)
return;
if (TIMER == NO_TIMER)
{
/* IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt */
if (IO3_LINE_STATE && (FCR & 0x00000500) == 0x00000400)
{
execute_int(get_trap_addr(TRAPNO_IO3));
standard_irq_callback(IRQ_IO3);
return;
}
/* INT1 is priority 7; state is in bit 0 of ISR; FCR bit 28 inhibits interrupt */
if (INT1_LINE_STATE && (FCR & 0x10000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT1));
standard_irq_callback(IRQ_INT1);
return;
}
/* INT2 is priority 9; state is in bit 1 of ISR; FCR bit 29 inhibits interrupt */
if (INT2_LINE_STATE && (FCR & 0x20000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT2));
standard_irq_callback(IRQ_INT2);
return;
}
/* INT3 is priority 11; state is in bit 2 of ISR; FCR bit 30 inhibits interrupt */
if (INT3_LINE_STATE && (FCR & 0x40000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT3));
standard_irq_callback(IRQ_INT3);
return;
}
/* INT4 is priority 13; state is in bit 3 of ISR; FCR bit 31 inhibits interrupt */
if (INT4_LINE_STATE && (FCR & 0x80000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT4));
standard_irq_callback(IRQ_INT4);
return;
}
/* IO1 is priority 14; state is in bit 4 of ISR; FCR bit 2 enables input and FCR bit 0 inhibits interrupt */
if (IO1_LINE_STATE && (FCR & 0x00000005) == 0x00000004)
{
execute_int(get_trap_addr(TRAPNO_IO1));
standard_irq_callback(IRQ_IO1);
return;
}
/* IO2 is priority 15; state is in bit 5 of ISR; FCR bit 6 enables input and FCR bit 4 inhibits interrupt */
if (IO2_LINE_STATE && (FCR & 0x00000050) == 0x00000040)
{
execute_int(get_trap_addr(TRAPNO_IO2));
standard_irq_callback(IRQ_IO2);
return;
}
}
else
{
/* IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt */
if (IO3_LINE_STATE && (FCR & 0x00000500) == 0x00000400)
{
execute_int(get_trap_addr(TRAPNO_IO3));
standard_irq_callback(IRQ_IO3);
return;
}
/* timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00300000)
{
m_core->timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* INT1 is priority 7; state is in bit 0 of ISR; FCR bit 28 inhibits interrupt */
if (INT1_LINE_STATE && (FCR & 0x10000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT1));
standard_irq_callback(IRQ_INT1);
return;
}
/* timer int might be priority 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00200000)
{
m_core->timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* INT2 is priority 9; state is in bit 1 of ISR; FCR bit 29 inhibits interrupt */
if (INT2_LINE_STATE && (FCR & 0x20000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT2));
standard_irq_callback(IRQ_INT2);
return;
}
/* timer int might be priority 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00100000)
{
m_core->timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* INT3 is priority 11; state is in bit 2 of ISR; FCR bit 30 inhibits interrupt */
if (INT3_LINE_STATE && (FCR & 0x40000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT3));
standard_irq_callback(IRQ_INT3);
return;
}
/* timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00000000)
{
m_core->timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* INT4 is priority 13; state is in bit 3 of ISR; FCR bit 31 inhibits interrupt */
if (INT4_LINE_STATE && (FCR & 0x80000000) == 0x00000000)
{
execute_int(get_trap_addr(TRAPNO_INT4));
standard_irq_callback(IRQ_INT4);
return;
}
/* IO1 is priority 14; state is in bit 4 of ISR; FCR bit 2 enables input and FCR bit 0 inhibits interrupt */
if (IO1_LINE_STATE && (FCR & 0x00000005) == 0x00000004)
{
execute_int(get_trap_addr(TRAPNO_IO1));
standard_irq_callback(IRQ_IO1);
return;
}
/* IO2 is priority 15; state is in bit 5 of ISR; FCR bit 6 enables input and FCR bit 4 inhibits interrupt */
if (IO2_LINE_STATE && (FCR & 0x00000050) == 0x00000040)
{
execute_int(get_trap_addr(TRAPNO_IO2));
standard_irq_callback(IRQ_IO2);
return;
}
}
}
void hyperstone_device::device_start()
{
// Handled entirely by init() and derived classes
}
void hyperstone_device::init(int scale_mask)
{
m_core = (internal_hyperstone_state *)m_cache.alloc_near(sizeof(internal_hyperstone_state));
memset(m_core, 0, sizeof(internal_hyperstone_state));
#if ENABLE_E132XS_DRC
m_enable_drc = allow_drc();
#else
m_enable_drc = false;
#endif
#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS
if (m_enable_drc)
m_trace_log = fopen("e1_drc.log", "wb");
else
m_trace_log = fopen("e1_interpreter.log", "wb");
#endif
memset(m_op_counts, 0, sizeof(uint32_t) * 256);
memset(m_core->global_regs, 0, sizeof(uint32_t) * 32);
memset(m_core->local_regs, 0, sizeof(uint32_t) * 64);
m_op = 0;
m_instruction_length = 0;
m_program = &space(AS_PROGRAM);
m_direct = m_program->direct<0>();
m_io = &space(AS_IO);
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hyperstone_device::timer_callback), this));
m_core->clock_scale_mask = scale_mask;
for (uint8_t i = 0; i < 16; i++)
{
m_core->fl_lut[i] = (i ? i : 16);
}
uint32_t umlflags = 0;
m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 32, 1);
// add UML symbols-
m_drcuml->symbol_add(&m_core->global_regs[0], sizeof(uint32_t), "pc");
m_drcuml->symbol_add(&m_core->global_regs[1], sizeof(uint32_t), "sr");
m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
char buf[4];
for (int i=0; i < 32; i++)
{
sprintf(buf, "g%d", i);
m_drcuml->symbol_add(&m_core->global_regs[i], sizeof(uint32_t), buf);
}
for (int i=0; i < 64; i++)
{
sprintf(buf, "l%d", i);
m_drcuml->symbol_add(&m_core->local_regs[i], sizeof(uint32_t), buf);
}
m_drcuml->symbol_add(&m_core->arg0, sizeof(uint32_t), "arg0");
m_drcuml->symbol_add(&m_core->arg1, sizeof(uint32_t), "arg1");
/* initialize the front-end helper */
m_drcfe = std::make_unique<e132xs_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
/* mark the cache dirty so it is updated on next execute */
m_cache_dirty = true;
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_core->global_regs[0]).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_core->global_regs[0]).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_core->global_regs[1]).callimport().callexport().formatstr("%40s").noshow();
state_add(E132XS_PC, "PC", m_core->global_regs[0]).mask(0xffffffff);
state_add(E132XS_SR, "SR", m_core->global_regs[1]).mask(0xffffffff);
state_add(E132XS_FER, "FER", m_core->global_regs[2]).mask(0xffffffff);
state_add(E132XS_G3, "G3", m_core->global_regs[3]).mask(0xffffffff);
state_add(E132XS_G4, "G4", m_core->global_regs[4]).mask(0xffffffff);
state_add(E132XS_G5, "G5", m_core->global_regs[5]).mask(0xffffffff);
state_add(E132XS_G6, "G6", m_core->global_regs[6]).mask(0xffffffff);
state_add(E132XS_G7, "G7", m_core->global_regs[7]).mask(0xffffffff);
state_add(E132XS_G8, "G8", m_core->global_regs[8]).mask(0xffffffff);
state_add(E132XS_G9, "G9", m_core->global_regs[9]).mask(0xffffffff);
state_add(E132XS_G10, "G10", m_core->global_regs[10]).mask(0xffffffff);
state_add(E132XS_G11, "G11", m_core->global_regs[11]).mask(0xffffffff);
state_add(E132XS_G12, "G12", m_core->global_regs[12]).mask(0xffffffff);
state_add(E132XS_G13, "G13", m_core->global_regs[13]).mask(0xffffffff);
state_add(E132XS_G14, "G14", m_core->global_regs[14]).mask(0xffffffff);
state_add(E132XS_G15, "G15", m_core->global_regs[15]).mask(0xffffffff);
state_add(E132XS_G16, "G16", m_core->global_regs[16]).mask(0xffffffff);
state_add(E132XS_G17, "G17", m_core->global_regs[17]).mask(0xffffffff);
state_add(E132XS_SP, "SP", m_core->global_regs[18]).mask(0xffffffff);
state_add(E132XS_UB, "UB", m_core->global_regs[19]).mask(0xffffffff);
state_add(E132XS_BCR, "BCR", m_core->global_regs[20]).mask(0xffffffff);
state_add(E132XS_TPR, "TPR", m_core->global_regs[21]).mask(0xffffffff);
state_add(E132XS_TCR, "TCR", m_core->global_regs[22]).mask(0xffffffff);
state_add(E132XS_TR, "TR", m_core->global_regs[23]).mask(0xffffffff);
state_add(E132XS_WCR, "WCR", m_core->global_regs[24]).mask(0xffffffff);
state_add(E132XS_ISR, "ISR", m_core->global_regs[25]).mask(0xffffffff);
state_add(E132XS_FCR, "FCR", m_core->global_regs[26]).mask(0xffffffff);
state_add(E132XS_MCR, "MCR", m_core->global_regs[27]).mask(0xffffffff);
state_add(E132XS_G28, "G28", m_core->global_regs[28]).mask(0xffffffff);
state_add(E132XS_G29, "G29", m_core->global_regs[29]).mask(0xffffffff);
state_add(E132XS_G30, "G30", m_core->global_regs[30]).mask(0xffffffff);
state_add(E132XS_G31, "G31", m_core->global_regs[31]).mask(0xffffffff);
state_add(E132XS_CL0, "CL0", m_core->local_regs[(0 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL1, "CL1", m_core->local_regs[(1 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL2, "CL2", m_core->local_regs[(2 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL3, "CL3", m_core->local_regs[(3 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL4, "CL4", m_core->local_regs[(4 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL5, "CL5", m_core->local_regs[(5 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL6, "CL6", m_core->local_regs[(6 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL7, "CL7", m_core->local_regs[(7 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL8, "CL8", m_core->local_regs[(8 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL9, "CL9", m_core->local_regs[(9 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL10, "CL10", m_core->local_regs[(10 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL11, "CL11", m_core->local_regs[(11 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL12, "CL12", m_core->local_regs[(12 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL13, "CL13", m_core->local_regs[(13 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL14, "CL14", m_core->local_regs[(14 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_CL15, "CL15", m_core->local_regs[(15 + GET_FP) % 64]).mask(0xffffffff);
state_add(E132XS_L0, "L0", m_core->local_regs[0]).mask(0xffffffff);
state_add(E132XS_L1, "L1", m_core->local_regs[1]).mask(0xffffffff);
state_add(E132XS_L2, "L2", m_core->local_regs[2]).mask(0xffffffff);
state_add(E132XS_L3, "L3", m_core->local_regs[3]).mask(0xffffffff);
state_add(E132XS_L4, "L4", m_core->local_regs[4]).mask(0xffffffff);
state_add(E132XS_L5, "L5", m_core->local_regs[5]).mask(0xffffffff);
state_add(E132XS_L6, "L6", m_core->local_regs[6]).mask(0xffffffff);
state_add(E132XS_L7, "L7", m_core->local_regs[7]).mask(0xffffffff);
state_add(E132XS_L8, "L8", m_core->local_regs[8]).mask(0xffffffff);
state_add(E132XS_L9, "L9", m_core->local_regs[9]).mask(0xffffffff);
state_add(E132XS_L10, "L10", m_core->local_regs[10]).mask(0xffffffff);
state_add(E132XS_L11, "L11", m_core->local_regs[11]).mask(0xffffffff);
state_add(E132XS_L12, "L12", m_core->local_regs[12]).mask(0xffffffff);
state_add(E132XS_L13, "L13", m_core->local_regs[13]).mask(0xffffffff);
state_add(E132XS_L14, "L14", m_core->local_regs[14]).mask(0xffffffff);
state_add(E132XS_L15, "L15", m_core->local_regs[15]).mask(0xffffffff);
state_add(E132XS_L16, "L16", m_core->local_regs[16]).mask(0xffffffff);
state_add(E132XS_L17, "L17", m_core->local_regs[17]).mask(0xffffffff);
state_add(E132XS_L18, "L18", m_core->local_regs[18]).mask(0xffffffff);
state_add(E132XS_L19, "L19", m_core->local_regs[19]).mask(0xffffffff);
state_add(E132XS_L20, "L20", m_core->local_regs[20]).mask(0xffffffff);
state_add(E132XS_L21, "L21", m_core->local_regs[21]).mask(0xffffffff);
state_add(E132XS_L22, "L22", m_core->local_regs[22]).mask(0xffffffff);
state_add(E132XS_L23, "L23", m_core->local_regs[23]).mask(0xffffffff);
state_add(E132XS_L24, "L24", m_core->local_regs[24]).mask(0xffffffff);
state_add(E132XS_L25, "L25", m_core->local_regs[25]).mask(0xffffffff);
state_add(E132XS_L26, "L26", m_core->local_regs[26]).mask(0xffffffff);
state_add(E132XS_L27, "L27", m_core->local_regs[27]).mask(0xffffffff);
state_add(E132XS_L28, "L28", m_core->local_regs[28]).mask(0xffffffff);
state_add(E132XS_L29, "L29", m_core->local_regs[29]).mask(0xffffffff);
state_add(E132XS_L30, "L30", m_core->local_regs[30]).mask(0xffffffff);
state_add(E132XS_L31, "L31", m_core->local_regs[31]).mask(0xffffffff);
state_add(E132XS_L32, "L32", m_core->local_regs[32]).mask(0xffffffff);
state_add(E132XS_L33, "L33", m_core->local_regs[33]).mask(0xffffffff);
state_add(E132XS_L34, "L34", m_core->local_regs[34]).mask(0xffffffff);
state_add(E132XS_L35, "L35", m_core->local_regs[35]).mask(0xffffffff);
state_add(E132XS_L36, "L36", m_core->local_regs[36]).mask(0xffffffff);
state_add(E132XS_L37, "L37", m_core->local_regs[37]).mask(0xffffffff);
state_add(E132XS_L38, "L38", m_core->local_regs[38]).mask(0xffffffff);
state_add(E132XS_L39, "L39", m_core->local_regs[39]).mask(0xffffffff);
state_add(E132XS_L40, "L40", m_core->local_regs[40]).mask(0xffffffff);
state_add(E132XS_L41, "L41", m_core->local_regs[41]).mask(0xffffffff);
state_add(E132XS_L42, "L42", m_core->local_regs[42]).mask(0xffffffff);
state_add(E132XS_L43, "L43", m_core->local_regs[43]).mask(0xffffffff);
state_add(E132XS_L44, "L44", m_core->local_regs[44]).mask(0xffffffff);
state_add(E132XS_L45, "L45", m_core->local_regs[45]).mask(0xffffffff);
state_add(E132XS_L46, "L46", m_core->local_regs[46]).mask(0xffffffff);
state_add(E132XS_L47, "L47", m_core->local_regs[47]).mask(0xffffffff);
state_add(E132XS_L48, "L48", m_core->local_regs[48]).mask(0xffffffff);
state_add(E132XS_L49, "L49", m_core->local_regs[49]).mask(0xffffffff);
state_add(E132XS_L50, "L50", m_core->local_regs[50]).mask(0xffffffff);
state_add(E132XS_L51, "L51", m_core->local_regs[51]).mask(0xffffffff);
state_add(E132XS_L52, "L52", m_core->local_regs[52]).mask(0xffffffff);
state_add(E132XS_L53, "L53", m_core->local_regs[53]).mask(0xffffffff);
state_add(E132XS_L54, "L54", m_core->local_regs[54]).mask(0xffffffff);
state_add(E132XS_L55, "L55", m_core->local_regs[55]).mask(0xffffffff);
state_add(E132XS_L56, "L56", m_core->local_regs[56]).mask(0xffffffff);
state_add(E132XS_L57, "L57", m_core->local_regs[57]).mask(0xffffffff);
state_add(E132XS_L58, "L58", m_core->local_regs[58]).mask(0xffffffff);
state_add(E132XS_L59, "L59", m_core->local_regs[59]).mask(0xffffffff);
state_add(E132XS_L60, "L60", m_core->local_regs[60]).mask(0xffffffff);
state_add(E132XS_L61, "L61", m_core->local_regs[61]).mask(0xffffffff);
state_add(E132XS_L62, "L62", m_core->local_regs[62]).mask(0xffffffff);
state_add(E132XS_L63, "L63", m_core->local_regs[63]).mask(0xffffffff);
save_item(NAME(m_core->global_regs));
save_item(NAME(m_core->local_regs));
save_item(NAME(m_core->trap_entry));
save_item(NAME(m_core->delay_pc));
save_item(NAME(m_instruction_length));
save_item(NAME(m_core->intblock));
save_item(NAME(m_core->delay_slot));
save_item(NAME(m_core->delay_slot_taken));
save_item(NAME(m_core->tr_clocks_per_tick));
save_item(NAME(m_core->tr_base_value));
save_item(NAME(m_core->tr_base_cycles));
save_item(NAME(m_core->timer_int_pending));
save_item(NAME(m_core->clck_scale));
save_item(NAME(m_core->clock_scale_mask));
save_item(NAME(m_core->clock_cycles_1));
save_item(NAME(m_core->clock_cycles_2));
save_item(NAME(m_core->clock_cycles_3));
save_item(NAME(m_core->clock_cycles_4));
save_item(NAME(m_core->clock_cycles_6));
save_item(NAME(m_core->clock_cycles_36));
// set our instruction counter
m_icountptr = &m_core->icount;
}
void e116t_device::device_start()
{
init(0);
m_core->opcodexor = 0;
}
void e116xt_device::device_start()
{
init(3);
m_core->opcodexor = 0;
}
void e116xs_device::device_start()
{
init(7);
m_core->opcodexor = 0;
}
void e116xsr_device::device_start()
{
init(7);
m_core->opcodexor = 0;
}
void gms30c2116_device::device_start()
{
init(0);
m_core->opcodexor = 0;
}
void gms30c2216_device::device_start()
{
init(0);
m_core->opcodexor = 0;
}
void e132n_device::device_start()
{
init(0);
m_core->opcodexor = WORD_XOR_BE(0);
}
void e132t_device::device_start()
{
init(0);
m_core->opcodexor = WORD_XOR_BE(0);
}
void e132xn_device::device_start()
{
init(3);
m_core->opcodexor = WORD_XOR_BE(0);
}
void e132xt_device::device_start()
{
init(3);
m_core->opcodexor = WORD_XOR_BE(0);
}
void e132xs_device::device_start()
{
init(7);
m_core->opcodexor = WORD_XOR_BE(0);
}
void e132xsr_device::device_start()
{
init(7);
m_core->opcodexor = WORD_XOR_BE(0);
}
void gms30c2132_device::device_start()
{
init(0);
m_core->opcodexor = WORD_XOR_BE(0);
}
void gms30c2232_device::device_start()
{
init(0);
m_core->opcodexor = WORD_XOR_BE(0);
}
void hyperstone_device::device_reset()
{
//TODO: Add different reset initializations for BCR, MCR, FCR, TPR
m_program = &space(AS_PROGRAM);
m_direct = m_program->direct<0>();
m_io = &space(AS_IO);
m_core->tr_clocks_per_tick = 2;
m_core->trap_entry = s_trap_entries[E132XS_ENTRY_MEM3]; // default entry point @ MEM3
set_global_register(BCR_REGISTER, ~0);
set_global_register(MCR_REGISTER, ~0);
set_global_register(FCR_REGISTER, ~0);
set_global_register(TPR_REGISTER, 0xc000000);
PC = get_trap_addr(TRAPNO_RESET);
SET_FP(0);
SET_FL(2);
SET_M(0);
SET_T(0);
SET_L(1);
SET_S(1);
SET_ILC(1<<19);
set_local_register(0, (PC & 0xfffffffe) | GET_S);
set_local_register(1, SR);
m_core->icount -= m_core->clock_cycles_2;
}
void hyperstone_device::device_stop()
{
if (m_drcfe != nullptr)
{
m_drcfe = nullptr;
}
if (m_drcuml != nullptr)
{
m_drcuml = nullptr;
}
#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS
fclose(m_trace_log);
#endif
#if E132XS_COUNT_INSTRUCTIONS
uint32_t indices[256];
for (uint32_t i = 0; i < 256; i++)
indices[i] = i;
for (uint32_t i = 0; i < 256; i++)
{
for (uint32_t j = 0; j < 256; j++)
{
if (m_op_counts[j] < m_op_counts[i])
{
uint32_t temp = m_op_counts[i];
m_op_counts[i] = m_op_counts[j];
m_op_counts[j] = temp;
temp = indices[i];
indices[i] = indices[j];
indices[j] = temp;
}
}
}
for (uint32_t i = 0; i < 256; i++)
{
if (m_op_counts[i] != 0)
{
printf("%02x: %d\n", (uint8_t)indices[i], m_op_counts[i]);
}
}
#endif
}
//-------------------------------------------------
// memory_space_config - return the configuration
// of the address spaces
//-------------------------------------------------
device_memory_interface::space_config_vector hyperstone_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_IO, &m_io_config)
};
}
//-------------------------------------------------
// state_string_export - export state as a string
// for the debugger
//-------------------------------------------------
void hyperstone_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case STATE_GENFLAGS:
str = string_format("%c%c%c%c%c%c%c%c%c%c%c%c FTE:%X FRM:%X ILC:%d FL:%d FP:%d",
GET_S ? 'S':'.',
GET_P ? 'P':'.',
GET_T ? 'T':'.',
GET_L ? 'L':'.',
GET_I ? 'I':'.',
m_core->global_regs[1] & 0x00040 ? '?':'.',
GET_H ? 'H':'.',
GET_M ? 'M':'.',
GET_V ? 'V':'.',
GET_N ? 'N':'.',
GET_Z ? 'Z':'.',
GET_C ? 'C':'.',
GET_FTE,
GET_FRM,
GET_ILC,
GET_FL,
GET_FP);
break;
}
}
//-------------------------------------------------
// disassemble - call the disassembly
// helper function
//-------------------------------------------------
util::disasm_interface *hyperstone_device::create_disassembler()
{
return new hyperstone_disassembler(this);
}
u8 hyperstone_device::get_fp() const
{
return GET_FP;
}
bool hyperstone_device::get_h() const
{
return GET_H;
}
/* Opcodes */
void hyperstone_device::hyperstone_trap()
{
m_core->icount -= m_core->clock_cycles_1;
static const uint32_t conditions[16] = {
0, 0, 0, 0, N_MASK | Z_MASK, N_MASK | Z_MASK, N_MASK, N_MASK, C_MASK | Z_MASK, C_MASK | Z_MASK, C_MASK, C_MASK, Z_MASK, Z_MASK, V_MASK, 0
};
static const bool trap_if_set[16] = {
false, false, false, false, true, false, true, false, true, false, true, false, true, false, true, false
};
check_delay_PC();
const uint8_t trapno = (m_op & 0xfc) >> 2;
const uint32_t addr = get_trap_addr(trapno);
const uint8_t code = ((m_op & 0x300) >> 6) | (m_op & 0x03);
if (trap_if_set[code])
{
if (SR & conditions[code])
execute_trap(addr);
}
else
{
if (!(SR & conditions[code]))
execute_trap(addr);
}
}
#include "e132xsop.hxx"
//**************************************************************************
// CORE EXECUTION LOOP
//**************************************************************************
//-------------------------------------------------
// execute_min_cycles - return minimum number of
// cycles it takes for one instruction to execute
//-------------------------------------------------
uint32_t hyperstone_device::execute_min_cycles() const
{
return 1;
}
//-------------------------------------------------
// execute_max_cycles - return maximum number of
// cycles it takes for one instruction to execute
//-------------------------------------------------
uint32_t hyperstone_device::execute_max_cycles() const
{
return 36;
}
//-------------------------------------------------
// execute_input_lines - return the number of
// input/interrupt lines
//-------------------------------------------------
uint32_t hyperstone_device::execute_input_lines() const
{
return 8;
}
void hyperstone_device::execute_set_input(int inputnum, int state)
{
if (state)
ISR |= 1 << inputnum;
else
ISR &= ~(1 << inputnum);
}
void hyperstone_device::hyperstone_reserved()
{
LOG("Executed Reserved opcode. PC = %08X OP = %04X\n", PC, OP);
}
void hyperstone_device::hyperstone_do()
{
fatalerror("Executed hyperstone_do instruction. PC = %08X\n", PC-4);
}
//-------------------------------------------------
// execute_run - execute a timeslice's worth of
// opcodes
//-------------------------------------------------
void hyperstone_device::execute_run()
{
if (m_enable_drc)
{
execute_run_drc();
return;
}
if (m_core->intblock < 0)
m_core->intblock = 0;
if (m_core->timer_int_pending)
check_interrupts<IS_TIMER>();
else
check_interrupts<NO_TIMER>();
while (m_core->icount > 0)
{
#if E132XS_LOG_INTERPRETER_REGS
dump_registers();
#endif
debugger_instruction_hook(this, PC);
OP = READ_OP(PC);
PC += 2;
m_instruction_length = (1<<19);
#if E132XS_COUNT_INSTRUCTIONS
m_op_counts[m_op >> 8]++;
#endif
switch (m_op >> 8)
{
case 0x00: hyperstone_chk<GLOBAL, GLOBAL>(); break;
case 0x01: hyperstone_chk<GLOBAL, LOCAL>(); break;
case 0x02: hyperstone_chk<LOCAL, GLOBAL>(); break;
case 0x03: hyperstone_chk<LOCAL, LOCAL>(); break;
case 0x04: hyperstone_movd<GLOBAL, GLOBAL>(); break;
case 0x05: hyperstone_movd<GLOBAL, LOCAL>(); break;
case 0x06: hyperstone_movd<LOCAL, GLOBAL>(); break;
case 0x07: hyperstone_movd<LOCAL, LOCAL>(); break;
case 0x08: hyperstone_divsu<GLOBAL, GLOBAL, IS_UNSIGNED>(); break;
case 0x09: hyperstone_divsu<GLOBAL, LOCAL, IS_UNSIGNED>(); break;
case 0x0a: hyperstone_divsu<LOCAL, GLOBAL, IS_UNSIGNED>(); break;
case 0x0b: hyperstone_divsu<LOCAL, LOCAL, IS_UNSIGNED>(); break;
case 0x0c: hyperstone_divsu<GLOBAL, GLOBAL, IS_SIGNED>(); break;
case 0x0d: hyperstone_divsu<GLOBAL, LOCAL, IS_SIGNED>(); break;
case 0x0e: hyperstone_divsu<LOCAL, GLOBAL, IS_SIGNED>(); break;
case 0x0f: hyperstone_divsu<LOCAL, LOCAL, IS_SIGNED>(); break;
case 0x10: hyperstone_xm<GLOBAL, GLOBAL>(); break;
case 0x11: hyperstone_xm<GLOBAL, LOCAL>(); break;
case 0x12: hyperstone_xm<LOCAL, GLOBAL>(); break;
case 0x13: hyperstone_xm<LOCAL, LOCAL>(); break;
case 0x14: hyperstone_mask<GLOBAL, GLOBAL>(); break;
case 0x15: hyperstone_mask<GLOBAL, LOCAL>(); break;
case 0x16: hyperstone_mask<LOCAL, GLOBAL>(); break;
case 0x17: hyperstone_mask<LOCAL, LOCAL>(); break;
case 0x18: hyperstone_sum<GLOBAL, GLOBAL>(); break;
case 0x19: hyperstone_sum<GLOBAL, LOCAL>(); break;
case 0x1a: hyperstone_sum<LOCAL, GLOBAL>(); break;
case 0x1b: hyperstone_sum<LOCAL, LOCAL>(); break;
case 0x1c: hyperstone_sums<GLOBAL, GLOBAL>(); break;
case 0x1d: hyperstone_sums<GLOBAL, LOCAL>(); break;
case 0x1e: hyperstone_sums<LOCAL, GLOBAL>(); break;
case 0x1f: hyperstone_sums<LOCAL, LOCAL>(); break;
case 0x20: hyperstone_cmp<GLOBAL, GLOBAL>(); break;
case 0x21: hyperstone_cmp<GLOBAL, LOCAL>(); break;
case 0x22: hyperstone_cmp<LOCAL, GLOBAL>(); break;
case 0x23: hyperstone_cmp<LOCAL, LOCAL>(); break;
case 0x24: hyperstone_mov<GLOBAL, GLOBAL>(); break;
case 0x25: hyperstone_mov<GLOBAL, LOCAL>(); break;
case 0x26: hyperstone_mov<LOCAL, GLOBAL>(); break;
case 0x27: hyperstone_mov<LOCAL, LOCAL>(); break;
case 0x28: hyperstone_add<GLOBAL, GLOBAL>(); break;
case 0x29: hyperstone_add<GLOBAL, LOCAL>(); break;
case 0x2a: hyperstone_add<LOCAL, GLOBAL>(); break;
case 0x2b: hyperstone_add<LOCAL, LOCAL>(); break;
case 0x2c: hyperstone_adds<GLOBAL, GLOBAL>(); break;
case 0x2d: hyperstone_adds<GLOBAL, LOCAL>(); break;
case 0x2e: hyperstone_adds<LOCAL, GLOBAL>(); break;
case 0x2f: hyperstone_adds<LOCAL, LOCAL>(); break;
case 0x30: hyperstone_cmpb<GLOBAL, GLOBAL>(); break;
case 0x31: hyperstone_cmpb<GLOBAL, LOCAL>(); break;
case 0x32: hyperstone_cmpb<LOCAL, GLOBAL>(); break;
case 0x33: hyperstone_cmpb<LOCAL, LOCAL>(); break;
case 0x34: hyperstone_andn<GLOBAL, GLOBAL>(); break;
case 0x35: hyperstone_andn<GLOBAL, LOCAL>(); break;
case 0x36: hyperstone_andn<LOCAL, GLOBAL>(); break;
case 0x37: hyperstone_andn<LOCAL, LOCAL>(); break;
case 0x38: hyperstone_or<GLOBAL, GLOBAL>(); break;
case 0x39: hyperstone_or<GLOBAL, LOCAL>(); break;
case 0x3a: hyperstone_or<LOCAL, GLOBAL>(); break;
case 0x3b: hyperstone_or<LOCAL, LOCAL>(); break;
case 0x3c: hyperstone_xor<GLOBAL, GLOBAL>(); break;
case 0x3d: hyperstone_xor<GLOBAL, LOCAL>(); break;
case 0x3e: hyperstone_xor<LOCAL, GLOBAL>(); break;
case 0x3f: hyperstone_xor<LOCAL, LOCAL>(); break;
case 0x40: hyperstone_subc<GLOBAL, GLOBAL>(); break;
case 0x41: hyperstone_subc<GLOBAL, LOCAL>(); break;
case 0x42: hyperstone_subc<LOCAL, GLOBAL>(); break;
case 0x43: hyperstone_subc<LOCAL, LOCAL>(); break;
case 0x44: hyperstone_not<GLOBAL, GLOBAL>(); break;
case 0x45: hyperstone_not<GLOBAL, LOCAL>(); break;
case 0x46: hyperstone_not<LOCAL, GLOBAL>(); break;
case 0x47: hyperstone_not<LOCAL, LOCAL>(); break;
case 0x48: hyperstone_sub<GLOBAL, GLOBAL>(); break;
case 0x49: hyperstone_sub<GLOBAL, LOCAL>(); break;
case 0x4a: hyperstone_sub<LOCAL, GLOBAL>(); break;
case 0x4b: hyperstone_sub<LOCAL, LOCAL>(); break;
case 0x4c: hyperstone_subs<GLOBAL, GLOBAL>(); break;
case 0x4d: hyperstone_subs<GLOBAL, LOCAL>(); break;
case 0x4e: hyperstone_subs<LOCAL, GLOBAL>(); break;
case 0x4f: hyperstone_subs<LOCAL, LOCAL>(); break;
case 0x50: hyperstone_addc<GLOBAL, GLOBAL>(); break;
case 0x51: hyperstone_addc<GLOBAL, LOCAL>(); break;
case 0x52: hyperstone_addc<LOCAL, GLOBAL>(); break;
case 0x53: hyperstone_addc<LOCAL, LOCAL>(); break;
case 0x54: hyperstone_and<GLOBAL, GLOBAL>(); break;
case 0x55: hyperstone_and<GLOBAL, LOCAL>(); break;
case 0x56: hyperstone_and<LOCAL, GLOBAL>(); break;
case 0x57: hyperstone_and<LOCAL, LOCAL>(); break;
case 0x58: hyperstone_neg<GLOBAL, GLOBAL>(); break;
case 0x59: hyperstone_neg<GLOBAL, LOCAL>(); break;
case 0x5a: hyperstone_neg<LOCAL, GLOBAL>(); break;
case 0x5b: hyperstone_neg<LOCAL, LOCAL>(); break;
case 0x5c: hyperstone_negs<GLOBAL, GLOBAL>(); break;
case 0x5d: hyperstone_negs<GLOBAL, LOCAL>(); break;
case 0x5e: hyperstone_negs<LOCAL, GLOBAL>(); break;
case 0x5f: hyperstone_negs<LOCAL, LOCAL>(); break;
case 0x60: hyperstone_cmpi<GLOBAL, SIMM>(); break;
case 0x61: hyperstone_cmpi<GLOBAL, LIMM>(); break;
case 0x62: hyperstone_cmpi<LOCAL, SIMM>(); break;
case 0x63: hyperstone_cmpi<LOCAL, LIMM>(); break;
case 0x64: hyperstone_movi<GLOBAL, SIMM>(); break;
case 0x65: hyperstone_movi<GLOBAL, LIMM>(); break;
case 0x66: hyperstone_movi<LOCAL, SIMM>(); break;
case 0x67: hyperstone_movi<LOCAL, LIMM>(); break;
case 0x68: hyperstone_addi<GLOBAL, SIMM>(); break;
case 0x69: hyperstone_addi<GLOBAL, LIMM>(); break;
case 0x6a: hyperstone_addi<LOCAL, SIMM>(); break;
case 0x6b: hyperstone_addi<LOCAL, LIMM>(); break;
case 0x6c: hyperstone_addsi<GLOBAL, SIMM>(); break;
case 0x6d: hyperstone_addsi<GLOBAL, LIMM>(); break;
case 0x6e: hyperstone_addsi<LOCAL, SIMM>(); break;
case 0x6f: hyperstone_addsi<LOCAL, LIMM>(); break;
case 0x70: hyperstone_cmpbi<GLOBAL, SIMM>(); break;
case 0x71: hyperstone_cmpbi<GLOBAL, LIMM>(); break;
case 0x72: hyperstone_cmpbi<LOCAL, SIMM>(); break;
case 0x73: hyperstone_cmpbi<LOCAL, LIMM>(); break;
case 0x74: hyperstone_andni<GLOBAL, SIMM>(); break;
case 0x75: hyperstone_andni<GLOBAL, LIMM>(); break;
case 0x76: hyperstone_andni<LOCAL, SIMM>(); break;
case 0x77: hyperstone_andni<LOCAL, LIMM>(); break;
case 0x78: hyperstone_ori<GLOBAL, SIMM>(); break;
case 0x79: hyperstone_ori<GLOBAL, LIMM>(); break;
case 0x7a: hyperstone_ori<LOCAL, SIMM>(); break;
case 0x7b: hyperstone_ori<LOCAL, LIMM>(); break;
case 0x7c: hyperstone_xori<GLOBAL, SIMM>(); break;
case 0x7d: hyperstone_xori<GLOBAL, LIMM>(); break;
case 0x7e: hyperstone_xori<LOCAL, SIMM>(); break;
case 0x7f: hyperstone_xori<LOCAL, LIMM>(); break;
case 0x80: hyperstone_shrdi<N_LO>(); break;
case 0x81: hyperstone_shrdi<N_HI>(); break;
case 0x82: hyperstone_shrd(); break;
case 0x83: hyperstone_shr(); break;
case 0x84: hyperstone_sardi<N_LO>(); break;
case 0x85: hyperstone_sardi<N_HI>(); break;
case 0x86: hyperstone_sard(); break;
case 0x87: hyperstone_sar(); break;
case 0x88: hyperstone_shldi<N_LO>(); break;
case 0x89: hyperstone_shldi<N_HI>(); break;
case 0x8a: hyperstone_shld(); break;
case 0x8b: hyperstone_shl(); break;
case 0x8c: hyperstone_reserved(); break;
case 0x8d: hyperstone_reserved(); break;
case 0x8e: hyperstone_testlz(); break;
case 0x8f: hyperstone_rol(); break;
case 0x90: hyperstone_ldxx1<GLOBAL, GLOBAL>(); break;
case 0x91: hyperstone_ldxx1<GLOBAL, LOCAL>(); break;
case 0x92: hyperstone_ldxx1<LOCAL, GLOBAL>(); break;
case 0x93: hyperstone_ldxx1<LOCAL, LOCAL>(); break;
case 0x94: hyperstone_ldxx2<GLOBAL, GLOBAL>(); break;
case 0x95: hyperstone_ldxx2<GLOBAL, LOCAL>(); break;
case 0x96: hyperstone_ldxx2<LOCAL, GLOBAL>(); break;
case 0x97: hyperstone_ldxx2<LOCAL, LOCAL>(); break;
case 0x98: hyperstone_stxx1<GLOBAL, GLOBAL>(); break;
case 0x99: hyperstone_stxx1<GLOBAL, LOCAL>(); break;
case 0x9a: hyperstone_stxx1<LOCAL, GLOBAL>(); break;
case 0x9b: hyperstone_stxx1<LOCAL, LOCAL>(); break;
case 0x9c: hyperstone_stxx2<GLOBAL, GLOBAL>(); break;
case 0x9d: hyperstone_stxx2<GLOBAL, LOCAL>(); break;
case 0x9e: hyperstone_stxx2<LOCAL, GLOBAL>(); break;
case 0x9f: hyperstone_stxx2<LOCAL, LOCAL>(); break;
case 0xa0: hyperstone_shri<N_LO, GLOBAL>(); break;
case 0xa1: hyperstone_shri<N_HI, GLOBAL>(); break;
case 0xa2: hyperstone_shri<N_LO, LOCAL>(); break;
case 0xa3: hyperstone_shri<N_HI, LOCAL>(); break;
case 0xa4: hyperstone_sari<N_LO, GLOBAL>(); break;
case 0xa5: hyperstone_sari<N_HI, GLOBAL>(); break;
case 0xa6: hyperstone_sari<N_LO, LOCAL>(); break;
case 0xa7: hyperstone_sari<N_HI, LOCAL>(); break;
case 0xa8: hyperstone_shli<N_LO, GLOBAL>(); break;
case 0xa9: hyperstone_shli<N_HI, GLOBAL>(); break;
case 0xaa: hyperstone_shli<N_LO, LOCAL>(); break;
case 0xab: hyperstone_shli<N_HI, LOCAL>(); break;
case 0xac: hyperstone_reserved(); break;
case 0xad: hyperstone_reserved(); break;
case 0xae: hyperstone_reserved(); break;
case 0xaf: hyperstone_reserved(); break;
case 0xb0: hyperstone_mulsu<GLOBAL, GLOBAL, IS_UNSIGNED>(); break;
case 0xb1: hyperstone_mulsu<GLOBAL, LOCAL, IS_UNSIGNED>(); break;
case 0xb2: hyperstone_mulsu<LOCAL, GLOBAL, IS_UNSIGNED>(); break;
case 0xb3: hyperstone_mulsu<LOCAL, LOCAL, IS_UNSIGNED>(); break;
case 0xb4: hyperstone_mulsu<GLOBAL, GLOBAL, IS_SIGNED>(); break;
case 0xb5: hyperstone_mulsu<GLOBAL, LOCAL, IS_SIGNED>(); break;
case 0xb6: hyperstone_mulsu<LOCAL, GLOBAL, IS_SIGNED>(); break;
case 0xb7: hyperstone_mulsu<LOCAL, LOCAL, IS_SIGNED>(); break;
case 0xb8: hyperstone_set<N_LO, GLOBAL>(); break;
case 0xb9: hyperstone_set<N_HI, GLOBAL>(); break;
case 0xba: hyperstone_set<N_LO, LOCAL>(); break;
case 0xbb: hyperstone_set<N_HI, LOCAL>(); break;
case 0xbc: hyperstone_mul<GLOBAL, GLOBAL>(); break;
case 0xbd: hyperstone_mul<GLOBAL, LOCAL>(); break;
case 0xbe: hyperstone_mul<LOCAL, GLOBAL>(); break;
case 0xbf: hyperstone_mul<LOCAL, LOCAL>(); break;
case 0xc0: execute_software(); break; // fadd
case 0xc1: execute_software(); break; // faddd
case 0xc2: execute_software(); break; // fsub
case 0xc3: execute_software(); break; // fsubd
case 0xc4: execute_software(); break; // fmul
case 0xc5: execute_software(); break; // fmuld
case 0xc6: execute_software(); break; // fdiv
case 0xc7: execute_software(); break; // fdivd
case 0xc8: execute_software(); break; // fcmp
case 0xc9: execute_software(); break; // fcmpd
case 0xca: execute_software(); break; // fcmpu
case 0xcb: execute_software(); break; // fcmpud
case 0xcc: execute_software(); break; // fcvt
case 0xcd: execute_software(); break; // fcvtd
case 0xce: hyperstone_extend(); break;
case 0xcf: hyperstone_do(); break;
case 0xd0: hyperstone_ldwr<GLOBAL>(); break;
case 0xd1: hyperstone_ldwr<LOCAL>(); break;
case 0xd2: hyperstone_lddr<GLOBAL>(); break;
case 0xd3: hyperstone_lddr<LOCAL>(); break;
case 0xd4: hyperstone_ldwp<GLOBAL>(); break;
case 0xd5: hyperstone_ldwp<LOCAL>(); break;
case 0xd6: hyperstone_lddp<GLOBAL>(); break;
case 0xd7: hyperstone_lddp<LOCAL>(); break;
case 0xd8: hyperstone_stwr<GLOBAL>(); break;
case 0xd9: hyperstone_stwr<LOCAL>(); break;
case 0xda: hyperstone_stdr<GLOBAL>(); break;
case 0xdb: hyperstone_stdr<LOCAL>(); break;
case 0xdc: hyperstone_stwp<GLOBAL>(); break;
case 0xdd: hyperstone_stwp<LOCAL>(); break;
case 0xde: hyperstone_stdp<GLOBAL>(); break;
case 0xdf: hyperstone_stdp<LOCAL>(); break;
case 0xe0: hyperstone_db<COND_V, IS_SET>(); break;
case 0xe1: hyperstone_db<COND_V, IS_CLEAR>(); break;
case 0xe2: hyperstone_db<COND_Z, IS_SET>(); break;
case 0xe3: hyperstone_db<COND_Z, IS_CLEAR>(); break;
case 0xe4: hyperstone_db<COND_C, IS_SET>(); break;
case 0xe5: hyperstone_db<COND_C, IS_CLEAR>(); break;
case 0xe6: hyperstone_db<COND_CZ, IS_SET>(); break;
case 0xe7: hyperstone_db<COND_CZ, IS_CLEAR>(); break;
case 0xe8: hyperstone_db<COND_N, IS_SET>(); break;
case 0xe9: hyperstone_db<COND_N, IS_CLEAR>(); break;
case 0xea: hyperstone_db<COND_NZ, IS_SET>(); break;
case 0xeb: hyperstone_db<COND_NZ, IS_CLEAR>(); break;
case 0xec: hyperstone_dbr(); break;
case 0xed: hyperstone_frame(); break;
case 0xee: hyperstone_call<GLOBAL>(); break;
case 0xef: hyperstone_call<LOCAL>(); break;
case 0xf0: hyperstone_b<COND_V, IS_SET>(); break;
case 0xf1: hyperstone_b<COND_V, IS_CLEAR>(); break;
case 0xf2: hyperstone_b<COND_Z, IS_SET>(); break;
case 0xf3: hyperstone_b<COND_Z, IS_CLEAR>(); break;
case 0xf4: hyperstone_b<COND_C, IS_SET>(); break;
case 0xf5: hyperstone_b<COND_C, IS_CLEAR>(); break;
case 0xf6: hyperstone_b<COND_CZ, IS_SET>(); break;
case 0xf7: hyperstone_b<COND_CZ, IS_CLEAR>(); break;
case 0xf8: hyperstone_b<COND_N, IS_SET>(); break;
case 0xf9: hyperstone_b<COND_N, IS_CLEAR>(); break;
case 0xfa: hyperstone_b<COND_NZ, IS_SET>(); break;
case 0xfb: hyperstone_b<COND_NZ, IS_CLEAR>(); break;
case 0xfc: hyperstone_br(); break;
case 0xfd: hyperstone_trap(); break;
case 0xfe: hyperstone_trap(); break;
case 0xff: hyperstone_trap(); break;
}
SET_ILC(m_instruction_length);
if (GET_T && GET_P && !m_core->delay_slot) /* Not in a Delayed Branch instructions */
{
uint32_t addr = get_trap_addr(TRAPNO_TRACE_EXCEPTION);
execute_exception(addr);
}
if (--m_core->intblock <= 0)
{
m_core->intblock = 0;
if (m_core->timer_int_pending)
check_interrupts<IS_TIMER>();
else
check_interrupts<NO_TIMER>();
}
}
}
DEFINE_DEVICE_TYPE(E116T, e116t_device, "e116t", "E1-16T")
DEFINE_DEVICE_TYPE(E116XT, e116xt_device, "e116xt", "E1-16XT")
DEFINE_DEVICE_TYPE(E116XS, e116xs_device, "e116xs", "E1-16XS")
DEFINE_DEVICE_TYPE(E116XSR, e116xsr_device, "e116xsr", "E1-16XSR")
DEFINE_DEVICE_TYPE(E132N, e132n_device, "e132n", "E1-32N")
DEFINE_DEVICE_TYPE(E132T, e132t_device, "e132t", "E1-32T")
DEFINE_DEVICE_TYPE(E132XN, e132xn_device, "e132xn", "E1-32XN")
DEFINE_DEVICE_TYPE(E132XT, e132xt_device, "e132xt", "E1-32XT")
DEFINE_DEVICE_TYPE(E132XS, e132xs_device, "e132xs", "E1-32XS")
DEFINE_DEVICE_TYPE(E132XSR, e132xsr_device, "e132xsr", "E1-32XSR")
DEFINE_DEVICE_TYPE(GMS30C2116, gms30c2116_device, "gms30c2116", "GMS30C2116")
DEFINE_DEVICE_TYPE(GMS30C2132, gms30c2132_device, "gms30c2132", "GMS30C2132")
DEFINE_DEVICE_TYPE(GMS30C2216, gms30c2216_device, "gms30c2216", "GMS30C2216")
DEFINE_DEVICE_TYPE(GMS30C2232, gms30c2232_device, "gms30c2232", "GMS30C2232")