-e132xs: Hyperstone DRC. [Ryan Holtz]

This commit is contained in:
mooglyguy 2017-12-29 13:17:13 +01:00
parent 6c7e77189e
commit 54f5e90d9c
8 changed files with 8123 additions and 219 deletions

View File

@ -45,7 +45,7 @@ const char *const hyperstone_disassembler::SETxx[] =
#define SOURCEBIT(op) ((op & 0x100) >> 8)
#define DESTBIT(op) ((op & 0x200) >> 9)
#define N_VALUE(op) ((((op & 0x100) >> 8) << 4 ) | (op & 0x0f))
#define DASM_N_VALUE(op) ((((op & 0x100) >> 8) << 4 ) | (op & 0x0f))
void hyperstone_disassembler::LL_format(char *source, char *dest, uint16_t op)
{
@ -200,7 +200,7 @@ int32_t hyperstone_disassembler::Rimm_format(char *dest, uint16_t op, offs_t &pc
uint16_t imm1, imm2;
int32_t ret;
int n = N_VALUE(op);
int n = DASM_N_VALUE(op);
if( DESTBIT(op) )
{
@ -287,7 +287,7 @@ uint8_t hyperstone_disassembler::Ln_format(char *dest, uint16_t op)
{
strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
return N_VALUE(op);
return DASM_N_VALUE(op);
}
uint8_t hyperstone_disassembler::Rn_format(char *dest, uint16_t op)
@ -301,7 +301,7 @@ uint8_t hyperstone_disassembler::Rn_format(char *dest, uint16_t op)
strcpy(dest, G_REG[DESTCODE(op)]);
}
return N_VALUE(op);
return DASM_N_VALUE(op);
}
int32_t hyperstone_disassembler::PCrel_format(uint16_t op, offs_t pc, const data_buffer &opcodes)
@ -796,7 +796,7 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con
{
uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0);
if( !N_VALUE(op) )
if( !DASM_N_VALUE(op) )
{
util::stream_format(stream, "ADDI %s, CZ", dest);
}
@ -813,7 +813,7 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con
{
uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0);
if( !N_VALUE(op) )
if( !DASM_N_VALUE(op) )
{
util::stream_format(stream, "ADDSI %s, CZ", dest);
}
@ -830,13 +830,13 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con
{
uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0);
if( !N_VALUE(op) )
if( !DASM_N_VALUE(op) )
{
util::stream_format(stream, "CMPBI %s, ANYBZ", dest);
}
else
{
if( N_VALUE(op) == 31 )
if( DASM_N_VALUE(op) == 31 )
imm = 0x7fffffff; //bit 31 = 0, others = 1
util::stream_format(stream, "CMPBI %s, $%x", dest, imm);
@ -850,7 +850,7 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con
{
uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0);
if( N_VALUE(op) == 31 )
if( DASM_N_VALUE(op) == 31 )
imm = 0x7fffffff; //bit 31 = 0, others = 1
util::stream_format(stream, "ANDNI %s, $%x", dest, imm);

View File

@ -25,8 +25,29 @@
#define S_BIT_CONST(val) ((val & 0x4000) >> 14)
#define DD(val) ((val & 0x3000) >> 12)
#define S_BIT ((OP & 0x100) >> 8)
#define D_BIT ((OP & 0x200) >> 9)
#define N_VALUE (((OP & 0x100) >> 4) | (OP & 0x0f))
#define HI_N_VALUE (0x10 | (OP & 0x0f))
#define LO_N_VALUE (OP & 0x0f)
#define N_OP_MASK (m_op & 0x10f)
#define DRC_HI_N_VALUE (0x10 | (op & 0x0f))
#define DRC_LO_N_VALUE (op & 0x0f)
#define DRC_N_OP_MASK (op & 0x10f)
#define DST_CODE ((OP & 0xf0) >> 4)
#define SRC_CODE (OP & 0x0f)
#define SIGN_BIT(val) ((val & 0x80000000) >> 31)
#define SIGN_TO_N(val) ((val & 0x80000000) >> 29)
#define SIGN64_TO_N(val) ((val & 0x8000000000000000ULL) >> 61)
/* Extended DSP instructions */
#define EHMAC 0x02a
#define EHMACD 0x02e
#define EHCMULD 0x046
#define EHCMACD 0x04e
#define EHCSUMD 0x086
#define EHCFFTD 0x096
#define EMUL_N 0x100
#define EMUL 0x102
#define EMULU 0x104
#define EMULS 0x106
@ -34,12 +55,6 @@
#define EMACD 0x10e
#define EMSUB 0x11a
#define EMSUBD 0x11e
#define EHMAC 0x02a
#define EHMACD 0x02e
#define EHCMULD 0x046
#define EHCMACD 0x04e
#define EHCSUMD 0x086
#define EHCFFTD 0x096
#define EHCFFTSD 0x296
/* IRQ numbers */

View File

@ -385,6 +385,33 @@ uint32_t hyperstone_device::get_emu_code_addr(uint8_t num) /* num is OP */
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 < 389000000ULL)
{
//if (m_global_regs[0] == 0x11094)
//{
// total_11094++;
//}
return;
} else if (total_ops == 389000000ULL) {
//printf("Total non-log hits of 0x11094: %d\n", (uint32_t)total_11094);
}
uint8_t packed[4];
packed[0] = (uint8_t)m_intblock;
packed[1] = (uint8_t)(m_icount >> 16);
packed[2] = (uint8_t)(m_icount >> 8);
packed[3] = (uint8_t)(m_icount >> 0);
fwrite(packed, 1, 4, m_trace_log);
fwrite(m_global_regs, 4, 32, m_trace_log);
fwrite(m_local_regs, 4, 64, m_trace_log);
}
#endif
void hyperstone_device::compute_tr()
{
uint64_t cycles_since_base = total_cycles() - m_tr_base_cycles;
@ -401,6 +428,7 @@ void hyperstone_device::update_timer_prescale()
m_clock_cycles_3 = 3 << m_clck_scale;
m_clock_cycles_4 = 4 << m_clck_scale;
m_clock_cycles_6 = 6 << m_clck_scale;
m_clock_cycles_36 = 36 << m_clck_scale;
m_tr_clocks_per_tick = ((TPR >> 16) & 0xff) + 2;
m_tr_base_value = m_tr_result;
m_tr_base_cycles = total_cycles();
@ -614,17 +642,6 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val)
}
}
#define S_BIT ((OP & 0x100) >> 8)
#define D_BIT ((OP & 0x200) >> 9)
#define N_VALUE (((OP & 0x100) >> 4) | (OP & 0x0f))
#define HI_N_VALUE (0x10 | (OP & 0x0f))
#define LO_N_VALUE (OP & 0x0f)
#define N_OP_MASK (m_op & 0x10f)
#define DST_CODE ((OP & 0xf0) >> 4)
#define SRC_CODE (OP & 0x0f)
#define SIGN_BIT(val) ((val & 0x80000000) >> 31)
#define SIGN_TO_N(val) ((val & 0x80000000) >> 29)
/*static*/ const int32_t hyperstone_device::s_immediate_values[16] =
{
16, 0, 0, 0, 32, 64, 128, int32_t(0x80000000),
@ -844,18 +861,16 @@ void hyperstone_device::execute_software()
//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) + 64*4 + (((fp + DST_CODE) % 64) * 4); //converted to 32bits offset
const uint32_t oldSR = SR;
SET_FL(6);
SET_FP(reg);
const uint32_t stack_of_dst = (SP & ~0xff) + 0x100 + (((fp + DST_CODE) & 0x3f) << 2); //converted to 32bits offset
m_local_regs[(reg + 0) & 0x3f] = stack_of_dst;
m_local_regs[(reg + 1) & 0x3f] = sreg;
m_local_regs[(reg + 2) & 0x3f] = sregf;
m_local_regs[(reg + 3) & 0x3f] = (PC & ~1) | GET_S;
m_local_regs[(reg + 4) & 0x3f] = oldSR;
m_local_regs[(reg + 4) & 0x3f] = SR;
SET_FL(6);
SET_FP(reg);
SR &= ~(M_MASK | T_MASK);
SR |= L_MASK;
@ -878,14 +893,15 @@ void hyperstone_device::execute_software()
7 - TIMER (trap 55)
*/
#define INT1_LINE_STATE ((ISR >> 0) & 1)
#define INT2_LINE_STATE ((ISR >> 1) & 1)
#define INT3_LINE_STATE ((ISR >> 2) & 1)
#define INT4_LINE_STATE ((ISR >> 3) & 1)
#define IO1_LINE_STATE ((ISR >> 4) & 1)
#define IO2_LINE_STATE ((ISR >> 5) & 1)
#define IO3_LINE_STATE ((ISR >> 6) & 1)
#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 */
@ -893,95 +909,156 @@ void hyperstone_device::check_interrupts()
return;
/* quick exit if nothing */
if (!m_timer_int_pending && (ISR & 0x7f) == 0)
if (TIMER == NO_TIMER && (ISR & 0x7f) == 0)
return;
/* 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)
if (TIMER == NO_TIMER)
{
execute_int(get_trap_addr(TRAPNO_IO3));
standard_irq_callback(IRQ_IO3);
return;
/* 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;
}
}
/* timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt */
if (m_timer_int_pending && (FCR & 0x00b00000) == 0x00300000)
else
{
m_timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* 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;
}
/* timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00300000)
{
m_timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* timer int might be priority 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt */
if (m_timer_int_pending && (FCR & 0x00b00000) == 0x00200000)
{
m_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;
}
/* 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 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00200000)
{
m_timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* timer int might be priority 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt */
if (m_timer_int_pending && (FCR & 0x00b00000) == 0x00100000)
{
m_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;
}
/* 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 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00100000)
{
m_timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
return;
}
/* timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt */
if (m_timer_int_pending && (FCR & 0x00b00000) == 0x00000000)
{
m_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;
}
/* 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;
}
/* timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt */
if (TIMER && (FCR & 0x00b00000) == 0x00000000)
{
m_timer_int_pending = 0;
execute_int(get_trap_addr(TRAPNO_TIMER));
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;
}
/* 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;
}
/* 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;
/* 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;
}
}
}
@ -992,6 +1069,15 @@ void hyperstone_device::device_start()
void hyperstone_device::init(int scale_mask)
{
m_enable_drc = allow_drc();
#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_global_regs, 0, sizeof(uint32_t) * 32);
memset(m_local_regs, 0, sizeof(uint32_t) * 64);
m_op = 0;
@ -1000,8 +1086,10 @@ void hyperstone_device::init(int scale_mask)
m_clck_scale = 0;
m_clock_cycles_1 = 0;
m_clock_cycles_2 = 0;
m_clock_cycles_3 = 0;
m_clock_cycles_4 = 0;
m_clock_cycles_6 = 0;
m_clock_cycles_36 = 0;
m_tr_base_cycles = 0;
m_tr_base_value = 0;
@ -1150,6 +1238,7 @@ void hyperstone_device::init(int scale_mask)
save_item(NAME(m_instruction_length));
save_item(NAME(m_intblock));
save_item(NAME(m_delay_slot));
save_item(NAME(m_delay_slot_taken));
save_item(NAME(m_tr_clocks_per_tick));
save_item(NAME(m_tr_base_value));
save_item(NAME(m_tr_base_cycles));
@ -1158,8 +1247,10 @@ void hyperstone_device::init(int scale_mask)
save_item(NAME(m_clock_scale_mask));
save_item(NAME(m_clock_cycles_1));
save_item(NAME(m_clock_cycles_2));
save_item(NAME(m_clock_cycles_3));
save_item(NAME(m_clock_cycles_4));
save_item(NAME(m_clock_cycles_6));
save_item(NAME(m_clock_cycles_36));
// set our instruction counter
m_icountptr = &m_icount;
@ -1275,6 +1366,7 @@ void hyperstone_device::device_reset()
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);
@ -1284,6 +1376,17 @@ void hyperstone_device::device_reset()
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
}
@ -1358,6 +1461,8 @@ bool hyperstone_device::get_h() const
void hyperstone_device::hyperstone_trap()
{
m_icount -= m_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
};
@ -1381,8 +1486,6 @@ void hyperstone_device::hyperstone_trap()
if (!(SR & conditions[code]))
execute_trap(addr);
}
m_icount -= m_clock_cycles_1;
}
@ -1453,11 +1556,16 @@ void hyperstone_device::execute_run()
if (m_intblock < 0)
m_intblock = 0;
check_interrupts();
if (m_timer_int_pending)
check_interrupts<IS_TIMER>();
else
check_interrupts<NO_TIMER>();
do
while (m_icount > 0)
{
uint32_t oldh = SR & 0x00000020;
#if E132XS_LOG_INTERPRETER_REGS
dump_registers();
#endif
debugger_instruction_hook(this, PC);
@ -1726,9 +1834,6 @@ void hyperstone_device::execute_run()
case 0xff: hyperstone_trap(); break;
}
/* clear the H state if it was previously set */
SR ^= oldh;
SET_ILC(m_instruction_length);
if (GET_T && GET_P && !m_delay_slot) /* Not in a Delayed Branch instructions */
@ -1737,10 +1842,15 @@ void hyperstone_device::execute_run()
execute_exception(addr);
}
if (--m_intblock == 0)
check_interrupts();
} while( m_icount > 0 );
if (--m_intblock <= 0)
{
m_intblock = 0;
if (m_timer_int_pending)
check_interrupts<IS_TIMER>();
else
check_interrupts<NO_TIMER>();
}
}
}
DEFINE_DEVICE_TYPE(E116T, e116t_device, "e116t", "E1-16T")

View File

@ -23,6 +23,35 @@
/***************************************************************************
CONSTANTS
***************************************************************************/
/* map variables */
#define MAPVAR_PC M0
#define MAPVAR_CYCLES M1
/* compilation boundaries -- how far back/forward does the analysis extend? */
#define COMPILE_BACKWARDS_BYTES 128
#define COMPILE_FORWARDS_BYTES 512
#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4))
#define COMPILE_MAX_SEQUENCE 64
/* exit codes */
#define EXECUTE_OUT_OF_CYCLES 0
#define EXECUTE_MISSING_CODE 1
#define EXECUTE_UNMAPPED_CODE 2
#define EXECUTE_RESET_CACHE 3
#define E132XS_STRICT_VERIFY 0x0001 /* verify all instructions */
#define SINGLE_INSTRUCTION_MODE (1)
#define ENABLE_E132XS_DRC (1)
#define E132XS_LOG_DRC_REGS (0)
#define E132XS_LOG_INTERPRETER_REGS (0)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@ -40,6 +69,11 @@ public:
inline void ccfunc_unimplemented();
inline void ccfunc_print();
inline void ccfunc_total_cycles();
inline void ccfunc_standard_irq_callback();
#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS
void dump_registers();
#endif
void update_timer_prescale();
void compute_tr();
void adjust_timer_interrupt();
@ -141,6 +175,18 @@ protected:
IS_SET = 1
};
enum trap_or_int
{
IS_TRAP = 0,
IS_INT = 1
};
enum is_timer
{
NO_TIMER = 0,
IS_TIMER = 1
};
enum
{
EXCEPTION_IO2 = 48,
@ -210,17 +256,18 @@ protected:
uint8_t m_clock_scale_mask;
uint8_t m_clck_scale;
uint8_t m_clock_cycles_1;
uint8_t m_clock_cycles_2;
uint8_t m_clock_cycles_3;
uint8_t m_clock_cycles_4;
uint8_t m_clock_cycles_6;
uint32_t m_clock_cycles_1;
uint32_t m_clock_cycles_2;
uint32_t m_clock_cycles_3;
uint32_t m_clock_cycles_4;
uint32_t m_clock_cycles_6;
uint32_t m_clock_cycles_36;
uint64_t m_tr_base_cycles;
uint32_t m_tr_base_value;
uint32_t m_tr_result;
uint32_t m_tr_clocks_per_tick;
uint8_t m_timer_int_pending;
uint32_t m_timer_int_pending;
emu_timer *m_timer;
uint64_t m_numcycles;
@ -228,6 +275,7 @@ protected:
uint32_t m_prev_pc;
uint32_t m_delay_pc;
uint32_t m_delay_slot;
uint32_t m_delay_slot_taken;
uint32_t m_opcodexor;
@ -245,7 +293,7 @@ protected:
private:
// internal functions
void check_interrupts();
template <hyperstone_device::is_timer TIMER> void check_interrupts();
void set_global_register(uint8_t code, uint32_t val);
void set_local_register(uint8_t code, uint32_t val);
@ -345,6 +393,165 @@ private:
void hyperstone_reserved();
void hyperstone_do();
#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS
FILE *m_trace_log;
#endif
drc_cache m_cache;
std::unique_ptr<drcuml_state> m_drcuml;
std::unique_ptr<e132xs_frontend> m_drcfe;
uint32_t m_drcoptions;
uint8_t m_cache_dirty;
uml::parameter m_regmap[16];
uml::code_handle *m_entry;
uml::code_handle *m_nocode;
uml::code_handle *m_interrupt_checks;
uml::code_handle *m_out_of_cycles;
uint32_t m_drc_arg0;
uint32_t m_drc_arg1;
uint32_t m_drc_arg2;
uint32_t m_drc_arg3;
uint32_t m_branch_dest;
uml::code_handle *m_mem_read8;
uml::code_handle *m_mem_write8;
uml::code_handle *m_mem_read16;
uml::code_handle *m_mem_write16;
uml::code_handle *m_mem_read32;
uml::code_handle *m_mem_write32;
uml::code_handle *m_io_read32;
uml::code_handle *m_io_write32;
uml::code_handle *m_exception[EXCEPTION_COUNT];
bool m_enable_drc;
/* internal compiler state */
struct compiler_state
{
uint32_t m_cycles; /* accumulated cycles */
uint8_t m_checkints; /* need to check interrupts before next instruction */
uml::code_label m_labelnum; /* index for local labels */
};
void execute_run_drc();
void flush_drc_cache();
void code_flush_cache();
void code_compile_block(offs_t pc);
//void load_fast_iregs(drcuml_block *block);
//void save_fast_iregs(drcuml_block *block);
void static_generate_entry_point();
void static_generate_nocode_handler();
void static_generate_out_of_cycles();
void static_generate_exception(uint32_t exception, const char *name);
void static_generate_memory_accessor(int size, int iswrite, bool isio, const char *name, uml::code_handle *&handleptr);
void static_generate_interrupt_checks();
void generate_interrupt_checks_no_timer(drcuml_block *block, uml::code_label &labelnum);
void generate_interrupt_checks_with_timer(drcuml_block *block, uml::code_label &labelnum);
void generate_branch(drcuml_block *block, uml::parameter targetpc, bool update_cycles = true);
void generate_update_cycles(drcuml_block *block, bool check_interrupts = true);
void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op);
bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_get_trap_addr(drcuml_block *block, uml::code_label &label, uint32_t trapno);
void generate_check_delay_pc(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_decode_const(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_decode_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_ignore_immediate_s(drcuml_block *block, const opcode_desc *desc);
void generate_decode_pcrel(drcuml_block *block, const opcode_desc *desc);
void generate_ignore_pcrel(drcuml_block *block, const opcode_desc *desc);
void generate_get_global_register(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_set_global_register(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <trap_or_int IS_INT> void generate_trap_or_int(drcuml_block *block);
void generate_int(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t addr);
void generate_exception(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t addr);
void generate_software(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_chk(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_movd(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL, sign_mode SIGNED> void generate_divsu(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_xm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_mask(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_sum(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_sums(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_cmp(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_mov(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_add(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_adds(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_cmpb(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_subc(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_sub(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_subs(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_addc(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_neg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_negs(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_and(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_andn(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_or(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_xor(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_not(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_cmpi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_movi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_addi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_addsi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_cmpbi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_andni(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_ori(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_xori(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N> void generate_shrdi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_shrd(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_shr(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N, reg_bank DST_GLOBAL> void generate_shri(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N> void generate_sardi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_sard(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_sar(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N, reg_bank DST_GLOBAL> void generate_sari(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N> void generate_shldi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_shld(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_shl(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N, reg_bank DST_GLOBAL> void generate_shli(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_testlz(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_rol(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_ldxx1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_ldxx2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_stxx1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_stxx2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL, sign_mode SIGNED> void generate_mulsu(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_mul(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <shift_type HI_N, reg_bank DST_GLOBAL> void generate_set(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_ldwr(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_lddr(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_ldwp(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_lddp(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_stwr(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_stdr(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_stwp(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <reg_bank SRC_GLOBAL> void generate_stdp(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <branch_condition CONDITION, condition_set COND_SET> void generate_b(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_br(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <branch_condition CONDITION, condition_set COND_SET> void generate_db(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_dbr(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_frame(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
template <hyperstone_device::reg_bank SRC_GLOBAL> void generate_call(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_trap_op(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_extend(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_reserved(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_do(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
};
// device type definition

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -55,8 +55,6 @@ void hyperstone_device::hyperstone_movd()
if (m_intblock < 1)
m_intblock = 1;
m_instruction_length = 0; // undefined
const uint32_t new_s = SR & S_MASK;
const uint32_t new_l = SR & L_MASK;
if( (!old_s && new_s) || (!new_s && !old_l && new_l))
@ -76,8 +74,8 @@ void hyperstone_device::hyperstone_movd()
m_local_regs[(SP & 0xfc) >> 2] = READ_W(SP);
}
//TODO: no 1!
m_icount -= m_clock_cycles_1;
//TODO: not 2!
m_icount -= m_clock_cycles_2;
}
else if (SRC_GLOBAL && (src_code == SR_REGISTER)) // Rd doesn't denote PC and Rs denotes SR
{
@ -160,7 +158,7 @@ void hyperstone_device::hyperstone_divsu()
(DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = (uint32_t)quotient;
}
m_icount -= 36 << m_clck_scale;
m_icount -= m_clock_cycles_36;
}
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
@ -334,9 +332,12 @@ void hyperstone_device::hyperstone_cmp()
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
void hyperstone_device::hyperstone_mov()
{
m_icount -= m_clock_cycles_1;
check_delay_PC();
const bool h = (SR & H_MASK) != 0;
const bool h = (SR & H_MASK) != 0;
SR &= ~H_MASK;
if (DST_GLOBAL && h && !(SR & S_MASK))
{
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
@ -365,8 +366,6 @@ void hyperstone_device::hyperstone_mov()
m_local_regs[(DST_CODE + fp) & 0x3f] = sreg;
}
}
m_icount -= m_clock_cycles_1;
}
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
@ -545,29 +544,19 @@ void hyperstone_device::hyperstone_subc()
const uint32_t src_code = SRC_GLOBAL ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t dst_code = DST_GLOBAL ? DST_CODE : ((DST_CODE + fp) & 0x3f);
const uint32_t sreg = SRC_GLOBAL ? ((src_code == SR_REGISTER) ? 0 : m_global_regs[src_code]) : m_local_regs[src_code];
uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
const uint32_t c = GET_C;
const uint64_t tmp = uint64_t(dreg) - (uint64_t(sreg) + uint64_t(c));
uint32_t old_z = SR & Z_MASK;
SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK);
if (SRC_GLOBAL && (src_code == SR_REGISTER))
{
const uint64_t tmp = uint64_t(dreg) - uint64_t(c);
SR |= ((tmp ^ dreg) & dreg & 0x80000000) >> 28;
SR |= (tmp & 0x100000000) >> 32;
dreg -= c;
}
else
{
const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code];
const uint64_t tmp = uint64_t(dreg) - (uint64_t(sreg) + uint64_t(c));
//CHECK!
const uint32_t sreg_c = sreg + c;
SR |= ((tmp ^ dreg) & (dreg ^ sreg_c) & 0x80000000) >> 28;
SR |= (tmp & 0x100000000) >> 32;
dreg -= sreg_c;
}
const uint32_t sreg_c = sreg + c;
SR |= ((tmp ^ dreg) & (dreg ^ sreg_c) & 0x80000000) >> 28;
SR |= (tmp & 0x100000000) >> 32;
dreg -= sreg + c;
if (old_z && dreg == 0)
SR |= Z_MASK;
@ -848,6 +837,8 @@ void hyperstone_device::hyperstone_cmpi()
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::imm_size IMM_LONG>
void hyperstone_device::hyperstone_movi()
{
m_icount -= m_clock_cycles_1;
uint32_t imm;
if (IMM_LONG)
imm = decode_immediate_s();
@ -857,6 +848,7 @@ void hyperstone_device::hyperstone_movi()
imm = m_op & 0x0f;
const bool h = (SR & H_MASK) != 0;
SR &= ~H_MASK;
if (DST_GLOBAL && h && !(SR & S_MASK))
{
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
@ -885,8 +877,6 @@ void hyperstone_device::hyperstone_movi()
m_local_regs[(DST_CODE + GET_FP) & 0x3f] = imm;
}
}
m_icount -= m_clock_cycles_1;
}
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::imm_size IMM_LONG>
@ -1234,7 +1224,7 @@ void hyperstone_device::hyperstone_shrd()
if (val == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(m_local_regs[dst_code]);
SR |= SIGN64_TO_N(val);
m_local_regs[dst_code] = (uint32_t)(val >> 32);
m_local_regs[dstf_code] = (uint32_t)val;
@ -1322,6 +1312,7 @@ void hyperstone_device::hyperstone_sard()
SR &= ~(C_MASK | Z_MASK | N_MASK);
const uint32_t n = m_local_regs[src_code] & 0x1f;
if (n)
{
SR |= (val >> (n - 1)) & 1;
@ -1338,7 +1329,7 @@ void hyperstone_device::hyperstone_sard()
if (val == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(m_local_regs[dst_code]);
SR |= SIGN64_TO_N(val);
m_local_regs[dst_code] = (uint32_t)(val >> 32);
m_local_regs[dstf_code] = (uint32_t)val;
@ -1396,24 +1387,21 @@ void hyperstone_device::hyperstone_shldi()
SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK);
const uint32_t n = HI_N ? HI_N_VALUE : LO_N_VALUE;
if ((HI_N || n) && ((val << (n - 1)) & 0x8000000000000000U))
SR |= C_MASK;
SR |= (n)?(((val<<(n-1))&0x8000000000000000ULL)?1:0):0;
const uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff;
const uint32_t tmp = high_order << n;
const uint32_t tmp = high_order << n;
uint32_t mask = (uint32_t)(0xffffffff00000000ULL >> n);
if (((high_order & mask) && (!(tmp & 0x80000000))) || (((high_order & mask) ^ mask) && (tmp & 0x80000000)))
SR |= V_MASK;
val <<= n;
high_order = extract_64hi(val);
if (val == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(high_order);
SR |= SIGN64_TO_N(val);
m_local_regs[dst_code] = high_order;
m_local_regs[dst_code] = extract_64hi(val);
m_local_regs[dstf_code] = extract_64lo(val);
m_icount -= m_clock_cycles_2;
@ -1437,18 +1425,19 @@ void hyperstone_device::hyperstone_shld()
return;
}
uint32_t n = m_local_regs[src_code & 0x3f] & 0x1f;
uint32_t high_order = m_local_regs[dst_code]; /* registers offset by frame pointer */
uint32_t high_order = m_local_regs[dst_code];
uint32_t low_order = m_local_regs[dstf_code];
uint64_t mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff;
uint64_t val = concat_64(high_order, low_order);
SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK);
SR |= (n)?(((val<<(n-1))&0x8000000000000000U)?1:0):0;
uint32_t tmp = high_order << n;
const uint32_t n = m_local_regs[src_code] & 0x1f;
SR |= (n)?(((val<<(n-1))&0x8000000000000000ULL)?1:0):0;
const uint32_t tmp = high_order << n;
const uint32_t mask = (uint32_t)(0xffffffff00000000ULL >> n);
if (((high_order & mask) && (!(tmp & 0x80000000))) || (((high_order & mask) ^ mask) && (tmp & 0x80000000)))
SR |= V_MASK;
@ -1456,7 +1445,7 @@ void hyperstone_device::hyperstone_shld()
if (val == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(m_local_regs[dst_code]);
SR |= SIGN64_TO_N(val);
m_local_regs[dst_code] = extract_64hi(val);
m_local_regs[dstf_code] = extract_64lo(val);
@ -1525,14 +1514,14 @@ void hyperstone_device::hyperstone_rol()
#ifdef MISSIONCRAFT_FLAGS
const uint32_t base = val;
const uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff;
const uint32_t mask = (uint32_t)(0xffffffff00000000ULL >> n);
#endif
if (n)
val = (val << n) | (val >> (32 - n));
#ifdef MISSIONCRAFT_FLAGS
SR &= ~(V_MASK | Z_MASK | C_MASK);
SR &= ~(V_MASK | Z_MASK | C_MASK | N_MASK);
if (((base & mask) && (!(val & 0x80000000))) || (((base & mask) ^ mask) && (val & 0x80000000)))
SR |= V_MASK;
#else
@ -1875,7 +1864,7 @@ void hyperstone_device::hyperstone_stxx1()
case 1: // STD.D
{
const uint32_t srcf_code = SRC_GLOBAL ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t sregf = ((SRC_GLOBAL && src_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code]);
const uint32_t sregf = ((SRC_GLOBAL && srcf_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code]);
extra_s &= ~1;
WRITE_W(dreg + extra_s, sreg);
WRITE_W(dreg + extra_s + 4, sregf);
@ -1888,7 +1877,7 @@ void hyperstone_device::hyperstone_stxx1()
case 3: // STD.IOD
{
const uint32_t srcf_code = SRC_GLOBAL ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t sregf = ((SRC_GLOBAL && src_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code]);
const uint32_t sregf = ((SRC_GLOBAL && srcf_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code]);
extra_s &= ~3;
IO_WRITE_W(dreg + extra_s, sreg);
IO_WRITE_W(dreg + extra_s + 4, sregf);
@ -1974,15 +1963,12 @@ void hyperstone_device::hyperstone_stxx2()
break;
case 1: // STD.N
{
const uint32_t srcf_code = SRC_GLOBAL ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t sregf = (SRC_GLOBAL && src_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code];
WRITE_W(dreg, sreg);
(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] += extra_s & ~1;
if(DST_GLOBAL == SRC_GLOBAL && (src_code + 1) == dst_code)
WRITE_W(dreg + 4, sregf + (extra_s & ~1)); // because DREG == SREGF and DREG has been incremented
else
WRITE_W(dreg + 4, sregf);
const uint32_t srcf_code = SRC_GLOBAL ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t sregf = (SRC_GLOBAL && srcf_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code];
WRITE_W(dreg + 4, sregf);
m_icount -= m_clock_cycles_1; // extra cycle
break;
@ -2041,16 +2027,18 @@ void hyperstone_device::hyperstone_sari()
check_delay_PC();
const uint32_t dst_code = DST_GLOBAL ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f);
uint32_t val = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
const uint32_t n = HI_N ? HI_N_VALUE : LO_N_VALUE;
uint32_t val = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
SR &= ~(C_MASK | Z_MASK | N_MASK);
if (HI_N || n)
{
const uint32_t sign_bit = val & 0x80000000;
SR |= (val >> (n - 1)) & 1;
uint32_t sign_bit = val & 0x80000000;
val >>= n;
if (sign_bit)
@ -2079,7 +2067,12 @@ void hyperstone_device::hyperstone_shli()
const uint32_t n = HI_N ? HI_N_VALUE : LO_N_VALUE;
SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK);
SR |= (HI_N || n) ? (((val << (n - 1)) & 0x80000000) ? 1 : 0) : 0;
if (HI_N || n)
{
SR |= (val & (0x80000000 >> (n - 1))) ? 1 : 0;
}
uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff;
uint32_t val2 = val << n;
@ -2128,12 +2121,11 @@ void hyperstone_device::hyperstone_mulsu()
(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = high_order;
(DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = (uint32_t)double_word;
m_icount -= m_clock_cycles_6;
if(SIGNED == IS_SIGNED && (sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff))
m_icount -= m_clock_cycles_4;
m_icount += m_clock_cycles_2;
else if(SIGNED == IS_UNSIGNED && sreg <= 0xffff && dreg <= 0xffff)
m_icount -= m_clock_cycles_4;
else
m_icount -= m_clock_cycles_6;
m_icount += m_clock_cycles_2;
}
template <hyperstone_device::shift_type HI_N, hyperstone_device::reg_bank DST_GLOBAL>
@ -2222,10 +2214,10 @@ void hyperstone_device::hyperstone_mul()
(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = result;
if ((sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff))
m_icount -= 3 << m_clck_scale;
else
if (sreg < 0xffff8000 || sreg > 0x7fff || dreg < 0xffff8000 || dreg > 0x7fff)
m_icount -= 5 << m_clck_scale;
else
m_icount -= 3 << m_clck_scale;
}
void hyperstone_device::hyperstone_extend()
@ -2244,7 +2236,7 @@ void hyperstone_device::hyperstone_extend()
{
// signed or unsigned multiplication, single word product
case EMUL:
case 0x100: // used in "N" type cpu
case EMUL_N: // used in "N" type cpu
m_global_regs[15] = (uint32_t)(vals * vald);
break;
@ -2256,13 +2248,13 @@ void hyperstone_device::hyperstone_extend()
m_global_regs[15] = (uint32_t)result;
break;
}
// signed multiplication, double word product
case EMULS:
{
const int64_t result = (int64_t)(int32_t)vals * (int64_t)(int32_t)vald;
m_global_regs[14] = (uint32_t)(result >> 32);
m_global_regs[15] = (uint32_t)result;
break;
}
@ -2279,6 +2271,7 @@ void hyperstone_device::hyperstone_extend()
m_global_regs[15] = (uint32_t)result;
break;
}
// signed multiply/substract, single word product difference
case EMSUB:
m_global_regs[15] = (int32_t)m_global_regs[15] - ((int32_t)vals * (int32_t)vald);
@ -2290,19 +2283,18 @@ void hyperstone_device::hyperstone_extend()
int64_t result = (int64_t)concat_64(m_global_regs[14], m_global_regs[15]) - (int64_t)((int64_t)(int32_t)vals * (int64_t)(int32_t)vald);
m_global_regs[14] = (uint32_t)(result >> 32);
m_global_regs[15] = (uint32_t)result;
break;
}
// signed half-word multiply/add, single word product sum
case EHMAC:
m_global_regs[15] = (int32_t)m_global_regs[15] + ((int32_t)((vald & 0xffff0000) >> 16) * (int32_t)((vals & 0xffff0000) >> 16)) + ((int32_t)(vald & 0xffff) * (int32_t)(vals & 0xffff));
m_global_regs[15] = (int32_t)m_global_regs[15] + ((int32_t)(vald >> 16) * (int32_t)(vals >> 16)) + ((int32_t)(vald & 0xffff) * (int32_t)(vals & 0xffff));
break;
// signed half-word multiply/add, double word product sum
case EHMACD:
{
int64_t result = (int64_t)concat_64(m_global_regs[14], m_global_regs[15]) + (int64_t)((int64_t)(int32_t)((vald & 0xffff0000) >> 16) * (int64_t)(int32_t)((vals & 0xffff0000) >> 16)) + ((int64_t)(int32_t)(vald & 0xffff) * (int64_t)(int32_t)(vals & 0xffff));
int64_t result = (int64_t)concat_64(m_global_regs[14], m_global_regs[15]) + (int64_t)((int64_t)(int32_t)(vald >> 16) * (int64_t)(int32_t)(vals >> 16)) + ((int64_t)(int32_t)(vald & 0xffff) * (int64_t)(int32_t)(vals & 0xffff));
m_global_regs[14] = (uint32_t)(result >> 32);
m_global_regs[15] = (uint32_t)result;
break;
@ -2310,14 +2302,14 @@ void hyperstone_device::hyperstone_extend()
// half-word complex multiply
case EHCMULD:
m_global_regs[14] = (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff));
m_global_regs[15] = (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16));
m_global_regs[14] = ((vald >> 16) * (vals >> 16 )) - ((vald & 0xffff) * (vals & 0xffff));
m_global_regs[15] = ((vald >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * (vals >> 16 ));
break;
// half-word complex multiply/add
case EHCMACD:
m_global_regs[14] += (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff));
m_global_regs[15] += (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16));
m_global_regs[14] += ((vald >> 16) * (vals >> 16 )) - ((vald & 0xffff) * (vals & 0xffff));
m_global_regs[15] += ((vald >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * (vals >> 16 ));
break;
// half-word (complex) add/substract
@ -2326,8 +2318,8 @@ void hyperstone_device::hyperstone_extend()
{
const uint32_t r14 = m_global_regs[14];
const uint32_t r15 = m_global_regs[15];
m_global_regs[14] = (((((vals & 0xffff0000) >> 16) + r14) << 16) & 0xffff0000) | (((vals & 0xffff) + r15) & 0xffff);
m_global_regs[15] = (((((vals & 0xffff0000) >> 16) - r14) << 16) & 0xffff0000) | (((vals & 0xffff) - r15) & 0xffff);
m_global_regs[14] = (((vals >> 16) + r14) << 16) | (((vals & 0xffff) + r15) & 0xffff);
m_global_regs[15] = (((vals >> 16) - r14) << 16) | (((vals & 0xffff) - r15) & 0xffff);
break;
}
@ -2358,7 +2350,7 @@ void hyperstone_device::hyperstone_extend()
break;
}
m_icount -= m_clock_cycles_1; //TODO: with the latency it can change
m_icount -= m_clock_cycles_1; // TODO: with the latency it can change
}
@ -2513,7 +2505,6 @@ void hyperstone_device::hyperstone_stdp()
const uint32_t src_code = SRC_GLOBAL ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t srcf_code = SRC_GLOBAL ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t sreg = (SRC_GLOBAL && src_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code];
const uint32_t sregf = (SRC_GLOBAL && src_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code];
const uint32_t dst_code = (DST_CODE + fp) & 0x3f;
const uint32_t dreg = m_local_regs[dst_code];
@ -2522,10 +2513,9 @@ void hyperstone_device::hyperstone_stdp()
m_local_regs[dst_code] += 8;
if (SRC_GLOBAL || srcf_code != dst_code)
WRITE_W(dreg + 4, sregf);
else
WRITE_W(dreg + 4, sregf + 8); // because DREG == SREGF and DREG has been incremented
const uint32_t sregf = (SRC_GLOBAL && srcf_code == SR_REGISTER) ? 0 : (SRC_GLOBAL ? m_global_regs : m_local_regs)[srcf_code];
WRITE_W(dreg + 4, sregf);
m_icount -= m_clock_cycles_2;
}
@ -2543,11 +2533,13 @@ void hyperstone_device::hyperstone_db()
m_delay_slot = 1;
m_delay_pc = PC + offset;
m_intblock = 3;
m_icount -= m_clock_cycles_2;
}
else
{
ignore_pcrel();
check_delay_PC();
m_icount -= m_clock_cycles_1;
}
}
else
@ -2556,6 +2548,7 @@ void hyperstone_device::hyperstone_db()
{
ignore_pcrel();
check_delay_PC();
m_icount -= m_clock_cycles_1;
}
else
{
@ -2564,10 +2557,9 @@ void hyperstone_device::hyperstone_db()
m_delay_slot = 1;
m_delay_pc = PC + offset;
m_intblock = 3;
m_icount -= m_clock_cycles_2;
}
}
m_icount -= m_clock_cycles_1;
}
void hyperstone_device::hyperstone_dbr()
@ -2578,6 +2570,8 @@ void hyperstone_device::hyperstone_dbr()
m_delay_slot = 1;
m_delay_pc = PC + offset;
m_intblock = 3;
m_icount -= m_clock_cycles_2;
}
void hyperstone_device::hyperstone_frame()
@ -2615,7 +2609,7 @@ void hyperstone_device::hyperstone_frame()
}
}
//TODO: no 1!
// TODO: More than 1 cycle!
m_icount -= m_clock_cycles_1;
}
@ -2633,6 +2627,7 @@ void hyperstone_device::hyperstone_call()
PC += 2;
SET_ILC(3<<19);
m_instruction_length = (3<<19);
extra_s = imm_2;
extra_s |= ((imm_1 & 0x3fff) << 16);
@ -2645,6 +2640,7 @@ void hyperstone_device::hyperstone_call()
extra_s = imm_1 & 0x3fff;
SET_ILC(2<<19);
m_instruction_length = (2<<19);
if (imm_1 & 0x4000)
extra_s |= 0xffffc000;
@ -2675,7 +2671,7 @@ void hyperstone_device::hyperstone_call()
//TODO: add interrupt locks, errors, ....
//TODO: no 1!
// TODO: More than 1 cycle!
m_icount -= m_clock_cycles_1;
}