From 4d0e408ee8a51929a8bf04ed27ce9884cad8b257 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sat, 11 Nov 2017 13:31:48 +0100 Subject: [PATCH] e132xs checkpoint, nw --- src/devices/cpu/e132xs/32xsdefs.h | 42 +- src/devices/cpu/e132xs/e132xs.cpp | 2267 ++++-------- src/devices/cpu/e132xs/e132xs.h | 143 +- src/devices/cpu/e132xs/e132xsop.hxx | 5089 ++++++++++++++++++++++----- 4 files changed, 4863 insertions(+), 2678 deletions(-) diff --git a/src/devices/cpu/e132xs/32xsdefs.h b/src/devices/cpu/e132xs/32xsdefs.h index 1e4a6e5b1cc..4fa881f15c2 100644 --- a/src/devices/cpu/e132xs/32xsdefs.h +++ b/src/devices/cpu/e132xs/32xsdefs.h @@ -9,10 +9,13 @@ #define PC_REGISTER 0 #define SR_REGISTER 1 +#define SP_REGISTER 18 +#define UB_REGISTER 19 #define BCR_REGISTER 20 #define TPR_REGISTER 21 #define TCR_REGISTER 22 #define TR_REGISTER 23 +#define WCR_REGISTER 24 #define ISR_REGISTER 25 #define FCR_REGISTER 26 #define MCR_REGISTER 27 @@ -39,10 +42,6 @@ #define EHCFFTD 0x096 #define EHCFFTSD 0x296 -/* Delay values */ -#define NO_DELAY 0 -#define DELAY_EXECUTE 1 - /* IRQ numbers */ #define IRQ_INT1 0 #define IRQ_INT2 1 @@ -147,31 +146,6 @@ #define SAME_SRCF_DST decode.same_srcf_dst -/* Memory access */ -/* read byte */ -#define READ_B(addr) m_program->read_byte((addr)) -/* read half-word */ -#define READ_HW(addr) m_program->read_word((addr) & ~1) -/* read word */ -#define READ_W(addr) m_program->read_dword((addr) & ~3) - -/* write byte */ -#define WRITE_B(addr, data) m_program->write_byte(addr, data) -/* write half-word */ -#define WRITE_HW(addr, data) m_program->write_word((addr) & ~1, data) -/* write word */ -#define WRITE_W(addr, data) m_program->write_dword((addr) & ~3, data) - - -/* I/O access */ -/* read word */ -#define IO_READ_W(addr) m_io->read_dword(((addr) >> 11) & 0x7ffc) -/* write word */ -#define IO_WRITE_W(addr, data) m_io->write_dword(((addr) >> 11) & 0x7ffc, data) - - -#define READ_OP(addr) m_direct->read_word((addr), m_opcodexor) - #define OP m_op #define PPC m_ppc //previous pc #define PC m_global_regs[0] //Program Counter @@ -220,7 +194,7 @@ #define GET_S ((SR & S_MASK)>>18) // bit 18 //SUPERVISOR STATE #define GET_ILC ((SR & 0x00180000)>>19) // bits 20 - 19 //INSTRUCTION-LENGTH /* if FL is zero it is always interpreted as 16 */ -#define GET_FL ((SR & 0x01e00000) ? ((SR & 0x01e00000)>>21) : 16) // bits 24 - 21 //FRAME LENGTH +#define GET_FL m_fl_lut[((SR >> 21) & 0xf)] // bits 24 - 21 //FRAME LENGTH #define GET_FP ((SR & 0xfe000000)>>25) // bits 31 - 25 //FRAME POINTER #define SET_C(val) (SR = (SR & ~C_MASK) | (val)) @@ -247,10 +221,10 @@ #define SET_LOW_SR(val) (SR = (SR & 0xffff0000) | ((val) & 0x0000ffff)) // when SR is addressed, only low 16 bits can be changed -#define CHECK_C(x) (SR = (SR & ~0x00000001) | (((x) & (((uint64_t)1) << 32)) ? 1 : 0 )) -#define CHECK_VADD(x,y,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & 0x80000000) ? 8: 0)) -#define CHECK_VADD3(x,y,w,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & ((w) ^ (z)) & 0x80000000) ? 8: 0)) -#define CHECK_VSUB(x,y,z) (SR = (SR & ~0x00000008) | ((((z) ^ (y)) & ((y) ^ (x)) & 0x80000000) ? 8: 0)) +#define CHECK_C(x) (SR = (SR & ~0x00000001) | (uint32_t)((x & 0x100000000L) >> 32)) +#define CHECK_VADD(x,y,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & 0x80000000) >> 29)) +#define CHECK_VADD3(x,y,w,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & ((w) ^ (z)) & 0x80000000) >> 29)) +#define CHECK_VSUB(x,y,z) (SR = (SR & ~0x00000008) | (((z ^ y) & (y ^ x) & 0x80000000) >> 29)) /* FER flags */ diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index e9db1c8500b..ff7fb8ca15e 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -148,7 +148,7 @@ - I'd almost be willing to bet money that there's no framing at all since the values in L0 - L15 as displayed by the debugger would change during a CALL or FRAME operation. I'll look when I'm in the mood. - - The mood struck me, and I took a look at SET_L_REG and GET_L_REG. + - The mood struck me, and I took a look at set_local_register and GET_L_REG. Apparently no matter what the current frame pointer is they'll always use local_regs[0] through local_regs[15]. @@ -274,9 +274,6 @@ hyperstone_device::hyperstone_device(const machine_config &mconfig, const char * m_io_config("io", ENDIANNESS_BIG, io_data_width, 15), m_icount(0) { - // build the opcode table - for (int op = 0; op < 256; op++) - m_opcode[op] = s_opcodetable[op]; } @@ -603,130 +600,109 @@ uint32_t hyperstone_device::get_global_register(uint8_t code) m_icount -= m_tr_clocks_per_tick / 2; return compute_tr(); } - return m_global_regs[code]; + return m_global_regs[code & 0x1f]; } void hyperstone_device::set_local_register(uint8_t code, uint32_t val) { - uint8_t new_code = (code + GET_FP) % 64; - - m_local_regs[new_code] = val; + m_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 - - if( code == PC_REGISTER ) + code &= 0x1f; + switch (code) { - SET_PC(val); - } - else if( code == 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_intblock < 1) - m_intblock = 1; - } - else - { - uint32_t oldval = m_global_regs[code]; - if( code != ISR_REGISTER ) + 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_intblock < 1) + m_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_global_regs[code] = val; - else - DEBUG_PRINTF(("Written to ISR register. PC = %08X\n", PC)); - - //are these set only when privilege bit is set? - if( code >= 16 ) - { - switch( code ) + return; + case SP_REGISTER: + case UB_REGISTER: + m_global_regs[code] = val & ~3; + return; + case BCR_REGISTER: + m_global_regs[code] = val; + return; + case TPR_REGISTER: + m_global_regs[code] = val; + if (!(val & 0x80000000)) /* change immediately */ + update_timer_prescale(); + adjust_timer_interrupt(); + return; + case TCR_REGISTER: + if (m_global_regs[code] != val) { - case 18: - SET_SP(val); - break; - - case 19: - SET_UB(val); - break; -/* - case ISR_REGISTER: - DEBUG_PRINTF(("written %08X to read-only ISR register\n",val)); - break; - - case TCR_REGISTER: -// DEBUG_PRINTF(("written %08X to TCR register\n",val)); - break; - - case 23: -// DEBUG_PRINTF(("written %08X to TR register\n",val)); - break; - - case 24: -// DEBUG_PRINTF(("written %08X to WCR register\n",val)); - break; - - case 16: - case 17: - case 28: - case 29: - case 30: - case 31: - DEBUG_PRINTF(("written %08X to _Reserved_ Global Register %d\n",val,code)); - break; - - case BCR_REGISTER: - break; -*/ - case TR_REGISTER: - m_tr_base_value = val; - m_tr_base_cycles = total_cycles(); + m_global_regs[code] = val; adjust_timer_interrupt(); - break; - - case TPR_REGISTER: - if (!(val & 0x80000000)) /* change immediately */ - update_timer_prescale(); - adjust_timer_interrupt(); - break; - - case TCR_REGISTER: - if (oldval != val) - { - adjust_timer_interrupt(); - if (m_intblock < 1) - m_intblock = 1; - } - break; - - case FCR_REGISTER: - if ((oldval ^ val) & 0x00800000) - adjust_timer_interrupt(); if (m_intblock < 1) m_intblock = 1; - break; - - case MCR_REGISTER: - // bits 14..12 EntryTableMap - hyperstone_set_trap_entry((val & 0x7000) >> 12); - break; } - } + return; + case TR_REGISTER: + m_global_regs[code] = val; + m_tr_base_value = val; + m_tr_base_cycles = total_cycles(); + adjust_timer_interrupt(); + return; + case WCR_REGISTER: + m_global_regs[code] = val; + return; + case ISR_REGISTER: + return; + case FCR_REGISTER: + if ((m_global_regs[code] ^ val) & 0x00800000) + adjust_timer_interrupt(); + m_global_regs[code] = val; + if (m_intblock < 1) + m_intblock = 1; + return; + case MCR_REGISTER: + // bits 14..12 EntryTableMap + hyperstone_set_trap_entry((val & 0x7000) >> 12); + m_global_regs[code] = val; + return; + case 28: + case 29: + case 30: + case 31: + m_global_regs[code] = val; + return; } } -#define GET_ABS_L_REG(code) m_local_regs[code] -#define SET_L_REG(code, val) set_local_register(code, val) -#define SET_ABS_L_REG(code, val) m_local_regs[code] = val -#define GET_G_REG(code) get_global_register(code) -#define SET_G_REG(code, val) set_global_register(code, val) - #define S_BIT ((OP & 0x100) >> 8) -#define N_BIT S_BIT #define D_BIT ((OP & 0x200) >> 9) -#define N_VALUE ((N_BIT << 4) | (OP & 0x0f)) +#define N_VALUE (((OP & 0x100) >> 4) | (OP & 0x0f)) #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 LOCAL 1 @@ -743,11 +719,6 @@ static const int32_t immediate_values[32] = #define decode_source_local(decode) \ do \ { \ - decode.src_is_local = 1; \ - uint8_t code = (decode.src + GET_FP) % 64; \ - SREG = m_local_regs[code]; \ - code = (decode.src + 1 + GET_FP) % 64; \ - SREGF = m_local_regs[code]; \ } while (0) #define decode_source_noh(decode) \ @@ -797,19 +768,6 @@ do } \ } while (0) -#define decode_dest_noh(decode) \ -do \ -{ \ - decode.dst_is_local = 0; \ - \ - DREG = get_global_register(decode.dst); \ - \ - /* bound safe */ \ - if (decode.dst != 15) \ - DREGF = get_global_register(decode.dst + 1); \ -} while (0) - - #define decode_dest(decode, hflag) \ do \ { \ @@ -837,106 +795,14 @@ do } \ } while (0) -#define decode_dest_local(decode) \ -do \ -{ \ - uint8_t code = decode.dst; \ - decode.dst_is_local = 1; \ - code = (decode.dst + GET_FP) % 64; /* registers offset by frame pointer */ \ - DREG = m_local_regs[code]; \ - code = (decode.dst + 1 + GET_FP) % 64; \ - DREGF = m_local_regs[code]; \ -} while (0) - -#define decode_RR00(decode) \ -do \ -{ \ - decode.src = SRC_CODE; \ - decode.dst = DST_CODE; \ - decode_source_noh(decode); \ - decode_dest_noh(decode); \ - \ - SAME_SRC_DST = (SRC_CODE == DST_CODE); \ - SAME_SRC_DSTF = (SRC_CODE == (DST_CODE + 1)); \ - SAME_SRCF_DST = ((SRC_CODE + 1) == DST_CODE); \ -} while (0) - -#define decode_RR01(decode) \ -do \ -{ \ - decode.src = SRC_CODE; \ - decode.dst = DST_CODE; \ - decode_source_local(decode); \ - decode_dest_noh(decode); \ - \ - SAME_SRC_DST = 0; \ - SAME_SRC_DSTF = 0; \ - SAME_SRCF_DST = 0; \ -} while (0) - -#define decode_RR10(decode) \ -do \ -{ \ - decode.src = SRC_CODE; \ - decode.dst = DST_CODE; \ - decode_source_noh(decode); \ - decode_dest_local(decode); \ - \ - SAME_SRC_DST = 0; \ - SAME_SRC_DSTF = 0; \ - SAME_SRCF_DST = 0; \ -} while (0) - -#define decode_RR11(decode) \ -do \ -{ \ - decode.src = SRC_CODE; \ - decode.dst = DST_CODE; \ - decode_source_local(decode); \ - decode_dest_local(decode); \ - \ - SAME_SRC_DST = (SRC_CODE == DST_CODE); \ - SAME_SRC_DSTF = (SRC_CODE == ((DST_CODE + 1) % 64)); \ - SAME_SRCF_DST = (((SRC_CODE + 1) % 64) == DST_CODE); \ -} while (0) - -#define decode_LL(decode) \ -do \ -{ \ - decode.src = SRC_CODE; \ - decode.dst = DST_CODE; \ - decode_source_local(decode); \ - decode_dest_local(decode); \ - \ - SAME_SRC_DST = (SRC_CODE == DST_CODE); \ - SAME_SRC_DSTF = (SRC_CODE == ((DST_CODE + 1) % 64)); \ - SAME_SRCF_DST = 0; \ -} while (0) - -#define decode_LR(decode, slocal) \ -do \ -{ \ - decode.src = SRC_CODE; \ - decode.dst = DST_CODE; \ - if (slocal) \ - decode_source_local(decode); \ - else \ - decode_source_noh(decode); \ - decode_dest_local(decode); \ - \ - SAME_SRC_DST = 0; \ - SAME_SRC_DSTF = 0; \ - SAME_SRCF_DST = (((SRC_CODE + 1) % 64) == DST_CODE && slocal == LOCAL); \ -} while (0) - #define check_delay_PC() \ do \ { \ /* if PC is used in a delay instruction, the delayed PC should be used */ \ - if( m_delay.delay_cmd == DELAY_EXECUTE ) \ + if (m_delay_slot) \ { \ - PC = m_delay.delay_pc; \ - m_delay.delay_cmd = NO_DELAY; \ + PC = m_delay_pc; \ + m_delay_slot = false; \ } \ } while (0) @@ -946,7 +812,7 @@ do EXTRA_U = immediate_values[OP & 0x0f]; \ } while (0) -#define decode_immediate_s(decode) \ +#define DECODE_IMMEDIATE_S(decode) \ do \ { \ switch( OP & 0x0f ) \ @@ -975,7 +841,48 @@ do } \ } while (0) -#define decode_const(decode) \ +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: + default: + return immediate_values[0x10 + nybble]; + 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; + } + } +} + +#define DECODE_CONST(decode) \ do \ { \ uint16_t imm_1 = READ_OP(PC); \ @@ -1009,30 +916,73 @@ do } \ } while (0) -#define decode_pcrel(decode) \ -do \ -{ \ - if( OP & 0x80 ) \ - { \ - uint16_t next = READ_OP(PC); \ - \ - PC += 2; \ - m_instruction_length = (2<<19); \ - \ - EXTRA_S = (OP & 0x7f) << 16; \ - EXTRA_S |= (next & 0xfffe); \ - \ - if( next & 1 ) \ - EXTRA_S |= 0xff800000; \ - } \ - else \ - { \ - EXTRA_S = OP & 0x7e; \ - \ - if( OP & 1 ) \ - EXTRA_S |= 0xffffff80; \ - } \ -} while (0) +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); + } +} #define decode_dis(decode) \ do \ @@ -1091,19 +1041,19 @@ do } \ } while (0) -void hyperstone_device::execute_br(regs_decode &decode) +void hyperstone_device::execute_br(int32_t offset) { PPC = PC; - PC += EXTRA_S; - SET_M(0); + PC += offset; + SR &= ~M_MASK; m_icount -= m_clock_cycles_2; } -void hyperstone_device::execute_dbr(regs_decode &decode) +void hyperstone_device::execute_dbr(int32_t offset) { - m_delay.delay_cmd = DELAY_EXECUTE; - m_delay.delay_pc = PC + EXTRA_S; + m_delay_slot = true; + m_delay_pc = PC + offset; m_intblock = 3; } @@ -1122,8 +1072,8 @@ void hyperstone_device::execute_trap(uint32_t addr) SET_FL(6); SET_FP(reg); - SET_L_REG(0, (PC & 0xfffffffe) | GET_S); - SET_L_REG(1, oldSR); + set_local_register(0, (PC & 0xfffffffe) | GET_S); + set_local_register(1, oldSR); SET_M(0); SET_T(0); @@ -1150,8 +1100,8 @@ void hyperstone_device::execute_int(uint32_t addr) SET_FL(2); SET_FP(reg); - SET_L_REG(0, (PC & 0xfffffffe) | GET_S); - SET_L_REG(1, oldSR); + set_local_register(0, (PC & 0xfffffffe) | GET_S); + set_local_register(1, oldSR); SET_M(0); SET_T(0); @@ -1179,8 +1129,8 @@ void hyperstone_device::execute_exception(uint32_t addr) SET_FP(reg); SET_FL(2); - SET_L_REG(0, (PC & 0xfffffffe) | GET_S); - SET_L_REG(1, oldSR); + set_local_register(0, (PC & 0xfffffffe) | GET_S); + set_local_register(1, oldSR); SET_M(0); SET_T(0); @@ -1194,40 +1144,43 @@ void hyperstone_device::execute_exception(uint32_t addr) m_icount -= m_clock_cycles_2; } -void hyperstone_device::execute_software(regs_decode &decode) +void hyperstone_device::execute_software() { - uint8_t reg; - uint32_t oldSR; - uint32_t addr; - uint32_t stack_of_dst; + check_delay_PC(); + + const uint32_t fp = GET_FP; + const uint32_t src_code = SRC_CODE; + const uint32_t sreg = m_local_regs[(src_code + fp) & 0x3f]; + const uint32_t sregf = m_local_regs[(src_code + 1 + fp) & 0x3f]; SET_ILC(1<<19); - addr = get_emu_code_addr((OP & 0xff00) >> 8); - reg = GET_FP + GET_FL; + 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 - stack_of_dst = (SP & ~0xff) + 64*4 + (((GET_FP + decode.dst) % 64) * 4); //converted to 32bits offset + const uint32_t stack_of_dst = (SP & ~0xff) + 64*4 + (((fp + DST_CODE) % 64) * 4); //converted to 32bits offset - oldSR = SR; + const uint32_t oldSR = SR; SET_FL(6); SET_FP(reg); - SET_L_REG(0, stack_of_dst); - SET_L_REG(1, SREG); - SET_L_REG(2, SREGF); - SET_L_REG(3, (PC & 0xfffffffe) | GET_S); - SET_L_REG(4, oldSR); + 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; - SET_M(0); - SET_T(0); - SET_L(1); + SR &= ~(M_MASK | T_MASK); + SR |= L_MASK; PPC = PC; PC = addr; + + m_icount -= m_clock_cycles_6; } @@ -1359,6 +1312,7 @@ void hyperstone_device::init(int scale_mask) { memset(m_global_regs, 0, sizeof(uint32_t) * 32); memset(m_local_regs, 0, sizeof(uint32_t) * 64); + memset(m_opcode_hits, 0, sizeof(uint64_t) * 256); m_ppc = 0; m_op = 0; m_trap_entry = 0; @@ -1386,6 +1340,11 @@ void hyperstone_device::init(int scale_mask) m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hyperstone_device::timer_callback), this)); m_clock_scale_mask = scale_mask; + for (uint8_t i = 0; i < 16; i++) + { + m_fl_lut[i] = (i ? i : 16); + } + // register our state for the debugger state_add(STATE_GENPC, "GENPC", m_global_regs[0]).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_global_regs[0]).noshow(); @@ -1507,10 +1466,10 @@ void hyperstone_device::init(int scale_mask) save_item(NAME(m_local_regs)); save_item(NAME(m_ppc)); save_item(NAME(m_trap_entry)); - save_item(NAME(m_delay.delay_pc)); + save_item(NAME(m_delay_pc)); save_item(NAME(m_instruction_length)); save_item(NAME(m_intblock)); - save_item(NAME(m_delay.delay_cmd)); + save_item(NAME(m_delay_slot)); save_item(NAME(m_tr_clocks_per_tick)); save_item(NAME(m_tr_base_value)); save_item(NAME(m_tr_base_cycles)); @@ -1637,15 +1596,41 @@ void hyperstone_device::device_reset() SET_L(1); SET_S(1); - SET_L_REG(0, (PC & 0xfffffffe) | GET_S); - SET_L_REG(1, SR); + set_local_register(0, (PC & 0xfffffffe) | GET_S); + set_local_register(1, SR); m_icount -= m_clock_cycles_2; } void hyperstone_device::device_stop() { - // nothing to do +#if 1 + int indices[256]; + for (int i = 0; i < 256; i++) + { + indices[i] = i; + } + for (int i = 0; i < 256; i++) + { + for (int j = i + 1; j < 256; j++) + { + if (m_opcode_hits[i] > m_opcode_hits[j]) + { + uint64_t tmp = m_opcode_hits[i]; + m_opcode_hits[i] = m_opcode_hits[j]; + m_opcode_hits[j] = tmp; + int tmpi = indices[i]; + indices[i] = indices[j]; + indices[j] = tmpi; + } + } + } + + for (int i = 255; i >= 0 && m_opcode_hits[i] != 0; i--) + { + printf("%02x: %08x%08x\n", indices[i], (uint32_t)(m_opcode_hits[i] >> 32), (uint32_t)m_opcode_hits[i]); + } +#endif } @@ -1731,49 +1716,20 @@ offs_t hyperstone_device::disasm_disassemble(std::ostream &stream, offs_t pc, co /* Opcodes */ -void hyperstone_device::hyperstone_chk(regs_decode &decode) -{ - uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); - - if( SRC_IS_SR ) - { - if( DREG == 0 ) - execute_exception(addr); - } - else - { - if( SRC_IS_PC ) - { - if( DREG >= SREG ) - execute_exception(addr); - } - else - { - if( DREG > SREG ) - execute_exception(addr); - } - } - - m_icount -= m_clock_cycles_1; -} - void hyperstone_device::hyperstone_movd(regs_decode &decode) { - if( DST_IS_PC ) // Rd denotes PC + if (DST_IS_PC) // Rd denotes PC { // RET instruction - uint8_t old_s, old_l; - int8_t difference; // really it's 7 bits - - if( SRC_IS_PC || SRC_IS_SR ) + if (SRC_IS_PC || SRC_IS_SR) { DEBUG_PRINTF(("Denoted PC or SR in RET instruction. PC = %08X\n", PC)); } else { - old_s = GET_S; - old_l = GET_L; + uint8_t old_s = GET_S; + uint8_t old_l = GET_L; PPC = PC; SET_PC(SREG); @@ -1789,7 +1745,7 @@ void hyperstone_device::hyperstone_movd(regs_decode &decode) execute_exception(addr); } - difference = GET_FP - ((SP & 0x1fc) >> 2); + int8_t difference = GET_FP - ((SP & 0x1fc) >> 2); /* convert to 8 bits */ if(difference > 63) @@ -1797,22 +1753,17 @@ void hyperstone_device::hyperstone_movd(regs_decode &decode) else if( difference < -64 ) difference = difference & 0x7f; - if( difference < 0 ) //else it's finished + for (; difference < 0; difference++) { - do - { - SP -= 4; - SET_ABS_L_REG(((SP & 0xfc) >> 2), READ_W(SP)); - difference++; - - } while(difference != 0); + SP -= 4; + m_local_regs[(SP & 0xfc) >> 2] = READ_W(SP); } } //TODO: no 1! m_icount -= m_clock_cycles_1; } - else if( SRC_IS_SR ) // Rd doesn't denote PC and Rs denotes SR + else if (SRC_IS_SR) // Rd doesn't denote PC and Rs denotes SR { SET_DREG(0); SET_DREGF(0); @@ -1823,14 +1774,12 @@ void hyperstone_device::hyperstone_movd(regs_decode &decode) } else // Rd doesn't denote PC and Rs doesn't denote SR { - uint64_t tmp; - SET_DREG(SREG); SET_DREGF(SREGF); - tmp = concat_64(SREG, SREGF); - SET_Z( tmp == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(SREG) ); + uint64_t tmp = concat_64(SREG, SREGF); + SET_Z(tmp == 0 ? 1 : 0); + SET_N(SIGN_BIT(SREG)); m_icount -= m_clock_cycles_2; } @@ -1838,47 +1787,35 @@ void hyperstone_device::hyperstone_movd(regs_decode &decode) void hyperstone_device::hyperstone_divu(regs_decode &decode) { - if( SAME_SRC_DST || SAME_SRC_DSTF ) + if (decode.same_src_dst || decode.same_src_dstf || SRC_IS_PC || SRC_IS_SR) { - DEBUG_PRINTF(("Denoted the same register code in hyperstone_divu instruction. PC = %08X\n", PC)); + DEBUG_PRINTF(("Denoted the same register code or PC/SR as source in hyperstone_divu instruction. PC = %08X\n", PC)); } else { - if( SRC_IS_PC || SRC_IS_SR ) + uint64_t dividend = concat_64(DREG, DREGF); + + if (SREG == 0) { - DEBUG_PRINTF(("Denoted PC or SR as source register in hyperstone_divu instruction. PC = %08X\n", PC)); + //Rd//Rdf -> undefined + //Z -> undefined + //N -> undefined + SR |= V_MASK; + uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); + execute_exception(addr); } else { - uint64_t dividend; + /* TODO: add quotient overflow */ + uint32_t quotient = dividend / SREG; + uint32_t remainder = dividend % SREG; - dividend = concat_64(DREG, DREGF); + SET_DREG(remainder); + SET_DREGF(quotient); - if( SREG == 0 ) - { - //Rd//Rdf -> undefined - //Z -> undefined - //N -> undefined - uint32_t addr; - SET_V(1); - addr = get_trap_addr(TRAPNO_RANGE_ERROR); - execute_exception(addr); - } - else - { - uint32_t quotient, remainder; - - /* TODO: add quotient overflow */ - quotient = dividend / SREG; - remainder = dividend % SREG; - - SET_DREG(remainder); - SET_DREGF(quotient); - - SET_Z( quotient == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(quotient) ); - SET_V(0); - } + SET_Z(quotient == 0 ? 1 : 0); + SET_N(SIGN_BIT(quotient)); + SR &= ~V_MASK; } } @@ -1887,7 +1824,7 @@ void hyperstone_device::hyperstone_divu(regs_decode &decode) void hyperstone_device::hyperstone_divs(regs_decode &decode) { - if( SAME_SRC_DST || SAME_SRC_DSTF ) + if( decode.same_src_dst || decode.same_src_dstf ) { DEBUG_PRINTF(("Denoted the same register code in hyperstone_divs instruction. PC = %08X\n", PC)); } @@ -1899,34 +1836,29 @@ void hyperstone_device::hyperstone_divs(regs_decode &decode) } else { - int64_t dividend; - - dividend = (int64_t) concat_64(DREG, DREGF); + int64_t dividend = (int64_t) concat_64(DREG, DREGF); if( SREG == 0 || (DREG & 0x80000000) ) { //Rd//Rdf -> undefined //Z -> undefined //N -> undefined - uint32_t addr; - SET_V(1); - addr = get_trap_addr(TRAPNO_RANGE_ERROR); + SR |= V_MASK; + uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); execute_exception(addr); } else { - int32_t quotient, remainder; - /* TODO: add quotient overflow */ - quotient = dividend / ((int32_t)(SREG)); - remainder = dividend % ((int32_t)(SREG)); + int32_t quotient = dividend / ((int32_t)(SREG)); + int32_t remainder = dividend % ((int32_t)(SREG)); SET_DREG(remainder); SET_DREGF(quotient); - SET_Z( quotient == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(quotient) ); - SET_V(0); + SET_Z(quotient == 0 ? 1 : 0); + SET_N(SIGN_BIT(quotient)); + SR &= ~V_MASK; } } } @@ -1993,12 +1925,11 @@ void hyperstone_device::hyperstone_mask(regs_decode &decode) void hyperstone_device::hyperstone_sum(regs_decode &decode) { - uint64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = (uint64_t)(SREG) + (uint64_t)(EXTRA_U); + const uint64_t tmp = (uint64_t)(SREG) + (uint64_t)(EXTRA_U); + CHECK_C(tmp); CHECK_VADD(SREG,EXTRA_U,tmp); @@ -2006,40 +1937,37 @@ void hyperstone_device::hyperstone_sum(regs_decode &decode) SET_DREG(DREG); - if( DST_IS_PC ) + if (DST_IS_PC) SET_M(0); - SET_Z( DREG == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(DREG) ); + SET_Z(DREG == 0 ? 1 : 0); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_sums(regs_decode &decode) { - int32_t res; - int64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = (int64_t)((int32_t)(SREG)) + (int64_t)(EXTRA_S); + int64_t tmp = (int64_t)((int32_t)(SREG)) + (int64_t)(EXTRA_S); CHECK_VADD(SREG,EXTRA_S,tmp); //#if SETCARRYS // CHECK_C(tmp); //#endif - res = (int32_t)(SREG) + EXTRA_S; + int32_t res = (int32_t)(SREG) + EXTRA_S; SET_DREG(res); - SET_Z( res == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(res) ); + SET_Z(res == 0 ? 1 : 0); + SET_N(SIGN_BIT(res)); m_icount -= m_clock_cycles_1; - if( GET_V && !SRC_IS_SR ) + if (GET_V && !SRC_IS_SR) { uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); execute_exception(addr); @@ -2048,35 +1976,33 @@ void hyperstone_device::hyperstone_sums(regs_decode &decode) void hyperstone_device::hyperstone_cmp(regs_decode &decode) { - uint64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - if( DREG == SREG ) - SET_Z(1); + if (DREG == SREG) + SR |= Z_MASK; else - SET_Z(0); + SR &= ~Z_MASK; - if( (int32_t) DREG < (int32_t) SREG ) - SET_N(1); + if ((int32_t) DREG < (int32_t) SREG) + SR |= N_MASK; else - SET_N(0); + SR &= ~N_MASK; - tmp = (uint64_t)(DREG) - (uint64_t)(SREG); - CHECK_VSUB(SREG,DREG,tmp); + uint64_t tmp = (uint64_t)(DREG) - (uint64_t)(SREG); + CHECK_VSUB(SREG, DREG, tmp); - if( DREG < SREG ) - SET_C(1); + if (DREG < SREG) + SR |= C_MASK; else - SET_C(0); + SR &= ~C_MASK; m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_mov(regs_decode &decode) { - if( !GET_S && decode.dst >= 16 ) + if (!GET_S && decode.dst >= 16) { uint32_t addr = get_trap_addr(TRAPNO_PRIVILEGE_ERROR); execute_exception(addr); @@ -2084,11 +2010,11 @@ void hyperstone_device::hyperstone_mov(regs_decode &decode) SET_DREG(SREG); - if( DST_IS_PC ) - SET_M(0); + if (DST_IS_PC) + SR &= ~M_MASK; - SET_Z( SREG == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(SREG) ); + SET_Z(SREG == 0 ? 1 : 0); + SET_N(SIGN_BIT(SREG)); m_icount -= m_clock_cycles_1; } @@ -2096,100 +2022,58 @@ void hyperstone_device::hyperstone_mov(regs_decode &decode) void hyperstone_device::hyperstone_add(regs_decode &decode) { - uint64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = (uint64_t)(SREG) + (uint64_t)(DREG); + uint64_t tmp = (uint64_t)(SREG) + (uint64_t)(DREG); CHECK_C(tmp); CHECK_VADD(SREG,DREG,tmp); DREG = SREG + DREG; SET_DREG(DREG); - if( DST_IS_PC ) + if (DST_IS_PC) SET_M(0); - SET_Z( DREG == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(DREG) ); + SET_Z(DREG == 0 ? 1 : 0); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_adds(regs_decode &decode) { - int32_t res; - int64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = (int64_t)((int32_t)(SREG)) + (int64_t)((int32_t)(DREG)); + int64_t tmp = (int64_t)((int32_t)(SREG)) + (int64_t)((int32_t)(DREG)); - CHECK_VADD(SREG,DREG,tmp); + CHECK_VADD(SREG, DREG, tmp); //#if SETCARRYS // CHECK_C(tmp); //#endif - res = (int32_t)(SREG) + (int32_t)(DREG); + int32_t res = (int32_t)(SREG) + (int32_t)(DREG); SET_DREG(res); - SET_Z( res == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(res) ); + SET_Z(res == 0 ? 1 : 0); + SET_N(SIGN_BIT(res)); m_icount -= m_clock_cycles_1; - if( GET_V ) + if (SR & V_MASK) { uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); execute_exception(addr); } } -void hyperstone_device::hyperstone_cmpb(regs_decode &decode) -{ - SET_Z( (DREG & SREG) == 0 ? 1 : 0 ); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_andn(regs_decode &decode) -{ - DREG = DREG & ~SREG; - - SET_DREG(DREG); - SET_Z( DREG == 0 ? 1 : 0 ); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_or(regs_decode &decode) -{ - DREG = DREG | SREG; - - SET_DREG(DREG); - SET_Z( DREG == 0 ? 1 : 0 ); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_xor(regs_decode &decode) -{ - DREG = DREG ^ SREG; - - SET_DREG(DREG); - SET_Z( DREG == 0 ? 1 : 0 ); - - m_icount -= m_clock_cycles_1; -} - void hyperstone_device::hyperstone_subc(regs_decode &decode) { uint64_t tmp; - if( SRC_IS_SR ) + if (SRC_IS_SR) { tmp = (uint64_t)(DREG) - (uint64_t)(GET_C); CHECK_VSUB(GET_C,DREG,tmp); @@ -2198,11 +2082,11 @@ void hyperstone_device::hyperstone_subc(regs_decode &decode) { tmp = (uint64_t)(DREG) - ((uint64_t)(SREG) + (uint64_t)(GET_C)); //CHECK! - CHECK_VSUB(SREG + GET_C,DREG,tmp); + CHECK_VSUB((SREG + GET_C),DREG,tmp); } - if( SRC_IS_SR ) + if (SRC_IS_SR) { DREG = DREG - GET_C; } @@ -2215,52 +2099,39 @@ void hyperstone_device::hyperstone_subc(regs_decode &decode) SET_DREG(DREG); - SET_Z( GET_Z & (DREG == 0 ? 1 : 0) ); - SET_N( SIGN_BIT(DREG) ); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_not(regs_decode &decode) -{ - SET_DREG(~SREG); - SET_Z( ~SREG == 0 ? 1 : 0 ); + SET_Z(GET_Z & (DREG == 0 ? 1 : 0)); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_sub(regs_decode &decode) { - uint64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = (uint64_t)(DREG) - (uint64_t)(SREG); + uint64_t tmp = (uint64_t)(DREG) - (uint64_t)(SREG); CHECK_C(tmp); CHECK_VSUB(SREG,DREG,tmp); DREG = DREG - SREG; SET_DREG(DREG); - if( DST_IS_PC ) - SET_M(0); + if (DST_IS_PC) + SR &= ~M_MASK; - SET_Z( DREG == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(DREG) ); + SET_Z(DREG == 0 ? 1 : 0); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_subs(regs_decode &decode) { - int32_t res; - int64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = (int64_t)((int32_t)(DREG)) - (int64_t)((int32_t)(SREG)); + int64_t tmp = (int64_t)((int32_t)(DREG)) - (int64_t)((int32_t)(SREG)); //#ifdef SETCARRYS // CHECK_C(tmp); @@ -2268,16 +2139,16 @@ void hyperstone_device::hyperstone_subs(regs_decode &decode) CHECK_VSUB(SREG,DREG,tmp); - res = (int32_t)(DREG) - (int32_t)(SREG); + int32_t res = (int32_t)(DREG) - (int32_t)(SREG); SET_DREG(res); - SET_Z( res == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(res) ); + SET_Z(res == 0 ? 1 : 0); + SET_N(SIGN_BIT(res)); m_icount -= m_clock_cycles_1; - if( GET_V ) + if (SR & V_MASK) { uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); execute_exception(addr); @@ -2287,8 +2158,7 @@ void hyperstone_device::hyperstone_subs(regs_decode &decode) void hyperstone_device::hyperstone_addc(regs_decode &decode) { uint64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) { tmp = (uint64_t)(DREG) + (uint64_t)(GET_C); CHECK_VADD(DREG,GET_C,tmp); @@ -2309,9 +2179,7 @@ void hyperstone_device::hyperstone_addc(regs_decode &decode) CHECK_VADD3(SREG,DREG,GET_C,tmp); } - - - if( SRC_IS_SR ) + if (SRC_IS_SR) DREG = DREG + GET_C; else DREG = SREG + DREG + GET_C; @@ -2319,30 +2187,18 @@ void hyperstone_device::hyperstone_addc(regs_decode &decode) CHECK_C(tmp); SET_DREG(DREG); - SET_Z( GET_Z & (DREG == 0 ? 1 : 0) ); - SET_N( SIGN_BIT(DREG) ); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_and(regs_decode &decode) -{ - DREG = DREG & SREG; - - SET_DREG(DREG); - SET_Z( DREG == 0 ? 1 : 0 ); + SET_Z(GET_Z & (DREG == 0 ? 1 : 0)); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_neg(regs_decode &decode) { - uint64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = -(uint64_t)(SREG); + uint64_t tmp = -(uint64_t)(SREG); CHECK_C(tmp); CHECK_VSUB(SREG,0,tmp); @@ -2350,72 +2206,44 @@ void hyperstone_device::hyperstone_neg(regs_decode &decode) SET_DREG(DREG); - SET_Z( DREG == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(DREG) ); + SET_Z(DREG == 0 ? 1 : 0); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_negs(regs_decode &decode) { - int32_t res; - int64_t tmp; - - if( SRC_IS_SR ) + if (SRC_IS_SR) SREG = GET_C; - tmp = -(int64_t)((int32_t)(SREG)); + int64_t tmp = -(int64_t)((int32_t)(SREG)); CHECK_VSUB(SREG,0,tmp); //#if SETCARRYS // CHECK_C(tmp); //#endif - res = -(int32_t)(SREG); + int32_t res = -(int32_t)(SREG); SET_DREG(res); - SET_Z( res == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(res) ); + SET_Z(res == 0 ? 1 : 0); + SET_N(SIGN_BIT(res)); m_icount -= m_clock_cycles_1; - if( GET_V && !SRC_IS_SR ) //trap doesn't occur when source is SR + if (GET_V && !SRC_IS_SR) //trap doesn't occur when source is SR { uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); execute_exception(addr); } } -void hyperstone_device::hyperstone_cmpi(regs_decode &decode) -{ - uint64_t tmp; - - tmp = (uint64_t)(DREG) - (uint64_t)(EXTRA_U); - CHECK_VSUB(EXTRA_U,DREG,tmp); - - if( DREG == EXTRA_U ) - SET_Z(1); - else - SET_Z(0); - - if( (int32_t) DREG < (int32_t) EXTRA_U ) - SET_N(1); - else - SET_N(0); - - if( DREG < EXTRA_U ) - SET_C(1); - else - SET_C(0); - - m_icount -= m_clock_cycles_1; -} - void hyperstone_device::hyperstone_movi(regs_decode &decode) { - if( !GET_S && decode.dst >= 16 ) + if (!GET_S && decode.dst >= 16) { uint32_t addr = get_trap_addr(TRAPNO_PRIVILEGE_ERROR); execute_exception(addr); @@ -2423,14 +2251,14 @@ void hyperstone_device::hyperstone_movi(regs_decode &decode) SET_DREG(EXTRA_U); - if( DST_IS_PC ) - SET_M(0); + if (DST_IS_PC) + SR &= ~M_MASK; - SET_Z( EXTRA_U == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(EXTRA_U) ); + SET_Z(EXTRA_U == 0 ? 1 : 0); + SET_N(SIGN_BIT(EXTRA_U)); #if MISSIONCRAFT_FLAGS - SET_V(0); // or V undefined ? + SR &= ~V_MASK; // or V undefined ? #endif m_icount -= m_clock_cycles_1; @@ -2439,57 +2267,53 @@ void hyperstone_device::hyperstone_movi(regs_decode &decode) void hyperstone_device::hyperstone_addi(regs_decode &decode) { uint32_t imm; - uint64_t tmp; - - if( N_VALUE ) + if (N_VALUE) imm = EXTRA_U; else imm = GET_C & ((GET_Z == 0 ? 1 : 0) | (DREG & 0x01)); - tmp = (uint64_t)(imm) + (uint64_t)(DREG); + uint64_t tmp = (uint64_t)(imm) + (uint64_t)(DREG); CHECK_C(tmp); CHECK_VADD(imm,DREG,tmp); DREG = imm + DREG; SET_DREG(DREG); - if( DST_IS_PC ) - SET_M(0); + if (DST_IS_PC) + SR &= ~M_MASK; - SET_Z( DREG == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(DREG) ); + SET_Z(DREG == 0 ? 1 : 0); + SET_N(SIGN_BIT(DREG)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_addsi(regs_decode &decode) { - int32_t imm, res; - int64_t tmp; - - if( N_VALUE ) + int32_t imm; + if (N_VALUE) imm = EXTRA_S; else imm = GET_C & ((GET_Z == 0 ? 1 : 0) | (DREG & 0x01)); - tmp = (int64_t)(imm) + (int64_t)((int32_t)(DREG)); + int64_t tmp = (int64_t)(imm) + (int64_t)((int32_t)(DREG)); CHECK_VADD(imm,DREG,tmp); //#if SETCARRYS // CHECK_C(tmp); //#endif - res = imm + (int32_t)(DREG); + int32_t res = imm + (int32_t)(DREG); SET_DREG(res); - SET_Z( res == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(res) ); + SET_Z(res == 0 ? 1 : 0); + SET_N(SIGN_BIT(res)); m_icount -= m_clock_cycles_1; - if( GET_V ) + if (SR & V_MASK) { uint32_t addr = get_trap_addr(TRAPNO_RANGE_ERROR); execute_exception(addr); @@ -2542,16 +2366,6 @@ void hyperstone_device::hyperstone_andni(regs_decode &decode) m_icount -= m_clock_cycles_1; } -void hyperstone_device::hyperstone_ori(regs_decode &decode) -{ - DREG = DREG | EXTRA_U; - - SET_DREG(DREG); - SET_Z( DREG == 0 ? 1 : 0 ); - - m_icount -= m_clock_cycles_1; -} - void hyperstone_device::hyperstone_xori(regs_decode &decode) { DREG = DREG ^ EXTRA_U; @@ -2564,18 +2378,15 @@ void hyperstone_device::hyperstone_xori(regs_decode &decode) void hyperstone_device::hyperstone_shrdi(regs_decode &decode) { - uint32_t low_order, high_order; - uint64_t val; + uint32_t high_order = DREG; + uint32_t low_order = DREGF; - high_order = DREG; - low_order = DREGF; - - val = concat_64(high_order, low_order); + uint64_t val = concat_64(high_order, low_order); if( N_VALUE ) SET_C((val >> (N_VALUE - 1)) & 1); else - SET_C(0); + SR &= ~C_MASK; val >>= N_VALUE; @@ -2584,348 +2395,206 @@ void hyperstone_device::hyperstone_shrdi(regs_decode &decode) SET_DREG(high_order); SET_DREGF(low_order); - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(high_order) ); - - m_icount -= m_clock_cycles_2; -} - -void hyperstone_device::hyperstone_shrd(regs_decode &decode) -{ - uint32_t low_order, high_order; - uint64_t val; - uint8_t n = SREG & 0x1f; - - // result undefined if Ls denotes the same register as Ld or Ldf - if( SAME_SRC_DST || SAME_SRC_DSTF ) - { - DEBUG_PRINTF(("Denoted same registers in hyperstone_shrd. PC = %08X\n", PC)); - } - else - { - high_order = DREG; - low_order = DREGF; - - val = concat_64(high_order, low_order); - - if( n ) - SET_C((val >> (n - 1)) & 1); - else - SET_C(0); - - val >>= n; - - high_order = extract_64hi(val); - low_order = extract_64lo(val); - - SET_DREG(high_order); - SET_DREGF(low_order); - - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(high_order) ); - } + SET_Z(val == 0 ? 1 : 0); + SET_N(SIGN_BIT(high_order)); m_icount -= m_clock_cycles_2; } void hyperstone_device::hyperstone_shr(regs_decode &decode) { - uint32_t ret; - uint8_t n; + uint32_t n = SREG & 0x1f; + uint32_t ret = DREG; - n = SREG & 0x1f; - ret = DREG; - - if( n ) + if (n) SET_C((ret >> (n - 1)) & 1); else - SET_C(0); + SR &= ~C_MASK; ret >>= n; SET_DREG(ret); - SET_Z( ret == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(ret) ); + SET_Z(ret == 0 ? 1 : 0); + SET_N(SIGN_BIT(ret)); m_icount -= m_clock_cycles_1; } -void hyperstone_device::hyperstone_sardi(regs_decode &decode) +void hyperstone_device::hyperstone_sardi() { - uint32_t low_order, high_order; - uint64_t val; - uint8_t sign_bit; + check_delay_PC(); - high_order = DREG; - low_order = DREGF; + const uint32_t dst_code = (DST_CODE + GET_FP) % 64; + const uint32_t dstf_code = (DST_CODE + GET_FP + 1) % 64; - val = concat_64(high_order, low_order); + uint64_t val = concat_64(m_local_regs[dst_code], m_local_regs[dstf_code]); - if( N_VALUE ) - SET_C((val >> (N_VALUE - 1)) & 1); - else - SET_C(0); + SR &= ~(C_MASK | Z_MASK | N_MASK); - sign_bit = val >> 63; - val >>= N_VALUE; - - if( sign_bit ) + const uint32_t n = N_VALUE; + if (n) { - int i; - for( i = 0; i < N_VALUE; i++ ) - { - val |= (0x8000000000000000U >> i); - } - } - - high_order = val >> 32; - low_order = val & 0xffffffff; - - SET_DREG(high_order); - SET_DREGF(low_order); - - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(high_order) ); - - m_icount -= m_clock_cycles_2; -} - -void hyperstone_device::hyperstone_sard(regs_decode &decode) -{ - uint32_t low_order, high_order; - uint64_t val; - uint8_t n, sign_bit; - - n = SREG & 0x1f; - - // result undefined if Ls denotes the same register as Ld or Ldf - if( SAME_SRC_DST || SAME_SRC_DSTF ) - { - DEBUG_PRINTF(("Denoted same registers in hyperstone_sard. PC = %08X\n", PC)); - } - else - { - high_order = DREG; - low_order = DREGF; - - val = concat_64(high_order, low_order); - - if( n ) - SET_C((val >> (n - 1)) & 1); - else - SET_C(0); - - sign_bit = val >> 63; + SR |= (val >> (n - 1)) & 1; + const uint64_t sign_bit = val >> 63; val >>= n; - if( sign_bit ) + if (sign_bit) { - int i; - for( i = 0; i < n; i++ ) - { - val |= (0x8000000000000000U >> i); - } + val |= 0xffffffff00000000U << (32 - n); } - - high_order = val >> 32; - low_order = val & 0xffffffff; - - SET_DREG(high_order); - SET_DREGF(low_order); - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(high_order) ); } + m_local_regs[dst_code] = (uint32_t)(val >> 32); + m_local_regs[dstf_code] = (uint32_t)val; + + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(m_local_regs[dst_code]); + m_icount -= m_clock_cycles_2; } void hyperstone_device::hyperstone_sar(regs_decode &decode) { - uint32_t ret; - uint8_t n, sign_bit; + uint32_t n = SREG & 0x1f; + uint32_t ret = DREG; + uint32_t sign_bit = (ret & 0x80000000) >> 31; - n = SREG & 0x1f; - ret = DREG; - sign_bit = (ret & 0x80000000) >> 31; - - if( n ) + if (n) SET_C((ret >> (n - 1)) & 1); else - SET_C(0); + SR &= ~C_MASK; ret >>= n; - if( sign_bit ) + if (sign_bit) { - int i; - for( i = 0; i < n; i++ ) + for (int i = 0; i < n; i++) { ret |= (0x80000000 >> i); } } SET_DREG(ret); - SET_Z( ret == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(ret) ); + SET_Z(ret == 0 ? 1 : 0); + SET_N(SIGN_BIT(ret)); m_icount -= m_clock_cycles_1; } -void hyperstone_device::hyperstone_shldi(regs_decode &decode) +void hyperstone_device::hyperstone_shld() { - uint32_t low_order, high_order, tmp; - uint64_t val, mask; + check_delay_PC(); - high_order = DREG; - low_order = DREGF; - - val = concat_64(high_order, low_order); - SET_C( (N_VALUE)?(((val<<(N_VALUE-1))&0x8000000000000000U)?1:0):0); - mask = ((((uint64_t)1) << (32 - N_VALUE)) - 1) ^ 0xffffffff; - tmp = high_order << N_VALUE; - - if( ((high_order & mask) && (!(tmp & 0x80000000))) || - (((high_order & mask) ^ mask) && (tmp & 0x80000000)) ) - SET_V(1); - else - SET_V(0); - - val <<= N_VALUE; - - high_order = extract_64hi(val); - low_order = extract_64lo(val); - - SET_DREG(high_order); - SET_DREGF(low_order); - - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(high_order) ); - - m_icount -= m_clock_cycles_2; -} - -void hyperstone_device::hyperstone_shld(regs_decode &decode) -{ - uint32_t low_order, high_order, tmp, n; - uint64_t val, mask; - - n = SREG & 0x1f; + uint32_t src_code = (SRC_CODE + GET_FP) % 64; + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + uint32_t dstf_code = (DST_CODE + GET_FP + 1) % 64; // result undefined if Ls denotes the same register as Ld or Ldf - if( SAME_SRC_DST || SAME_SRC_DSTF ) + if (src_code == dst_code || src_code == dstf_code) { DEBUG_PRINTF(("Denoted same registers in hyperstone_shld. PC = %08X\n", PC)); } else { - high_order = DREG; - low_order = DREGF; + uint32_t n = m_local_regs[src_code % 64] & 0x1f; + uint32_t high_order = m_local_regs[dst_code]; /* registers offset by frame pointer */ + uint32_t low_order = m_local_regs[dstf_code]; - mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff; + uint64_t mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff; - val = concat_64(high_order, low_order); + uint64_t val = concat_64(high_order, low_order); SET_C( (n)?(((val<<(n-1))&0x8000000000000000U)?1:0):0); - tmp = high_order << n; + uint32_t tmp = high_order << n; - if( ((high_order & mask) && (!(tmp & 0x80000000))) || - (((high_order & mask) ^ mask) && (tmp & 0x80000000)) ) + if (((high_order & mask) && (!(tmp & 0x80000000))) || (((high_order & mask) ^ mask) && (tmp & 0x80000000))) SET_V(1); else - SET_V(0); + SR &= ~V_MASK; val <<= n; - high_order = extract_64hi(val); - low_order = extract_64lo(val); + m_local_regs[dst_code] = extract_64hi(val); + m_local_regs[dstf_code] = extract_64lo(val); - SET_DREG(high_order); - SET_DREGF(low_order); - - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(high_order) ); + SET_Z(val == 0 ? 1 : 0); + SET_N(SIGN_BIT(high_order)); } m_icount -= m_clock_cycles_2; } -void hyperstone_device::hyperstone_shl(regs_decode &decode) +void hyperstone_device::hyperstone_shl() { - uint32_t base, ret, n; - uint64_t mask; + check_delay_PC(); - n = SREG & 0x1f; - base = DREG; - mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff; + uint32_t src_code = SRC_CODE + GET_FP; + uint32_t dst_code = DST_CODE + GET_FP; + + uint32_t n = m_local_regs[src_code % 64] & 0x1f; + uint32_t base = m_local_regs[dst_code % 64]; /* registers offset by frame pointer */ + uint64_t mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff; SET_C( (n)?(((base<<(n-1))&0x80000000)?1:0):0); - ret = base << n; + uint32_t ret = base << n; - if( ((base & mask) && (!(ret & 0x80000000))) || - (((base & mask) ^ mask) && (ret & 0x80000000)) ) + if (((base & mask) && (!(ret & 0x80000000))) || (((base & mask) ^ mask) && (ret & 0x80000000))) SET_V(1); else - SET_V(0); + SR &= ~V_MASK; - SET_DREG(ret); - SET_Z( ret == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(ret) ); + m_local_regs[dst_code % 64] = ret; + SET_Z(ret == 0 ? 1 : 0); + SET_N(SIGN_BIT(ret)); m_icount -= m_clock_cycles_1; } -void hyperstone_device::hyperstone_testlz(regs_decode &decode) +void hyperstone_device::hyperstone_testlz() { - uint8_t zeros = 0; - uint32_t mask; + check_delay_PC(); - for( mask = 0x80000000; ; mask >>= 1 ) + uint32_t sreg = m_local_regs[(SRC_CODE + GET_FP) % 64]; + uint32_t zeros = 0; + for (uint32_t mask = 0x80000000; mask != 0; mask >>= 1 ) { - if( SREG & mask ) + if (sreg & mask) break; else zeros++; - - if( zeros == 32 ) - break; } - SET_DREG(zeros); + m_local_regs[(DST_CODE + GET_FP) % 64] = zeros; m_icount -= m_clock_cycles_2; } void hyperstone_device::hyperstone_rol(regs_decode &decode) { - uint32_t val, base; - uint8_t n; - uint64_t mask; + uint32_t n = SREG & 0x1f; - n = SREG & 0x1f; + uint32_t val = DREG; + uint32_t base = val; - val = base = DREG; + uint64_t mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff; - mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff; - - while( n > 0 ) + while (n > 0) { val = (val << 1) | ((val & 0x80000000) >> 31); n--; } #ifdef MISSIONCRAFT_FLAGS - - if( ((base & mask) && (!(val & 0x80000000))) || - (((base & mask) ^ mask) && (val & 0x80000000)) ) + if (((base & mask) && (!(val & 0x80000000))) || (((base & mask) ^ mask) && (val & 0x80000000))) SET_V(1); else SET_V(0); - #endif SET_DREG(val); - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(val) ); + SET_Z(val == 0 ? 1 : 0); + SET_N(SIGN_BIT(val)); m_icount -= m_clock_cycles_1; } @@ -2935,7 +2604,7 @@ void hyperstone_device::hyperstone_ldxx1(regs_decode &decode) { uint32_t load; - if( DST_IS_SR ) + if (DST_IS_SR) { switch( decode.sub_type ) { @@ -2977,33 +2646,26 @@ void hyperstone_device::hyperstone_ldxx1(regs_decode &decode) if( (EXTRA_S & 3) == 3 ) // LDD.IOA { - load = IO_READ_W(EXTRA_S & ~3); - SET_SREG(load); + SET_SREG(IO_READ_W(EXTRA_S)); load = IO_READ_W((EXTRA_S & ~3) + 4); SET_SREGF(load); m_icount -= m_clock_cycles_1; // extra cycle } - else if( (EXTRA_S & 3) == 2 ) // LDW.IOA + else if ((EXTRA_S & 3) == 2) // LDW.IOA { - load = IO_READ_W(EXTRA_S & ~3); - SET_SREG(load); + SET_SREG(IO_READ_W(EXTRA_S)); } - else if( (EXTRA_S & 3) == 1 ) // LDD.A + else if( (EXTRA_S & 3) == 1) // LDD.A { - load = READ_W(EXTRA_S & ~1); - SET_SREG(load); - - load = READ_W((EXTRA_S & ~1) + 4); - SET_SREGF(load); - + SET_SREG(READ_W(EXTRA_S)); + SET_SREGF(READ_W(EXTRA_S + 4)); m_icount -= m_clock_cycles_1; // extra cycle } - else // LDW.A + else // LDW.A { - load = READ_W(EXTRA_S & ~1); - SET_SREG(load); + SET_SREG(READ_W(EXTRA_S)); } break; @@ -3011,73 +2673,47 @@ void hyperstone_device::hyperstone_ldxx1(regs_decode &decode) } else { - switch( decode.sub_type ) + switch (decode.sub_type) { case 0: // LDBS.D - - load = READ_B(DREG + EXTRA_S); - load |= (load & 0x80) ? 0xffffff00 : 0; - SET_SREG(load); - + SET_SREG((int32_t)(int8_t)READ_B(DREG + EXTRA_S)); break; case 1: // LDBU.D - - load = READ_B(DREG + EXTRA_S); - SET_SREG(load); - + SET_SREG(READ_B(DREG + EXTRA_S)); break; case 2: - - load = READ_HW(DREG + (EXTRA_S & ~1)); - - if( EXTRA_S & 1 ) // LDHS.D + if (EXTRA_S & 1) { - load |= (load & 0x8000) ? 0xffff0000 : 0; + SET_SREG((int32_t)(int16_t)READ_HW(DREG + (EXTRA_S & ~1))); } - /* - else // LDHU.D + else { - // nothing more + SET_SREG(READ_HW(DREG + (EXTRA_S & ~1))); } - */ - - SET_SREG(load); - break; case 3: - - if( (EXTRA_S & 3) == 3 ) // LDD.IOD + if ((EXTRA_S & 3) == 3) // LDD.IOD { - load = IO_READ_W(DREG + (EXTRA_S & ~3)); - SET_SREG(load); - - load = IO_READ_W(DREG + (EXTRA_S & ~3) + 4); - SET_SREGF(load); - + SET_SREG(IO_READ_W(DREG + (EXTRA_S & ~3))); + SET_SREGF(IO_READ_W(DREG + (EXTRA_S & ~3) + 4)); m_icount -= m_clock_cycles_1; // extra cycle } - else if( (EXTRA_S & 3) == 2 ) // LDW.IOD + else if ((EXTRA_S & 3) == 2) // LDW.IOD { - load = IO_READ_W(DREG + (EXTRA_S & ~3)); - SET_SREG(load); + SET_SREG(IO_READ_W(DREG + (EXTRA_S & ~3))); } - else if( (EXTRA_S & 3) == 1 ) // LDD.D + else if ((EXTRA_S & 3) == 1) // LDD.D { - load = READ_W(DREG + (EXTRA_S & ~1)); - SET_SREG(load); - - load = READ_W(DREG + (EXTRA_S & ~1) + 4); - SET_SREGF(load); - + SET_SREG(READ_W(DREG + (EXTRA_S & ~1))); + SET_SREGF(READ_W(DREG + (EXTRA_S & ~1) + 4)); m_icount -= m_clock_cycles_1; // extra cycle } - else // LDW.D + else // LDW.D { - load = READ_W(DREG + (EXTRA_S & ~1)); - SET_SREG(load); + SET_SREG(READ_W(DREG + (EXTRA_S & ~1))); } break; @@ -3089,9 +2725,7 @@ void hyperstone_device::hyperstone_ldxx1(regs_decode &decode) void hyperstone_device::hyperstone_ldxx2(regs_decode &decode) { - uint32_t load; - - if( DST_IS_PC || DST_IS_SR ) + if (DST_IS_PC || DST_IS_SR) { DEBUG_PRINTF(("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC)); } @@ -3100,106 +2734,61 @@ void hyperstone_device::hyperstone_ldxx2(regs_decode &decode) switch( decode.sub_type ) { case 0: // LDBS.N + SET_SREG((int32_t)(int8_t)READ_B(DREG)); - if(SAME_SRC_DST) - DEBUG_PRINTF(("LDBS.N denoted same regs @ %08X",PPC)); - - load = READ_B(DREG); - load |= (load & 0x80) ? 0xffffff00 : 0; - SET_SREG(load); - - if(!SAME_SRC_DST) + if (!decode.same_src_dst) SET_DREG(DREG + EXTRA_S); - break; case 1: // LDBU.N + SET_SREG(READ_B(DREG)); - if(SAME_SRC_DST) - DEBUG_PRINTF(("LDBU.N denoted same regs @ %08X",PPC)); - - load = READ_B(DREG); - SET_SREG(load); - - if(!SAME_SRC_DST) + if(!decode.same_src_dst) SET_DREG(DREG + EXTRA_S); - break; case 2: + if (EXTRA_S & 1) // LDHS.N + SET_SREG((int32_t)(int16_t)READ_HW(DREG)); + else // LDHU.N + SET_SREG(READ_HW(DREG)); - load = READ_HW(DREG); - - if( EXTRA_S & 1 ) // LDHS.N - { - load |= (load & 0x8000) ? 0xffff0000 : 0; - - if(SAME_SRC_DST) - DEBUG_PRINTF(("LDHS.N denoted same regs @ %08X",PPC)); - } - /* - else // LDHU.N - { - // nothing more - } - */ - - SET_SREG(load); - - if(!SAME_SRC_DST) + if(!decode.same_src_dst) SET_DREG(DREG + (EXTRA_S & ~1)); - break; case 3: - - if( (EXTRA_S & 3) == 3 ) // LDW.S + switch (EXTRA_S & 3) { - if(SAME_SRC_DST) - DEBUG_PRINTF(("LDW.S denoted same regs @ %08X",PPC)); - - if(DREG < SP) + case 0: // LDW.N SET_SREG(READ_W(DREG)); - else - SET_SREG(GET_ABS_L_REG((DREG & 0xfc) >> 2)); + if(!decode.same_src_dst) + SET_DREG(DREG + (EXTRA_S & ~1)); + break; + case 1: // LDD.N + SET_SREG(READ_W(DREG)); + SET_SREGF(READ_W(DREG + 4)); - if(!SAME_SRC_DST) - SET_DREG(DREG + (EXTRA_S & ~3)); + if (!decode.same_src_dst && !decode.same_srcf_dst) + SET_DREG(DREG + (EXTRA_S & ~1)); - m_icount -= m_clock_cycles_2; // extra cycles + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // Reserved + DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC)); + break; + case 3: // LDW.S + if (DREG < SP) + SET_SREG(READ_W(DREG)); + else + SET_SREG(m_local_regs[(DREG & 0xfc) >> 2]); + + if (!decode.same_src_dst) + SET_DREG(DREG + (EXTRA_S & ~3)); + + m_icount -= m_clock_cycles_2; // extra cycles + break; } - else if( (EXTRA_S & 3) == 2 ) // Reserved - { - DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC)); - } - else if( (EXTRA_S & 3) == 1 ) // LDD.N - { - if(SAME_SRC_DST || SAME_SRCF_DST) - DEBUG_PRINTF(("LDD.N denoted same regs @ %08X",PPC)); - - load = READ_W(DREG); - SET_SREG(load); - - load = READ_W(DREG + 4); - SET_SREGF(load); - - if(!SAME_SRC_DST && !SAME_SRCF_DST) - SET_DREG(DREG + (EXTRA_S & ~1)); - - m_icount -= m_clock_cycles_1; // extra cycle - } - else // LDW.N - { - if(SAME_SRC_DST) - DEBUG_PRINTF(("LDW.N denoted same regs @ %08X",PPC)); - - load = READ_W(DREG); - SET_SREG(load); - - if(!SAME_SRC_DST) - SET_DREG(DREG + (EXTRA_S & ~1)); - } - break; } } @@ -3395,10 +2984,10 @@ void hyperstone_device::hyperstone_stxx2(regs_decode &decode) WRITE_W(DREG, SREG); else { - if(((DREG & 0xfc) >> 2) == ((decode.src + GET_FP) % 64) && S_BIT == LOCAL) + if(((DREG & 0xfc) >> 2) == ((decode.src + GET_FP) % 64) && (OP & 0x100)) DEBUG_PRINTF(("STW.S denoted the same local register @ %08X\n",PPC)); - SET_ABS_L_REG((DREG & 0xfc) >> 2,SREG); + m_local_regs[(DREG & 0xfc) >> 2] = SREG; } SET_DREG(DREG + (EXTRA_S & ~3)); @@ -3415,7 +3004,7 @@ void hyperstone_device::hyperstone_stxx2(regs_decode &decode) WRITE_W(DREG, SREG); SET_DREG(DREG + (EXTRA_S & ~1)); - if( SAME_SRCF_DST ) + if( decode.same_srcf_dst ) WRITE_W(DREG + 4, SREGF + (EXTRA_S & ~1)); // because DREG == SREGF and DREG has been incremented else WRITE_W(DREG + 4, SREGF); @@ -3437,11 +3026,9 @@ void hyperstone_device::hyperstone_stxx2(regs_decode &decode) void hyperstone_device::hyperstone_shri(regs_decode &decode) { - uint32_t val; + uint32_t val = DREG; - val = DREG; - - if( N_VALUE ) + if (N_VALUE) SET_C((val >> (N_VALUE - 1)) & 1); else SET_C(0); @@ -3449,62 +3036,34 @@ void hyperstone_device::hyperstone_shri(regs_decode &decode) val >>= N_VALUE; SET_DREG(val); - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(val) ); + SET_Z(val == 0 ? 1 : 0); + SET_N(SIGN_BIT(val)); m_icount -= m_clock_cycles_1; } void hyperstone_device::hyperstone_sari(regs_decode &decode) { - uint32_t val; - uint8_t sign_bit; + uint32_t val = DREG; + uint32_t sign_bit = val & 0x80000000; - val = DREG; - sign_bit = (val & 0x80000000) >> 31; + const uint32_t n = N_VALUE; - if( N_VALUE ) - SET_C((val >> (N_VALUE - 1)) & 1); - else - SET_C(0); + SR &= ~(C_MASK | Z_MASK | N_MASK); + if (n) + SET_C((val >> (n - 1)) & 1); - val >>= N_VALUE; + val >>= n; - if( sign_bit ) - { - int i; - for( i = 0; i < N_VALUE; i++ ) - { + if (sign_bit) + for (int i = 0; i < n; i++) val |= (0x80000000 >> i); - } - } SET_DREG(val); - SET_Z( val == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(val) ); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_shli(regs_decode &decode) -{ - uint32_t val, val2; - uint64_t mask; - - val = DREG; - SET_C( (N_VALUE)?(((val<<(N_VALUE-1))&0x80000000)?1:0):0); - mask = ((((uint64_t)1) << (32 - N_VALUE)) - 1) ^ 0xffffffff; - val2 = val << N_VALUE; - - if( ((val & mask) && (!(val2 & 0x80000000))) || - (((val & mask) ^ mask) && (val2 & 0x80000000)) ) - SET_V(1); - else - SET_V(0); - - SET_DREG(val2); - SET_Z( val2 == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(val2) ); + if (val == 0) + SR |= Z_MASK; + if (SIGN_BIT(val)) + SR |= N_MASK; m_icount -= m_clock_cycles_1; } @@ -3570,13 +3129,13 @@ void hyperstone_device::hyperstone_muls(regs_decode &decode) void hyperstone_device::hyperstone_set(regs_decode &decode) { - int n = N_VALUE; + const uint32_t n = N_VALUE; - if( DST_IS_PC ) + if ( DST_IS_PC) { DEBUG_PRINTF(("Denoted PC in hyperstone_set. PC = %08X\n", PC)); } - else if( DST_IS_SR ) + else if (DST_IS_SR) { //TODO: add fetch opcode when there's the pipeline @@ -3585,21 +3144,13 @@ void hyperstone_device::hyperstone_set(regs_decode &decode) } else { - switch( n ) + switch (n) { // SETADR case 0: - { - uint32_t val; - val = (SP & 0xfffffe00) | (GET_FP << 2); - - //plus carry into bit 9 - val += (( (SP & 0x100) && (SIGN_BIT(SR) == 0) ) ? 1 : 0); - - SET_DREG(val); - + SET_DREG((SP & 0xfffffe00) | (GET_FP << 2) | (((SP & 0x100) && (SIGN_BIT(SR) == 0)) ? 1 : 0)); break; - } + // Reserved case 1: case 16: @@ -3916,8 +3467,6 @@ void hyperstone_device::hyperstone_set(regs_decode &decode) void hyperstone_device::hyperstone_mul(regs_decode &decode) { - uint32_t single_word; - // PC or SR aren't denoted, else result is undefined if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR ) { @@ -3925,305 +3474,23 @@ void hyperstone_device::hyperstone_mul(regs_decode &decode) } else { - single_word = (SREG * DREG);// & 0xffffffff; // only the low-order word is taken + const uint32_t single_word = (SREG * DREG);// & 0xffffffff; // only the low-order word is taken SET_DREG(single_word); - SET_Z( single_word == 0 ? 1 : 0 ); - SET_N( SIGN_BIT(single_word) ); + SR &= ~(Z_MASK | N_MASK); + if (single_word == 0) + SR |= Z_MASK; + if (SIGN_BIT(single_word)) + SR |= N_MASK; } - if((SREG >= 0xffff8000 && SREG <= 0x7fff) && (DREG >= 0xffff8000 && DREG <= 0x7fff)) + if ((SREG >= 0xffff8000 && SREG <= 0x7fff) && (DREG >= 0xffff8000 && DREG <= 0x7fff)) m_icount -= 3 << m_clck_scale; else m_icount -= 5 << m_clck_scale; } -void hyperstone_device::hyperstone_fadd(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_faddd(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fsub(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fsubd(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fmul(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fmuld(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fdiv(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fdivd(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fcmp(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fcmpd(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fcmpu(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fcmpud(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fcvt(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_fcvtd(regs_decode &decode) -{ - execute_software(decode); - m_icount -= m_clock_cycles_6; -} - -void hyperstone_device::hyperstone_extend(regs_decode &decode) -{ - //TODO: add locks, overflow error and other things - uint32_t vals, vald; - - vals = SREG; - vald = DREG; - - switch( EXTRA_U ) // extended opcode - { - // signed or unsigned multiplication, single word product - case EMUL: - case 0x100: // used in "N" type cpu - { - uint32_t result; - - result = vals * vald; - SET_G_REG(15, result); - - break; - } - // unsigned multiplication, double word product - case EMULU: - { - uint64_t result; - - result = (uint64_t)vals * (uint64_t)vald; - vals = result >> 32; - vald = result & 0xffffffff; - SET_G_REG(14, vals); - SET_G_REG(15, vald); - - break; - } - // signed multiplication, double word product - case EMULS: - { - int64_t result; - - result = (int64_t)(int32_t)(vals) * (int64_t)(int32_t)(vald); - vals = result >> 32; - vald = result & 0xffffffff; - SET_G_REG(14, vals); - SET_G_REG(15, vald); - - break; - } - // signed multiply/add, single word product sum - case EMAC: - { - int32_t result; - - result = (int32_t)GET_G_REG(15) + ((int32_t)(vals) * (int32_t)(vald)); - SET_G_REG(15, result); - - break; - } - // signed multiply/add, double word product sum - case EMACD: - { - int64_t result; - - result = (int64_t)concat_64(GET_G_REG(14), GET_G_REG(15)) + (int64_t)((int64_t)(int32_t)(vals) * (int64_t)(int32_t)(vald)); - - vals = result >> 32; - vald = result & 0xffffffff; - SET_G_REG(14, vals); - SET_G_REG(15, vald); - - break; - } - // signed multiply/substract, single word product difference - case EMSUB: - { - int32_t result; - - result = (int32_t)GET_G_REG(15) - ((int32_t)(vals) * (int32_t)(vald)); - SET_G_REG(15, result); - - break; - } - // signed multiply/substract, double word product difference - case EMSUBD: - { - int64_t result; - - result = (int64_t)concat_64(GET_G_REG(14), GET_G_REG(15)) - (int64_t)((int64_t)(int32_t)(vals) * (int64_t)(int32_t)(vald)); - - vals = result >> 32; - vald = result & 0xffffffff; - SET_G_REG(14, vals); - SET_G_REG(15, vald); - - break; - } - // signed half-word multiply/add, single word product sum - case EHMAC: - { - int32_t result; - - result = (int32_t)GET_G_REG(15) + ((int32_t)((vald & 0xffff0000) >> 16) * (int32_t)((vals & 0xffff0000) >> 16)) + ((int32_t)(vald & 0xffff) * (int32_t)(vals & 0xffff)); - SET_G_REG(15, result); - - break; - } - // signed half-word multiply/add, double word product sum - case EHMACD: - { - int64_t result; - - result = (int64_t)concat_64(GET_G_REG(14), GET_G_REG(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)); - - vals = result >> 32; - vald = result & 0xffffffff; - SET_G_REG(14, vals); - SET_G_REG(15, vald); - - break; - } - // half-word complex multiply - case EHCMULD: - { - uint32_t result; - - result = (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff)); - SET_G_REG(14, result); - - result = (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16)); - SET_G_REG(15, result); - - break; - } - // half-word complex multiply/add - case EHCMACD: - { - uint32_t result; - - result = GET_G_REG(14) + (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff)); - SET_G_REG(14, result); - - result = GET_G_REG(15) + (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16)); - SET_G_REG(15, result); - - break; - } - // half-word (complex) add/substract - // Ls is not used and should denote the same register as Ld - case EHCSUMD: - { - uint32_t result; - - result = ((((vals & 0xffff0000) >> 16) + GET_G_REG(14)) << 16) & 0xffff0000; - result |= ((vals & 0xffff) + GET_G_REG(15)) & 0xffff; - SET_G_REG(14, result); - - result = ((((vals & 0xffff0000) >> 16) - GET_G_REG(14)) << 16) & 0xffff0000; - result |= ((vals & 0xffff) - GET_G_REG(15)) & 0xffff; - SET_G_REG(15, result); - - break; - } - // half-word (complex) add/substract with fixed point adjustment - // Ls is not used and should denote the same register as Ld - case EHCFFTD: - { - uint32_t result; - - result = ((((vals & 0xffff0000) >> 16) + (GET_G_REG(14) >> 15)) << 16) & 0xffff0000; - result |= ((vals & 0xffff) + (GET_G_REG(15) >> 15)) & 0xffff; - SET_G_REG(14, result); - - result = ((((vals & 0xffff0000) >> 16) - (GET_G_REG(14) >> 15)) << 16) & 0xffff0000; - result |= ((vals & 0xffff) - (GET_G_REG(15) >> 15)) & 0xffff; - SET_G_REG(15, result); - - break; - } - // half-word (complex) add/substract with fixed point adjustment and shift - // Ls is not used and should denote the same register as Ld - case EHCFFTSD: - { - uint32_t result; - - result = (((((vals & 0xffff0000) >> 16) + (GET_G_REG(14) >> 15)) >> 1) << 16) & 0xffff0000; - result |= ((((vals & 0xffff) + (GET_G_REG(15) >> 15)) >> 1) & 0xffff); - SET_G_REG(14, result); - - result = (((((vals & 0xffff0000) >> 16) - (GET_G_REG(14) >> 15)) >> 1) << 16) & 0xffff0000; - result |= ((((vals & 0xffff) - (GET_G_REG(15) >> 15)) >> 1) & 0xffff); - SET_G_REG(15, result); - - break; - } - default: - DEBUG_PRINTF(("Executed Illegal extended opcode (%X). PC = %08X\n", EXTRA_U, PC)); - break; - } - - m_icount -= m_clock_cycles_1; //TODO: with the latency it can change -} - void hyperstone_device::hyperstone_do(regs_decode &decode) { fatalerror("Executed hyperstone_do instruction. PC = %08X\n", PPC); @@ -4250,7 +3517,7 @@ void hyperstone_device::hyperstone_ldwp(regs_decode &decode) // post increment the destination register if it's different from the source one // (needed by Hidden Catch) - if(!(decode.src == decode.dst && S_BIT == LOCAL)) + if(!(decode.src == decode.dst && (OP & 0x100))) SET_DREG(DREG + 4); m_icount -= m_clock_cycles_1; @@ -4263,7 +3530,7 @@ void hyperstone_device::hyperstone_lddp(regs_decode &decode) // post increment the destination register if it's different from the source one // and from the "next source" one - if(!(decode.src == decode.dst && S_BIT == LOCAL) && !SAME_SRCF_DST ) + if(!(decode.src == decode.dst && (OP & 0x100)) && !decode.same_srcf_dst ) { SET_DREG(DREG + 8); } @@ -4315,7 +3582,7 @@ void hyperstone_device::hyperstone_stdp(regs_decode &decode) WRITE_W(DREG, SREG); SET_DREG(DREG + 8); - if( SAME_SRCF_DST ) + if( decode.same_srcf_dst ) WRITE_W(DREG + 4, SREGF + 8); // because DREG == SREGF and DREG has been incremented else WRITE_W(DREG + 4, SREGF); @@ -4323,282 +3590,7 @@ void hyperstone_device::hyperstone_stdp(regs_decode &decode) m_icount -= m_clock_cycles_2; } -void hyperstone_device::hyperstone_dbv(regs_decode &decode) -{ - if( GET_V ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbnv(regs_decode &decode) -{ - if( !GET_V ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbe(regs_decode &decode) //or DBZ -{ - if( GET_Z ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbne(regs_decode &decode) //or DBNZ -{ - if( !GET_Z ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbc(regs_decode &decode) //or DBST -{ - if( GET_C ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbnc(regs_decode &decode) //or DBHE -{ - if( !GET_C ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbse(regs_decode &decode) -{ - if( GET_C || GET_Z ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbht(regs_decode &decode) -{ - if( !GET_C && !GET_Z ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbn(regs_decode &decode) //or DBLT -{ - if( GET_N ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbnn(regs_decode &decode) //or DBGE -{ - if( !GET_N ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dble(regs_decode &decode) -{ - if( GET_N || GET_Z ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbgt(regs_decode &decode) -{ - if( !GET_N && !GET_Z ) - execute_dbr(decode); - - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_dbr(regs_decode &decode) -{ - execute_dbr(decode); -} - -void hyperstone_device::hyperstone_frame(regs_decode &decode) -{ - int8_t difference; // really it's 7 bits - uint8_t realfp = GET_FP - SRC_CODE; - - SET_FP(realfp); - SET_FL(DST_CODE); - SET_M(0); - - difference = ((SP & 0x1fc) >> 2) + (64 - 10) - (realfp + GET_FL); - - /* convert to 8 bits */ - if(difference > 63) - difference = (int8_t)(difference|0x80); - else if( difference < -64 ) - difference = difference & 0x7f; - - if( difference < 0 ) // else it's finished - { - uint8_t tmp_flag; - - tmp_flag = ( SP >= UB ? 1 : 0 ); - - do - { - WRITE_W(SP, GET_ABS_L_REG((SP & 0xfc) >> 2)); - SP += 4; - difference++; - - } while(difference != 0); - - if( tmp_flag ) - { - uint32_t addr = get_trap_addr(TRAPNO_FRAME_ERROR); - execute_exception(addr); - } - } - - //TODO: no 1! - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_call(regs_decode &decode) -{ - if( SRC_IS_SR ) - SREG = 0; - - if( !DST_CODE ) - decode.dst = 16; - - EXTRA_S = (EXTRA_S & ~1) + SREG; - - SET_ILC(m_instruction_length); - - SET_DREG((PC & 0xfffffffe) | GET_S); - SET_DREGF(SR); - - SET_FP(GET_FP + decode.dst); - - SET_FL(6); //default value for call - SET_M(0); - - PPC = PC; - PC = EXTRA_S; // const value - - m_intblock = 2; - - //TODO: add interrupt locks, errors, .... - - //TODO: no 1! - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bv(regs_decode &decode) -{ - if( GET_V ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bnv(regs_decode &decode) -{ - if( !GET_V ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_be(regs_decode &decode) //or BZ -{ - if( GET_Z ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bne(regs_decode &decode) //or BNZ -{ - if( !GET_Z ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bc(regs_decode &decode) //or BST -{ - if( GET_C ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bnc(regs_decode &decode) //or BHE -{ - if( !GET_C ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bse(regs_decode &decode) -{ - if( GET_C || GET_Z ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bht(regs_decode &decode) -{ - if( !GET_C && !GET_Z ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bn(regs_decode &decode) //or BLT -{ - if( GET_N ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bnn(regs_decode &decode) //or BGE -{ - if( !GET_N ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_ble(regs_decode &decode) -{ - if( GET_N || GET_Z ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_bgt(regs_decode &decode) -{ - if( !GET_N && !GET_Z ) - execute_br(decode); - else - m_icount -= m_clock_cycles_1; -} - -void hyperstone_device::hyperstone_br(regs_decode &decode) -{ - execute_br(decode); -} - -void hyperstone_device::hyperstone_trap(regs_decode &decode) +void hyperstone_device::hyperstone_trap() { uint8_t code, trapno; uint32_t addr; @@ -4759,13 +3751,14 @@ void hyperstone_device::execute_run() m_instruction_length = (1<<19); #if 1 + //m_opcode_hits[(OP >> 8) & 0x00ff]++; /* execute opcode */ switch ((OP >> 8) & 0x00ff) { - case 0x00: op00(); break; - case 0x01: op01(); break; - case 0x02: op02(); break; - case 0x03: op03(); break; + 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: op04(); break; case 0x05: op05(); break; case 0x06: op06(); break; @@ -4810,10 +3803,10 @@ void hyperstone_device::execute_run() case 0x2d: op2d(); break; case 0x2e: op2e(); break; case 0x2f: op2f(); break; - case 0x30: op30(); break; - case 0x31: op31(); break; - case 0x32: op32(); break; - case 0x33: op33(); break; + case 0x30: op30(); break; // cmpb + case 0x31: op31(); break; // cmpb + case 0x32: op32(); break; // cmpb + case 0x33: op33(); break; // cmpb case 0x34: op34(); break; case 0x35: op35(); break; case 0x36: op36(); break; @@ -4846,10 +3839,10 @@ void hyperstone_device::execute_run() case 0x51: op51(); break; case 0x52: op52(); break; case 0x53: op53(); break; - case 0x54: op54(); break; - case 0x55: op55(); break; - case 0x56: op56(); break; - case 0x57: op57(); 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: op58(); break; case 0x59: op59(); break; case 0x5a: op5a(); break; @@ -4858,10 +3851,10 @@ void hyperstone_device::execute_run() case 0x5d: op5d(); break; case 0x5e: op5e(); break; case 0x5f: op5f(); break; - case 0x60: op60(); break; - case 0x61: op61(); break; - case 0x62: op62(); break; - case 0x63: op63(); 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: op64(); break; case 0x65: op65(); break; case 0x66: op66(); break; @@ -4882,29 +3875,29 @@ void hyperstone_device::execute_run() case 0x75: op75(); break; case 0x76: op76(); break; case 0x77: op77(); break; - case 0x78: op78(); break; - case 0x79: op79(); break; - case 0x7a: op7a(); break; - case 0x7b: op7b(); 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: op7c(); break; case 0x7d: op7d(); break; case 0x7e: op7e(); break; case 0x7f: op7f(); break; case 0x80: op80(); break; case 0x81: op81(); break; - case 0x82: op82(); break; + case 0x82: hyperstone_shrd(); break; case 0x83: op83(); break; - case 0x84: op84(); break; - case 0x85: op85(); break; - case 0x86: op86(); break; + case 0x84: hyperstone_sardi(); break; + case 0x85: hyperstone_sardi(); break; + case 0x86: hyperstone_sard(); break; case 0x87: op87(); break; - case 0x88: op88(); break; - case 0x89: op89(); break; - case 0x8a: op8a(); break; - case 0x8b: op8b(); break; + case 0x88: hyperstone_shldi(); break; + case 0x89: hyperstone_shldi(); break; + case 0x8a: hyperstone_shld(); break; + case 0x8b: hyperstone_shl(); break; case 0x8c: op8c(); break; case 0x8d: op8d(); break; - case 0x8e: op8e(); break; + case 0x8e: hyperstone_testlz(); break; case 0x8f: op8f(); break; case 0x90: op90(); break; case 0x91: op91(); break; @@ -4924,16 +3917,16 @@ void hyperstone_device::execute_run() case 0x9f: op9f(); break; case 0xa0: opa0(); break; case 0xa1: opa1(); break; - case 0xa2: opa2(); break; - case 0xa3: opa3(); break; + case 0xa2: hyperstone_shri_local(); break; + case 0xa3: hyperstone_shri_local(); break; case 0xa4: opa4(); break; case 0xa5: opa5(); break; case 0xa6: opa6(); break; case 0xa7: opa7(); break; - case 0xa8: opa8(); break; - case 0xa9: opa9(); break; - case 0xaa: opaa(); break; - case 0xab: opab(); break; + case 0xa8: hyperstone_shli_global(); break; + case 0xa9: hyperstone_shli_global(); break; + case 0xaa: hyperstone_shli_local(); break; + case 0xab: hyperstone_shli_local(); break; case 0xac: opac(); break; case 0xad: opad(); break; case 0xae: opae(); break; @@ -4954,20 +3947,20 @@ void hyperstone_device::execute_run() case 0xbd: opbd(); break; case 0xbe: opbe(); break; case 0xbf: opbf(); break; - case 0xc0: opc0(); break; - case 0xc1: opc1(); break; - case 0xc2: opc2(); break; - case 0xc3: opc3(); break; - case 0xc4: opc4(); break; - case 0xc5: opc5(); break; - case 0xc6: opc6(); break; - case 0xc7: opc7(); break; - case 0xc8: opc8(); break; - case 0xc9: opc9(); break; - case 0xca: opca(); break; - case 0xcb: opcb(); break; - case 0xcc: opcc(); break; - case 0xcd: opcd(); 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: opce(); break; case 0xcf: opcf(); break; case 0xd0: opd0(); break; @@ -5028,7 +4021,7 @@ void hyperstone_device::execute_run() SET_ILC(m_instruction_length); - if( GET_T && GET_P && m_delay.delay_cmd == NO_DELAY ) /* Not in a Delayed Branch instructions */ + if (GET_T && GET_P && !m_delay_slot) /* Not in a Delayed Branch instructions */ { uint32_t addr = get_trap_addr(TRAPNO_TRACE_EXCEPTION); execute_exception(addr); diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 2d6e9c94ebd..a3d4261d724 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -132,13 +132,6 @@ protected: direct_read_data *m_direct; address_space *m_io; - /* Delay information */ - struct delay_info - { - int32_t delay_cmd; - uint32_t delay_pc; - }; - // CPU registers uint32_t m_global_regs[32]; uint32_t m_local_regs[64]; @@ -161,7 +154,8 @@ protected: uint8_t m_timer_int_pending; emu_timer *m_timer; - delay_info m_delay; + uint32_t m_delay_pc; + bool m_delay_slot; uint32_t m_opcodexor; @@ -174,8 +168,8 @@ protected: typedef void (hyperstone_device::*ophandler)(); ophandler m_opcode[256]; - - static const ophandler s_opcodetable[256]; + uint64_t m_opcode_hits[256]; + uint8_t m_fl_lut[16]; private: struct regs_decode @@ -215,14 +209,21 @@ private: TIMER_CALLBACK_MEMBER(timer_callback); - void execute_br(regs_decode &decode); - void execute_dbr(regs_decode &decode); + void execute_br(int32_t offset); + void execute_dbr(int32_t offset); void execute_trap(uint32_t addr); void execute_int(uint32_t addr); void execute_exception(uint32_t addr); - void execute_software(regs_decode &decode); + void execute_software(); - void hyperstone_chk(regs_decode &decode); + void ignore_immediate_s(); + uint32_t decode_immediate_s(); + uint32_t decode_const(); + + void hyperstone_chk_global_global(); + void hyperstone_chk_global_local(); + void hyperstone_chk_local_global(); + void hyperstone_chk_local_local(); void hyperstone_movd(regs_decode &decode); void hyperstone_divu(regs_decode &decode); void hyperstone_divs(regs_decode &decode); @@ -234,39 +235,42 @@ private: void hyperstone_mov(regs_decode &decode); void hyperstone_add(regs_decode &decode); void hyperstone_adds(regs_decode &decode); - void hyperstone_cmpb(regs_decode &decode); - void hyperstone_andn(regs_decode &decode); - void hyperstone_or(regs_decode &decode); - void hyperstone_xor(regs_decode &decode); void hyperstone_subc(regs_decode &decode); - void hyperstone_not(regs_decode &decode); void hyperstone_sub(regs_decode &decode); void hyperstone_subs(regs_decode &decode); void hyperstone_addc(regs_decode &decode); - void hyperstone_and(regs_decode &decode); void hyperstone_neg(regs_decode &decode); void hyperstone_negs(regs_decode &decode); - void hyperstone_cmpi(regs_decode &decode); + void hyperstone_and_global_global(); + void hyperstone_and_global_local(); + void hyperstone_and_local_global(); + void hyperstone_and_local_local(); + void hyperstone_cmpi_global_simm(); + void hyperstone_cmpi_global_limm(); + void hyperstone_cmpi_local_simm(); + void hyperstone_cmpi_local_limm(); void hyperstone_movi(regs_decode &decode); void hyperstone_addi(regs_decode &decode); void hyperstone_addsi(regs_decode &decode); void hyperstone_cmpbi(regs_decode &decode); void hyperstone_andni(regs_decode &decode); - void hyperstone_ori(regs_decode &decode); + void hyperstone_ori_global_simm(); + void hyperstone_ori_global_limm(); + void hyperstone_ori_local_simm(); + void hyperstone_ori_local_limm(); void hyperstone_xori(regs_decode &decode); void hyperstone_shrdi(regs_decode &decode); - void hyperstone_shrd(regs_decode &decode); + void hyperstone_shrd(); void hyperstone_shr(regs_decode &decode); void hyperstone_shri(regs_decode &decode); - void hyperstone_sardi(regs_decode &decode); - void hyperstone_sard(regs_decode &decode); + void hyperstone_sardi(); + void hyperstone_sard(); void hyperstone_sar(regs_decode &decode); void hyperstone_sari(regs_decode &decode); - void hyperstone_shldi(regs_decode &decode); - void hyperstone_shld(regs_decode &decode); - void hyperstone_shl(regs_decode &decode); - void hyperstone_shli(regs_decode &decode); - void hyperstone_testlz(regs_decode &decode); + void hyperstone_shldi(); + void hyperstone_shld(); + void hyperstone_shl(); + void hyperstone_testlz(); void hyperstone_rol(regs_decode &decode); void hyperstone_ldxx1(regs_decode &decode); void hyperstone_ldxx2(regs_decode &decode); @@ -277,25 +281,6 @@ private: void hyperstone_mul(regs_decode &decode); void hyperstone_set(regs_decode &decode); - void hyperstone_fadd(regs_decode &decode); - void hyperstone_faddd(regs_decode &decode); - void hyperstone_fsub(regs_decode &decode); - void hyperstone_fsubd(regs_decode &decode); - void hyperstone_fmul(regs_decode &decode); - void hyperstone_fmuld(regs_decode &decode); - void hyperstone_fdiv(regs_decode &decode); - void hyperstone_fdivd(regs_decode &decode); - - void hyperstone_fcmp(regs_decode &decode); - void hyperstone_fcmpd(regs_decode &decode); - void hyperstone_fcmpu(regs_decode &decode); - void hyperstone_fcmpud(regs_decode &decode); - - void hyperstone_fcvt(regs_decode &decode); - void hyperstone_fcvtd(regs_decode &decode); - - void hyperstone_extend(regs_decode &decode); - void hyperstone_ldwr(regs_decode &decode); void hyperstone_lddr(regs_decode &decode); void hyperstone_ldwp(regs_decode &decode); @@ -306,40 +291,16 @@ private: void hyperstone_stwp(regs_decode &decode); void hyperstone_stdp(regs_decode &decode); - void hyperstone_dbv(regs_decode &decode); - void hyperstone_dbnv(regs_decode &decode); - void hyperstone_dbe(regs_decode &decode); - void hyperstone_dbne(regs_decode &decode); - void hyperstone_dbc(regs_decode &decode); - void hyperstone_dbnc(regs_decode &decode); - void hyperstone_dbse(regs_decode &decode); - void hyperstone_dbht(regs_decode &decode); - void hyperstone_dbn(regs_decode &decode); - void hyperstone_dbnn(regs_decode &decode); - void hyperstone_dble(regs_decode &decode); - void hyperstone_dbgt(regs_decode &decode); - void hyperstone_dbr(regs_decode &decode); - - void hyperstone_frame(regs_decode &decode); - void hyperstone_call(regs_decode &decode); - - void hyperstone_bv(regs_decode &decode); - void hyperstone_bnv(regs_decode &decode); - void hyperstone_be(regs_decode &decode); - void hyperstone_bne(regs_decode &decode); - void hyperstone_bc(regs_decode &decode); - void hyperstone_bnc(regs_decode &decode); - void hyperstone_bse(regs_decode &decode); - void hyperstone_bht(regs_decode &decode); - void hyperstone_bn(regs_decode &decode); - void hyperstone_bnn(regs_decode &decode); - void hyperstone_ble(regs_decode &decode); - void hyperstone_bgt(regs_decode &decode); - void hyperstone_br(regs_decode &decode); - - void hyperstone_trap(regs_decode &decode); + void hyperstone_trap(); void hyperstone_do(regs_decode &decode); + void hyperstone_shli_global(); + void hyperstone_shli_local(); + void hyperstone_shri_local(); + + int32_t decode_pcrel(); + void ignore_pcrel(); + #if 0 void execute_run_drc(); void flush_drc_cache(); @@ -356,7 +317,7 @@ private: bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); #endif - void op00(); void op01(); void op02(); void op03(); void op04(); void op05(); void op06(); void op07(); + void op04(); void op05(); void op06(); void op07(); void op08(); void op09(); void op0a(); void op0b(); void op0c(); void op0d(); void op0e(); void op0f(); void op10(); void op11(); void op12(); void op13(); void op14(); void op15(); void op16(); void op17(); void op18(); void op19(); void op1a(); void op1b(); void op1c(); void op1d(); void op1e(); void op1f(); @@ -366,22 +327,22 @@ private: void op38(); void op39(); void op3a(); void op3b(); void op3c(); void op3d(); void op3e(); void op3f(); void op40(); void op41(); void op42(); void op43(); void op44(); void op45(); void op46(); void op47(); void op48(); void op49(); void op4a(); void op4b(); void op4c(); void op4d(); void op4e(); void op4f(); - void op50(); void op51(); void op52(); void op53(); void op54(); void op55(); void op56(); void op57(); + void op50(); void op51(); void op52(); void op53(); void op58(); void op59(); void op5a(); void op5b(); void op5c(); void op5d(); void op5e(); void op5f(); - void op60(); void op61(); void op62(); void op63(); void op64(); void op65(); void op66(); void op67(); + void op64(); void op65(); void op66(); void op67(); void op68(); void op69(); void op6a(); void op6b(); void op6c(); void op6d(); void op6e(); void op6f(); void op70(); void op71(); void op72(); void op73(); void op74(); void op75(); void op76(); void op77(); - void op78(); void op79(); void op7a(); void op7b(); void op7c(); void op7d(); void op7e(); void op7f(); - void op80(); void op81(); void op82(); void op83(); void op84(); void op85(); void op86(); void op87(); - void op88(); void op89(); void op8a(); void op8b(); void op8c(); void op8d(); void op8e(); void op8f(); + void op7c(); void op7d(); void op7e(); void op7f(); + void op80(); void op81(); void op83(); void op87(); + void op8c(); void op8d(); void op8f(); void op90(); void op91(); void op92(); void op93(); void op94(); void op95(); void op96(); void op97(); void op98(); void op99(); void op9a(); void op9b(); void op9c(); void op9d(); void op9e(); void op9f(); - void opa0(); void opa1(); void opa2(); void opa3(); void opa4(); void opa5(); void opa6(); void opa7(); - void opa8(); void opa9(); void opaa(); void opab(); void opac(); void opad(); void opae(); void opaf(); + void opa0(); void opa1(); void opa4(); void opa5(); void opa6(); void opa7(); + void opac(); void opad(); void opae(); void opaf(); void opb0(); void opb1(); void opb2(); void opb3(); void opb4(); void opb5(); void opb6(); void opb7(); void opb8(); void opb9(); void opba(); void opbb(); void opbc(); void opbd(); void opbe(); void opbf(); - void opc0(); void opc1(); void opc2(); void opc3(); void opc4(); void opc5(); void opc6(); void opc7(); - void opc8(); void opc9(); void opca(); void opcb(); void opcc(); void opcd(); void opce(); void opcf(); + + void opce(); void opcf(); void opd0(); void opd1(); void opd2(); void opd3(); void opd4(); void opd5(); void opd6(); void opd7(); void opd8(); void opd9(); void opda(); void opdb(); void opdc(); void opdd(); void opde(); void opdf(); void ope0(); void ope1(); void ope2(); void ope3(); void ope4(); void ope5(); void ope6(); void ope7(); diff --git a/src/devices/cpu/e132xs/e132xsop.hxx b/src/devices/cpu/e132xs/e132xsop.hxx index 95c9553c846..747280c8b60 100644 --- a/src/devices/cpu/e132xs/e132xsop.hxx +++ b/src/devices/cpu/e132xs/e132xsop.hxx @@ -1,74 +1,235 @@ // license:BSD-3-Clause // copyright-holders:Pierpaolo Prazzoli -void hyperstone_device::op00() +void hyperstone_device::hyperstone_chk_global_global() { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_chk(decode); + + const uint32_t src_code = SRC_CODE; + const uint32_t dst_code = DST_CODE; + const uint32_t dreg = m_global_regs[dst_code]; + + if (src_code == SR_REGISTER) + { + if (dreg == 0) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + } + else + { + const uint32_t sreg = m_global_regs[src_code]; + if (src_code == PC_REGISTER) + { + if (dreg >= sreg) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + } + else + { + if (dreg > sreg) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + } + } + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op01() +void hyperstone_device::hyperstone_chk_global_local() { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_chk(decode); + + const uint32_t sreg = m_local_regs[(SRC_CODE + GET_FP) & 0x3f]; + const uint32_t dreg = m_global_regs[DST_CODE]; + if (dreg > sreg) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op02() +void hyperstone_device::hyperstone_chk_local_global() { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_chk(decode); + + const uint32_t src_code = SRC_CODE; + const uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) & 0x3f]; + + if (src_code == SR_REGISTER) + { + if (dreg == 0) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + } + else + { + const uint32_t sreg = m_global_regs[src_code]; + if (src_code == PC_REGISTER) + { + if (dreg >= sreg) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + } + else + { + if (dreg > sreg) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + } + } + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op03() +void hyperstone_device::hyperstone_chk_local_local() { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_chk(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dreg = m_local_regs[(DST_CODE + fp) & 0x3f]; + if (dreg > sreg) + execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op04() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_movd(decode); } -void hyperstone_device::op05() +void hyperstone_device::op05() // movd, local src, global dst { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_movd(decode); + const uint32_t src_code = SRC_CODE + GET_FP; + const uint32_t dst_code = DST_CODE; + + const uint32_t sreg = m_local_regs[src_code & 0x3f]; + const uint32_t sregf = m_local_regs[(src_code + 1) & 0x3f]; + + if (dst_code == PC_REGISTER) + { + uint32_t old_s = SR & S_MASK; + uint32_t old_l = SR & L_MASK; + PPC = PC; + + SET_PC(sreg); + SR = (sregf & 0xffe00000) | ((sreg & 0x01) << 18 ) | (sregf & 0x3ffff); + if (!m_intblock) + m_intblock = 1; + + m_instruction_length = 0; // undefined + + uint32_t new_s = SR & S_MASK; + uint32_t new_l = SR & L_MASK; + if ((!old_s && new_s) || (!new_s && !old_l && new_l)) + { + uint32_t addr = get_trap_addr(TRAPNO_PRIVILEGE_ERROR); + execute_exception(addr); + } + + int8_t difference = GET_FP - ((SP & 0x1fc) >> 2); + + /* convert to 8 bits */ + if (difference > 63) + difference |= 0x80; + else if ( difference < -64 ) + difference &= 0x7f; + + for (; difference < 0; difference++) + { + SP -= 4; + m_local_regs[(SP & 0xfc) >> 2] = READ_W(SP); + } + } + else + { + set_global_register(dst_code, sreg); + set_global_register(dst_code + 1, sregf); + + uint64_t tmp = concat_64(sreg, sregf); + SR &= ~(Z_MASK | N_MASK); + if (tmp == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(sreg); + + m_icount -= m_clock_cycles_2; + } } void hyperstone_device::op06() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_movd(decode); } -void hyperstone_device::op07() +void hyperstone_device::op07() // movd local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_movd(decode); + + const uint32_t src_code = SRC_CODE; + const uint32_t dst_code = DST_CODE; + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(src_code + fp) & 0x3f]; + const uint32_t sregf = m_local_regs[(src_code + 1 + fp) & 0x3f]; + + m_local_regs[(dst_code + fp) & 0x3f] = sreg; + m_local_regs[(dst_code + 1 + fp) & 0x3f] = sregf; + + uint64_t tmp = concat_64(sreg, sregf); + SR &= ~(Z_MASK | N_MASK); + if (tmp == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(sreg); + + m_icount -= m_clock_cycles_2; } void hyperstone_device::op08() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_divu(decode); } @@ -76,7 +237,21 @@ void hyperstone_device::op09() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_divu(decode); } @@ -84,7 +259,20 @@ void hyperstone_device::op0a() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_divu(decode); } @@ -92,7 +280,20 @@ void hyperstone_device::op0b() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_divu(decode); } @@ -100,7 +301,21 @@ void hyperstone_device::op0c() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_divs(decode); } @@ -108,7 +323,21 @@ void hyperstone_device::op0d() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_divs(decode); } @@ -116,7 +345,20 @@ void hyperstone_device::op0e() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_divs(decode); } @@ -124,7 +366,20 @@ void hyperstone_device::op0f() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_divs(decode); } @@ -135,7 +390,21 @@ void hyperstone_device::op10() regs_decode decode; decode_lim(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_xm(decode); } @@ -144,7 +413,20 @@ void hyperstone_device::op11() regs_decode decode; decode_lim(decode); check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_xm(decode); } @@ -153,7 +435,20 @@ void hyperstone_device::op12() regs_decode decode; decode_lim(decode); check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_xm(decode); } @@ -162,115 +457,278 @@ void hyperstone_device::op13() regs_decode decode; decode_lim(decode); check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_xm(decode); } void hyperstone_device::op14() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_mask(decode); } void hyperstone_device::op15() { - regs_decode decode; - decode_const(decode); + const uint32_t extra_u = decode_const(); + check_delay_PC(); - decode_RR01(decode); - hyperstone_mask(decode); + + const uint32_t dreg = m_local_regs[(SRC_CODE + GET_FP) & 0x3f] & extra_u; + set_global_register(DST_CODE, dreg); + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op16() { - regs_decode decode; - decode_const(decode); + const uint32_t extra_u = decode_const(); + check_delay_PC(); - decode_RR10(decode); - hyperstone_mask(decode); + + const uint32_t dreg = m_global_regs[SRC_CODE] & extra_u; + m_local_regs[(DST_CODE + GET_FP) & 0x3f] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op17() +void hyperstone_device::op17() // mask local,local { - regs_decode decode; - decode_const(decode); + const uint32_t extra_u = decode_const(); + check_delay_PC(); - decode_RR11(decode); - hyperstone_mask(decode); + + const uint32_t fp = GET_FP; + const uint32_t dreg = m_local_regs[(SRC_CODE + fp) & 0x3f] & extra_u; + m_local_regs[(DST_CODE + fp) & 0x3f] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op18() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_sum(decode); } void hyperstone_device::op19() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_sum(decode); } void hyperstone_device::op1a() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_sum(decode); } -void hyperstone_device::op1b() +void hyperstone_device::op1b() // sum local,local { - regs_decode decode; - decode_const(decode); + const uint32_t extra_u = decode_const(); + check_delay_PC(); - decode_RR11(decode); - hyperstone_sum(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + + const uint64_t tmp = (uint64_t)sreg + (uint64_t)extra_u; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + + if ((sreg ^ tmp) & (extra_u ^ tmp) & 0x80000000) + SR |= V_MASK; + + const uint32_t dreg = sreg + extra_u; + + m_local_regs[(DST_CODE + fp) & 0x3f] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op1c() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_sums(decode); } void hyperstone_device::op1d() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_sums(decode); } void hyperstone_device::op1e() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_sums(decode); } void hyperstone_device::op1f() { regs_decode decode; - decode_const(decode); + DECODE_CONST(decode); check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_sums(decode); } @@ -280,7 +738,20 @@ void hyperstone_device::op20() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_cmp(decode); } @@ -288,24 +759,74 @@ void hyperstone_device::op21() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_cmp(decode); } -void hyperstone_device::op22() +void hyperstone_device::op22() // cmp local,global { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_cmp(decode); + + const uint32_t src_code = SRC_CODE; + const uint32_t sreg = ((src_code == SR_REGISTER) ? GET_C : m_global_regs[src_code]); + const uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) & 0x3f]; + + SR &= ~(Z_MASK | N_MASK | V_MASK | C_MASK); + + if (dreg == sreg) + SR |= Z_MASK; + + if ((int32_t)dreg < (int32_t)sreg) + SR |= N_MASK; + + const uint64_t tmp = (uint64_t)dreg - (uint64_t)sreg; + + if ((tmp ^ dreg) & (dreg ^ sreg) & 0x80000000) + SR |= V_MASK; + + if (dreg < sreg) + SR |= C_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op23() +void hyperstone_device::op23() // cmp local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_cmp(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dreg = m_local_regs[(DST_CODE + fp) & 0x3f]; + + SR &= ~(Z_MASK | N_MASK | V_MASK | C_MASK); + if (dreg == sreg) + SR |= Z_MASK; + + if ((int32_t)dreg < (int32_t)sreg) + SR |= N_MASK; + + const uint64_t tmp = (uint64_t)dreg - (uint64_t)sreg; + if ((tmp ^ dreg) & (dreg ^ sreg) & 0x80000000) + SR |= V_MASK; + + if (dreg < sreg) + SR |= C_MASK; + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op24() @@ -325,70 +846,182 @@ void hyperstone_device::op25() check_delay_PC(); decode.src = SRC_CODE; decode.dst = DST_CODE; - decode_source_local(decode); + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + decode_dest(decode, GET_H); hyperstone_mov(decode); } void hyperstone_device::op26() { - regs_decode decode; check_delay_PC(); - decode.src = SRC_CODE; - decode.dst = DST_CODE; - decode_source(decode, GET_H); - decode_dest_local(decode); - hyperstone_mov(decode); + uint32_t src_code = SRC_CODE; + + uint32_t sreg; + if (SR & H_MASK) + { + src_code += 16; + sreg = get_global_register(src_code); + if ((WRITE_ONLY_REGMASK >> src_code) & 1) + sreg = 0; /* write-only registers */ + } + else + { + sreg = m_global_regs[src_code]; \ + } + + m_local_regs[(DST_CODE + GET_FP) & 0x3f] = sreg; + + SR &= ~(Z_MASK | N_MASK); + if (sreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(sreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op27() { - regs_decode decode; check_delay_PC(); - decode.src = SRC_CODE; - decode.dst = DST_CODE; - decode_source_local(decode); - decode_dest_local(decode); - hyperstone_mov(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + m_local_regs[(DST_CODE + fp) & 0x3f] = sreg; + + SR &= ~(Z_MASK | N_MASK); + if (sreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(sreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op28() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_add(decode); } -void hyperstone_device::op29() +void hyperstone_device::op29() // add global,local { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_add(decode); + + const uint32_t dst_code = DST_CODE; + + const uint32_t sreg = m_local_regs[(SRC_CODE + GET_FP) & 0x3f]; + uint32_t dreg = m_global_regs[dst_code]; + + const uint64_t tmp = (uint64_t)sreg + (uint64_t)dreg; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + + if ((sreg ^ tmp) & (dreg ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += sreg; + set_global_register(dst_code, dreg); + + if (dst_code == 0) + SR &= ~M_MASK; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op2a() +void hyperstone_device::op2a() // add local,global { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_add(decode); + + const uint32_t src_code = SRC_CODE; + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + uint32_t sreg = ((src_code == SR_REGISTER) ? GET_C : m_global_regs[src_code]); + uint32_t dreg = m_local_regs[dst_code]; + + if (src_code == SR_REGISTER) + sreg = GET_C; + + const uint64_t tmp = (uint64_t)sreg + (uint64_t)dreg; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + + if ((sreg ^ tmp) & (dreg ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += sreg; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op2b() { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_add(decode); + + const uint32_t fp = GET_FP; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + uint32_t dreg = m_local_regs[dst_code]; + + const uint64_t tmp = (uint64_t)sreg + (uint64_t)dreg; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + + if ((sreg ^ tmp) & (dreg ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += sreg; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op2c() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_adds(decode); } @@ -396,7 +1029,15 @@ void hyperstone_device::op2d() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_adds(decode); } @@ -404,7 +1045,15 @@ void hyperstone_device::op2e() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_adds(decode); } @@ -412,138 +1061,250 @@ void hyperstone_device::op2f() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_adds(decode); } -void hyperstone_device::op30() +void hyperstone_device::op30() // cmpb { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_cmpb(decode); + + uint32_t sreg = m_global_regs[SRC_CODE]; + uint32_t dreg = m_global_regs[DST_CODE]; + + if (dreg & sreg) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op31() +void hyperstone_device::op31() // cmpb { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_cmpb(decode); + + uint32_t sreg = m_local_regs[(SRC_CODE + GET_FP) % 64]; + uint32_t dreg = m_global_regs[DST_CODE]; + + if (dreg & sreg) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op32() +void hyperstone_device::op32() // cmpb { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_cmpb(decode); + + uint32_t sreg = m_global_regs[SRC_CODE]; + uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) % 64]; /* registers offset by frame pointer */ + + if (dreg & sreg) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op33() +void hyperstone_device::op33() // cmpb { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_cmpb(decode); + + uint32_t sreg = m_local_regs[(SRC_CODE + GET_FP) % 64]; + uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) % 64]; /* registers offset by frame pointer */ + + if (dreg & sreg) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op34() +void hyperstone_device::op34() // andn { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_andn(decode); + + uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + dreg &= ~m_global_regs[SRC_CODE]; + + set_global_register(dst_code, dreg); + SET_Z(dreg == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op35() +void hyperstone_device::op35() // andn { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_andn(decode); + + uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + dreg &= ~m_local_regs[(SRC_CODE + GET_FP) % 64]; + + set_global_register(dst_code, dreg); + SET_Z(dreg == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op36() +void hyperstone_device::op36() // andn { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_andn(decode); + + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + m_local_regs[dst_code] &= ~m_global_regs[SRC_CODE]; + SET_Z(m_local_regs[dst_code] == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op37() +void hyperstone_device::op37() // andn { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_andn(decode); + + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + m_local_regs[dst_code] &= ~m_local_regs[(SRC_CODE + GET_FP) % 64]; + SET_Z(m_local_regs[dst_code] == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op38() +void hyperstone_device::op38() // or global,global { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_or(decode); + + const uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + dreg |= m_global_regs[SRC_CODE]; + + set_global_register(dst_code, dreg); + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op39() +void hyperstone_device::op39() // or global,local { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_or(decode); + + const uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + dreg |= m_local_regs[(SRC_CODE + GET_FP) % 64]; + + set_global_register(dst_code, dreg); + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op3a() +void hyperstone_device::op3a() // or local,global { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_or(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) % 64; + const uint32_t dreg = m_local_regs[dst_code] | m_global_regs[SRC_CODE]; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op3b() +void hyperstone_device::op3b() // or local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_or(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code] | m_local_regs[(SRC_CODE + GET_FP) & 0x3f]; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op3c() +void hyperstone_device::op3c() // xor global,global { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_xor(decode); + + const uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + dreg ^= m_global_regs[SRC_CODE]; + + set_global_register(dst_code, dreg); + SET_Z(dreg == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op3d() +void hyperstone_device::op3d() // xor { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_xor(decode); + + uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + dreg ^= m_local_regs[(SRC_CODE + GET_FP) % 64]; + + set_global_register(dst_code, dreg); + SET_Z(dreg == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op3e() +void hyperstone_device::op3e() // xor { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_xor(decode); + + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + m_local_regs[dst_code] ^= m_global_regs[SRC_CODE]; + SET_Z(m_local_regs[dst_code] == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op3f() +void hyperstone_device::op3f() // xor { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_xor(decode); + + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + m_local_regs[dst_code] ^= m_local_regs[(SRC_CODE + GET_FP) % 64]; + SET_Z(m_local_regs[dst_code] == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } @@ -552,7 +1313,20 @@ void hyperstone_device::op40() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_subc(decode); } @@ -560,7 +1334,20 @@ void hyperstone_device::op41() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_subc(decode); } @@ -568,7 +1355,20 @@ void hyperstone_device::op42() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_subc(decode); } @@ -576,47 +1376,80 @@ void hyperstone_device::op43() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_subc(decode); } -void hyperstone_device::op44() +void hyperstone_device::op44() // not { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_not(decode); + + uint32_t dreg = ~m_global_regs[SRC_CODE]; + set_global_register(DST_CODE, dreg); + SET_Z(dreg == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op45() +void hyperstone_device::op45() // not { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_not(decode); + + uint32_t dreg = ~m_local_regs[(SRC_CODE + GET_FP) % 64]; + set_global_register(DST_CODE, dreg); + SET_Z(dreg == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op46() +void hyperstone_device::op46() // not { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_not(decode); + + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + m_local_regs[dst_code] = ~m_global_regs[SRC_CODE]; + SET_Z(m_local_regs[dst_code] == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op47() +void hyperstone_device::op47() // not { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_not(decode); + + uint32_t dst_code = (DST_CODE + GET_FP) % 64; + m_local_regs[dst_code] = ~m_local_regs[(SRC_CODE + GET_FP) % 64]; + SET_Z(m_local_regs[dst_code] == 0 ? 1 : 0); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op48() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_sub(decode); } @@ -624,7 +1457,15 @@ void hyperstone_device::op49() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_sub(decode); } @@ -632,23 +1473,59 @@ void hyperstone_device::op4a() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_sub(decode); } void hyperstone_device::op4b() { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_sub(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + uint32_t dreg = m_local_regs[dst_code]; + + const uint64_t tmp = (uint64_t)dreg - (uint64_t)sreg; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + if ((tmp ^ dreg) & (dreg ^ sreg) & 0x80000000) + SR |= V_MASK; + + dreg -= sreg; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op4c() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_subs(decode); } @@ -656,7 +1533,15 @@ void hyperstone_device::op4d() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_subs(decode); } @@ -664,7 +1549,15 @@ void hyperstone_device::op4e() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; + hyperstone_subs(decode); } @@ -672,7 +1565,15 @@ void hyperstone_device::op4f() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_subs(decode); } @@ -682,7 +1583,15 @@ void hyperstone_device::op50() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_addc(decode); } @@ -690,7 +1599,15 @@ void hyperstone_device::op51() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_addc(decode); } @@ -698,55 +1615,127 @@ void hyperstone_device::op52() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; + hyperstone_addc(decode); } -void hyperstone_device::op53() +void hyperstone_device::op53() // addc local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_addc(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + uint32_t dreg = m_local_regs[dst_code]; + + const bool old_z = (SR & Z_MASK) != 0; + const uint32_t c = (SR & C_MASK) ? 1 : 0; + const uint64_t tmp = (uint64_t)sreg + (uint64_t)dreg + (uint64_t)c; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + if ((sreg ^ tmp) & (dreg ^ tmp) & (c ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += sreg + c; + + m_local_regs[dst_code] = dreg; + + if (dreg == 0 && old_z) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op54() +void hyperstone_device::hyperstone_and_global_global() { - regs_decode decode; check_delay_PC(); - decode_RR00(decode); - hyperstone_and(decode); + + const uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + dreg &= m_global_regs[SRC_CODE]; + set_global_register(dst_code, dreg); + + if (m_local_regs[dst_code] == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op55() +void hyperstone_device::hyperstone_and_global_local() { - regs_decode decode; check_delay_PC(); - decode_RR01(decode); - hyperstone_and(decode); + + const uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + dreg &= m_local_regs[(SRC_CODE + GET_FP) % 64]; + set_global_register(dst_code, dreg); + + if (m_local_regs[dst_code] == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op56() +void hyperstone_device::hyperstone_and_local_global() { - regs_decode decode; check_delay_PC(); - decode_RR10(decode); - hyperstone_and(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + m_local_regs[dst_code] &= m_global_regs[SRC_CODE]; + + if (m_local_regs[dst_code] == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op57() +void hyperstone_device::hyperstone_and_local_local() { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_and(decode); + + const uint32_t fp = GET_FP; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + m_local_regs[dst_code] &= m_local_regs[(SRC_CODE + fp) & 0x3f]; + + if (m_local_regs[dst_code] == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op58() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_neg(decode); } @@ -754,7 +1743,15 @@ void hyperstone_device::op59() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_neg(decode); } @@ -762,23 +1759,58 @@ void hyperstone_device::op5a() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_neg(decode); } -void hyperstone_device::op5b() +void hyperstone_device::op5b() // neg local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_neg(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + + const uint64_t tmp = -(uint64_t)sreg; + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + if (tmp & 0x100000000L) + SR |= C_MASK; + + if (tmp & sreg & 0x80000000) + SR |= V_MASK; + + const uint32_t dreg = -sreg; + m_local_regs[(DST_CODE + fp) & 0x3f] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op5c() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_negs(decode); } @@ -786,7 +1818,15 @@ void hyperstone_device::op5d() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + hyperstone_negs(decode); } @@ -794,7 +1834,15 @@ void hyperstone_device::op5e() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_negs(decode); } @@ -802,50 +1850,121 @@ void hyperstone_device::op5f() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + hyperstone_negs(decode); } -void hyperstone_device::op60() +void hyperstone_device::hyperstone_cmpi_global_simm() // cmpi global,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_cmpi(decode); + + const uint32_t imm = immediate_values[m_op & 0x0f]; + const uint32_t dreg = m_global_regs[DST_CODE]; + + SR &= ~(V_MASK | Z_MASK | N_MASK | C_MASK); + + uint64_t tmp = (uint64_t)dreg - (uint64_t)imm; + if ((tmp ^ dreg) & (dreg ^ imm) & 0x80000000) + SR |= V_MASK; + + if (dreg == imm) + SR |= Z_MASK; + + if ((int32_t)dreg < (int32_t)imm) + SR |= N_MASK; + + if (dreg < imm) + SR |= C_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op61() +void hyperstone_device::hyperstone_cmpi_global_limm() // cmpi global,long imm { - regs_decode decode; - decode_immediate_s(decode); + const uint32_t imm = decode_immediate_s(); + check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_cmpi(decode); + + const uint32_t dreg = m_global_regs[DST_CODE]; + + SR &= ~(V_MASK | Z_MASK | N_MASK | C_MASK); + + uint64_t tmp = (uint64_t)dreg - (uint64_t)imm; + if ((tmp ^ dreg) & (dreg ^ imm) & 0x80000000) + SR |= V_MASK; + + if (dreg == imm) + SR |= Z_MASK; + + if ((int32_t)dreg < (int32_t)imm) + SR |= N_MASK; + + if (dreg < imm) + SR |= C_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op62() +void hyperstone_device::hyperstone_cmpi_local_simm() // cmpi local,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_cmpi(decode); + + const uint32_t imm = immediate_values[m_op & 0x0f]; + const uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) & 0x3f]; + + SR &= ~(V_MASK | Z_MASK | N_MASK | C_MASK); + + uint64_t tmp = (uint64_t)dreg - (uint64_t)imm; + if ((tmp ^ dreg) & (dreg ^ imm) & 0x80000000) + SR |= V_MASK; + + if (dreg == imm) + SR |= Z_MASK; + + if ((int32_t)dreg < (int32_t)imm) + SR |= N_MASK; + + if (dreg < imm) + SR |= C_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op63() +void hyperstone_device::hyperstone_cmpi_local_limm() // cmpi local,long imm { - regs_decode decode; - decode_immediate_s(decode); + uint32_t imm = decode_immediate_s(); + check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_cmpi(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code]; + + SR &= ~(V_MASK | Z_MASK | N_MASK | C_MASK); + + uint64_t tmp = (uint64_t)dreg - (uint64_t)imm; + if ((tmp ^ dreg) & (dreg ^ imm) & 0x80000000) + SR |= V_MASK; + + if (dreg == imm) + SR |= Z_MASK; + + if ((int32_t)dreg < (int32_t)imm) + SR |= N_MASK; + + if (dreg < imm) + SR |= C_MASK; + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op64() @@ -861,71 +1980,164 @@ void hyperstone_device::op64() void hyperstone_device::op65() { regs_decode decode; - decode_immediate_s(decode); + DECODE_IMMEDIATE_S(decode); check_delay_PC(); decode.dst = DST_CODE; decode_dest(decode, GET_H); hyperstone_movi(decode); } -void hyperstone_device::op66() +void hyperstone_device::op66() // movi local,short imm +{ + check_delay_PC(); + + const uint32_t imm = immediate_values[OP & 0x0f]; + m_local_regs[(DST_CODE + GET_FP) & 0x3f] = imm; + + SR &= ~(Z_MASK | N_MASK); + if (imm == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(imm); + +#if MISSIONCRAFT_FLAGS + SR &= ~V_MASK; // or V undefined ? +#endif + + m_icount -= m_clock_cycles_1; +} + +void hyperstone_device::op67() // movi local,long imm +{ + const uint32_t extra_u = decode_immediate_s(); + check_delay_PC(); + + m_local_regs[(DST_CODE + GET_FP) & 0x3f] = extra_u; + + SR &= ~(Z_MASK | N_MASK); + if (extra_u == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(extra_u); + +#if MISSIONCRAFT_FLAGS + SR &= ~V_MASK; // or V undefined ? +#endif + + m_icount -= m_clock_cycles_1; +} + +void hyperstone_device::op68() // addi global,short imm { regs_decode decode; decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_movi(decode); -} -void hyperstone_device::op67() -{ - regs_decode decode; - decode_immediate_s(decode); - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_movi(decode); -} + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; -void hyperstone_device::op68() -{ - regs_decode decode; - decode_immediate_u(decode); - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); hyperstone_addi(decode); } -void hyperstone_device::op69() +void hyperstone_device::op69() // addi global,long imm { - regs_decode decode; - decode_immediate_s(decode); + const uint32_t extra_u = decode_immediate_s(); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_addi(decode); + + const uint32_t dst_code = DST_CODE; + uint32_t dreg = m_global_regs[dst_code]; + + uint32_t imm; + if (N_VALUE) + { + imm = extra_u; + } + else + { + imm = GET_C & (((SR & Z_MASK) ? 0 : 1) | (dreg & 0x01)); + } + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + const uint64_t tmp = (uint64_t)imm + (uint64_t)dreg; + if (tmp & 0x100000000L) + SR |= C_MASK; + if ((imm ^ tmp) & (dreg ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += imm; + set_global_register(dst_code, dreg); + + if (dst_code == 0) + SR &= ~M_MASK; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op6a() +void hyperstone_device::op6a() // addi local,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_addi(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + + uint32_t dreg = m_local_regs[dst_code]; + + uint32_t imm; + if (N_VALUE) + imm = immediate_values[m_op & 0x0f]; + else + imm = GET_C & (((SR & Z_MASK) ? 0 : 1) | (dreg & 0x01)); + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + const uint64_t tmp = (uint64_t)imm + (uint64_t)dreg; + if (tmp & 0x100000000L) + SR |= C_MASK; + if ((imm ^ tmp) & (dreg ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += imm; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op6b() +void hyperstone_device::op6b() // addi local,long imm { - regs_decode decode; - decode_immediate_s(decode); + uint32_t imm = decode_immediate_s(); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_addi(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + uint32_t dreg = m_local_regs[dst_code]; + + if (!N_VALUE) + imm = GET_C & (((SR & Z_MASK) ? 0 : 1) | (dreg & 0x01)); + + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + const uint64_t tmp = (uint64_t)imm + (uint64_t)dreg; + if (tmp & 0x100000000L) + SR |= C_MASK; + if ((imm ^ tmp) & (dreg ^ tmp) & 0x80000000) + SR |= V_MASK; + + dreg += imm; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op6c() @@ -934,17 +2146,27 @@ void hyperstone_device::op6c() decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_addsi(decode); } void hyperstone_device::op6d() { regs_decode decode; - decode_immediate_s(decode); + DECODE_IMMEDIATE_S(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_addsi(decode); } @@ -954,17 +2176,25 @@ void hyperstone_device::op6e() decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_addsi(decode); } void hyperstone_device::op6f() { regs_decode decode; - decode_immediate_s(decode); + DECODE_IMMEDIATE_S(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_addsi(decode); } @@ -976,38 +2206,124 @@ void hyperstone_device::op70() decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_cmpbi(decode); } -void hyperstone_device::op71() +void hyperstone_device::op71() // cmpbi global,long imm { - regs_decode decode; - decode_immediate_s(decode); - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_cmpbi(decode); + const uint32_t dreg = m_global_regs[DST_CODE]; + + const uint32_t n = N_VALUE; + if (n) + { + uint32_t imm; + if (n == 31) + { + ignore_immediate_s(); + check_delay_PC(); + imm = 0x7fffffff; // bit 31 = 0, others = 1 + } + else + { + imm = decode_immediate_s(); + check_delay_PC(); + } + + if (dreg & imm) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + } + else + { + ignore_immediate_s(); + check_delay_PC(); + if ((dreg & 0xff000000) == 0 || (dreg & 0x00ff0000) == 0 || (dreg & 0x0000ff00) == 0 || (dreg & 0x000000ff) == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + } + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op72() +void hyperstone_device::op72() // cmpbi local,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_cmpbi(decode); + + const uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) & 0x3f]; + + const uint32_t n = N_VALUE; + if (n) + { + uint32_t imm; + if (n == 31) + { + imm = 0x7fffffff; // bit 31 = 0, others = 1 + } + else + { + imm = immediate_values[m_op & 0x0f]; + } + + if (dreg & imm) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + } + else + { + if ((dreg & 0xff000000) == 0 || (dreg & 0x00ff0000) == 0 || (dreg & 0x0000ff00) == 0 || (dreg & 0x000000ff) == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + } + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op73() +void hyperstone_device::op73() // cmpbi local,long imm { - regs_decode decode; - decode_immediate_s(decode); - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_cmpbi(decode); + const uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) & 0x3f]; + + const uint32_t n = N_VALUE; + if (n) + { + uint32_t imm; + if (n == 31) + { + ignore_immediate_s(); + check_delay_PC(); + imm = 0x7fffffff; // bit 31 = 0, others = 1 + } + else + { + imm = decode_immediate_s(); + check_delay_PC(); + } + + if (dreg & imm) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + } + else + { + ignore_immediate_s(); + check_delay_PC(); + if ((dreg & 0xff000000) == 0 || (dreg & 0x00ff0000) == 0 || (dreg & 0x0000ff00) == 0 || (dreg & 0x000000ff) == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op74() @@ -1016,78 +2332,148 @@ void hyperstone_device::op74() decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_andni(decode); } -void hyperstone_device::op75() +void hyperstone_device::op75() // andni global,long imm { - regs_decode decode; - decode_immediate_s(decode); + const uint32_t extra_u = decode_immediate_s(); + check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_andni(decode); + + uint32_t imm; + if (N_VALUE == 31) + imm = 0x7fffffff; // bit 31 = 0, others = 1 + else + imm = extra_u; + + const uint32_t dst_code = DST_CODE; + const uint32_t dreg = m_global_regs[dst_code] & ~imm; + set_global_register(dst_code, dreg); + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op76() +void hyperstone_device::op76() // andni local,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_andni(decode); + + uint32_t imm; + if (N_VALUE == 31) + imm = 0x7fffffff; // bit 31 = 0, others = 1 + else + imm = immediate_values[m_op & 0x0f]; + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code] & ~imm; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op77() +void hyperstone_device::op77() // andni local,long imm { - regs_decode decode; - decode_immediate_s(decode); + const uint32_t extra_u = decode_immediate_s(); + check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_andni(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + + uint32_t imm; + if (N_VALUE == 31) + imm = 0x7fffffff; // bit 31 = 0, others = 1 + else + imm = extra_u; + + const uint32_t dreg = m_local_regs[dst_code] & ~imm; + m_local_regs[dst_code] = dreg; + + if (dreg == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op78() +void hyperstone_device::hyperstone_ori_global_simm() // ori global,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_ori(decode); + + const uint32_t dst_code = DST_CODE; + const uint32_t dreg = m_global_regs[dst_code] | immediate_values[m_op & 0x0f]; + set_global_register(dst_code, dreg); + + if (dreg) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op79() +void hyperstone_device::hyperstone_ori_global_limm() // ori global,long imm { - regs_decode decode; - decode_immediate_s(decode); + uint32_t extra_u = decode_immediate_s(); + check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_ori(decode); + + const uint32_t dst_code = DST_CODE; + const uint32_t dreg = m_global_regs[dst_code] | extra_u; + set_global_register(dst_code, dreg); + + if (dreg) + SR &= ~Z_MASK; + else + SR |= Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op7a() +void hyperstone_device::hyperstone_ori_local_simm() // ori local,short imm { - regs_decode decode; - decode_immediate_u(decode); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_ori(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + m_local_regs[dst_code] |= immediate_values[m_op & 0x0f]; + + if (m_local_regs[dst_code] == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op7b() +void hyperstone_device::hyperstone_ori_local_limm() // ori local,long imm { - regs_decode decode; - decode_immediate_s(decode); + const uint32_t extra_u = decode_immediate_s(); check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_ori(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + m_local_regs[dst_code] |= extra_u; + + if (m_local_regs[dst_code] == 0) + SR |= Z_MASK; + else + SR &= ~Z_MASK; + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op7c() @@ -1096,17 +2482,26 @@ void hyperstone_device::op7c() decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_xori(decode); } void hyperstone_device::op7d() { regs_decode decode; - decode_immediate_s(decode); + DECODE_IMMEDIATE_S(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_xori(decode); } @@ -1116,29 +2511,63 @@ void hyperstone_device::op7e() decode_immediate_u(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_xori(decode); } void hyperstone_device::op7f() { regs_decode decode; - decode_immediate_s(decode); + DECODE_IMMEDIATE_S(decode); check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_xori(decode); } -void hyperstone_device::op80() +void hyperstone_device::op80() // shrdi local,imm { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shrdi(decode); + + const uint32_t fp = GET_FP; + const uint32_t code = DST_CODE; + const uint32_t dst_code = (code + fp) & 0x3f; + const uint32_t dstf_code = (code + 1 + fp) & 0x3f; + uint32_t high_order = m_local_regs[dst_code]; + const uint32_t low_order = m_local_regs[dstf_code]; + + uint64_t val = concat_64(high_order, low_order); + + SR &= ~(C_MASK | Z_MASK | N_MASK); + + const uint32_t n = N_VALUE; + if (n) + { + SR |= (val >> (n - 1)) & 1; + + val >>= n; + } + + high_order = extract_64hi(val); + + m_local_regs[dst_code] = high_order; + m_local_regs[dstf_code] = extract_64lo(val); + + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(high_order); + + m_icount -= m_clock_cycles_2; } void hyperstone_device::op81() @@ -1146,92 +2575,181 @@ void hyperstone_device::op81() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_shrdi(decode); } -void hyperstone_device::op82() +void hyperstone_device::hyperstone_shrd() { - regs_decode decode; check_delay_PC(); - decode_LL(decode); - hyperstone_shrd(decode); + + const uint32_t fp = GET_FP; + const uint32_t src_code = (SRC_CODE + fp) & 0x3f; + const uint32_t d_code = DST_CODE; + const uint32_t dst_code = (d_code + fp) & 0x3f; + const uint32_t dstf_code = (d_code + 1 + fp) & 0x3f; + + if (src_code == dst_code || src_code == dstf_code) + { + m_icount -= m_clock_cycles_2; + return; + } + + uint64_t val = concat_64(m_local_regs[dst_code], m_local_regs[dstf_code]); + + SR &= ~(C_MASK | Z_MASK | N_MASK); + + const uint32_t n = m_local_regs[src_code] & 0x1f; + + if (n) + { + SR |= (val >> (n - 1)) & 1; + val >>= n; + } + + m_local_regs[dst_code] = (uint32_t)(val >> 32); + m_local_regs[dstf_code] = (uint32_t)val; + + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(m_local_regs[dst_code]); + + m_icount -= m_clock_cycles_2; } -void hyperstone_device::op83() +void hyperstone_device::op83() // shr local,local { - regs_decode decode; check_delay_PC(); - decode_LL(decode); - hyperstone_shr(decode); + + const uint32_t fp = GET_FP; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + const uint32_t n = m_local_regs[(SRC_CODE + fp) & 0x3f] & 0x1f; + uint32_t dreg = m_local_regs[dst_code]; + + SR &= ~(C_MASK | Z_MASK | N_MASK); + + if (n && (dreg & (1 << (n - 1)))) + SR |= C_MASK; + + dreg >>= n; + + m_local_regs[dst_code] = dreg; + if (dreg == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(dreg); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op84() +void hyperstone_device::hyperstone_sard() { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_sardi(decode); -} -void hyperstone_device::op85() -{ - regs_decode decode; - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_sardi(decode); -} + const uint32_t fp = GET_FP; + const uint32_t src_code = (SRC_CODE + fp) & 0x3f; + const uint32_t d_code = DST_CODE; + const uint32_t dst_code = (d_code + fp) & 0x3f; + const uint32_t dstf_code = (d_code + 1 + fp) & 0x3f; -void hyperstone_device::op86() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_sard(decode); + if (src_code == dst_code || src_code == dstf_code) + { + m_icount -= m_clock_cycles_2; + return; + } + + uint64_t val = concat_64(m_local_regs[dst_code], m_local_regs[dstf_code]); + + SR &= ~(C_MASK | Z_MASK | N_MASK); + + const uint32_t n = m_local_regs[src_code] & 0x1f; + if (n) + { + SR |= (val >> (n - 1)) & 1; + + uint32_t sign_bit = val >> 63; + + val >>= n; + + if (sign_bit) + { + val |= 0xffffffff00000000L << (32 - n); + } + } + + m_local_regs[dst_code] = (uint32_t)(val >> 32); + m_local_regs[dstf_code] = (uint32_t)val; + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(m_local_regs[dst_code]); + + m_icount -= m_clock_cycles_2; } void hyperstone_device::op87() { regs_decode decode; check_delay_PC(); - decode_LL(decode); + + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = 0; + hyperstone_sar(decode); } -void hyperstone_device::op88() +void hyperstone_device::hyperstone_shldi() { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shldi(decode); -} -void hyperstone_device::op89() -{ - regs_decode decode; - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shldi(decode); -} + const uint32_t fp = GET_FP; + const uint32_t code = DST_CODE; + const uint32_t dst_code = (code + fp) & 0x3f; + const uint32_t dstf_code = (code + 1 + fp) & 0x3f; + uint32_t high_order = m_local_regs[dst_code]; + uint32_t low_order = m_local_regs[dstf_code]; -void hyperstone_device::op8a() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_shld(decode); -} + uint64_t val = concat_64(high_order, low_order); -void hyperstone_device::op8b() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_shl(decode); + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + + const uint32_t n = N_VALUE; + + if (n && ((val << (n - 1)) & 0x8000000000000000U)) + SR |= C_MASK; + + const uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff; + const uint32_t tmp = high_order << n; + + if (((high_order & mask) && (!(tmp & 0x80000000))) || (((high_order & mask) ^ mask) && (tmp & 0x80000000))) + SR |= V_MASK; + + val <<= n; + + high_order = extract_64hi(val); + + m_local_regs[dst_code] = high_order; + m_local_regs[dstf_code] = extract_64lo(val); + + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(high_order); + + m_icount -= m_clock_cycles_2; } void hyperstone_device::op8c() @@ -1244,20 +2762,44 @@ void hyperstone_device::op8d() DEBUG_PRINTF(("Executed Reserved opcode. PC = %08X OP = %04X\n", PC, OP)); } -void hyperstone_device::op8e() +void hyperstone_device::op8f() // rol local,local { - regs_decode decode; check_delay_PC(); - decode_LL(decode); - hyperstone_testlz(decode); -} -void hyperstone_device::op8f() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_rol(decode); + const uint32_t fp = GET_FP; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + + uint32_t n = m_local_regs[(SRC_CODE + fp) & 0x3f] & 0x1f; + uint32_t val = m_local_regs[dst_code]; + +#ifdef MISSIONCRAFT_FLAGS + const uint32_t base = val; + const uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff; +#endif + + while (n > 0) + { + val = (val << 1) | ((val & 0x80000000) >> 31); + n--; + } + +#ifdef MISSIONCRAFT_FLAGS + SR &= ~(V_MASK | Z_MASK | C_MASK); + if (((base & mask) && (!(val & 0x80000000))) || (((base & mask) ^ mask) && (val & 0x80000000))) + SET_V(1); + else + SET_V(0); +#else + SR &= ~(Z_MASK | C_MASK); +#endif + + m_local_regs[dst_code] = val; + + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(val); + + m_icount -= m_clock_cycles_1; } @@ -1267,35 +2809,342 @@ void hyperstone_device::op90() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_ldxx1(decode); } -void hyperstone_device::op91() +void hyperstone_device::op91() // ldxx1 global,local { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR01(decode); - hyperstone_ldxx1(decode); + + const uint32_t src_code = (SRC_CODE + GET_FP) & 0x3f; + + if (DST_CODE == SR_REGISTER) + { + switch (sub_type) + { + case 0x0000: // LDBS.A + m_local_regs[src_code] = (int32_t)(int8_t)READ_B(extra_s); + break; + + case 0x1000: // LDBU.A + m_local_regs[src_code] = READ_B(extra_s); + break; + + case 0x2000: + if (extra_s & 1) // LDHS.A + m_local_regs[src_code] = (int32_t)(int16_t)READ_HW(extra_s); + else // LDHU.A + m_local_regs[src_code] = READ_HW(extra_s); + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.A + m_local_regs[src_code] = READ_W(extra_s); + break; + case 1: // LDD.A + m_local_regs[src_code] = READ_W(extra_s); + m_local_regs[(src_code + 1) & 0x3f] = READ_W(extra_s + 4); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // LDW.IOA + m_local_regs[src_code] = IO_READ_W(extra_s); + break; + case 3: // LDD.IOA + m_local_regs[src_code] = IO_READ_W(extra_s); + m_local_regs[(src_code + 1) & 0x3f] = IO_READ_W((extra_s & ~3) + 4); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + } + else + { + const uint32_t dreg = m_global_regs[DST_CODE]; + switch (sub_type) + { + case 0x0000: // LDBS.D + m_local_regs[src_code] = (int32_t)(int8_t)READ_B(dreg + extra_s); + break; + + case 0x1000: // LDBU.D + m_local_regs[src_code] = READ_B(dreg + extra_s); + break; + + case 0x2000: + if (extra_s & 1) + m_local_regs[src_code] = (int32_t)(int16_t)READ_HW(dreg + (extra_s & ~1)); + else + m_local_regs[src_code] = READ_HW(dreg + (extra_s & ~1)); + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.D + m_local_regs[src_code] = READ_W(dreg + (extra_s & ~1)); + break; + case 1: // LDD.D + m_local_regs[src_code] = READ_W(dreg + (extra_s & ~1)); + m_local_regs[(src_code + 1) & 0x3f] = READ_W(dreg + (extra_s & ~1) + 4); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // LDW.IOD + m_local_regs[src_code] = IO_READ_W(dreg + (extra_s & ~3)); + break; + case 3: // LDD.IOD + m_local_regs[src_code] = IO_READ_W(dreg + (extra_s & ~3)); + m_local_regs[(src_code + 1) & 0x3f] = IO_READ_W(dreg + (extra_s & ~3) + 4); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op92() { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR10(decode); - hyperstone_ldxx1(decode); + + if (DST_CODE == SR_REGISTER) + { + switch (sub_type) + { + case 0x0000: // LDBS.A + set_global_register(SRC_CODE, (int32_t)(int8_t)READ_B(extra_s)); + break; + + case 0x1000: // LDBU.A + set_global_register(SRC_CODE, READ_B(extra_s)); + break; + + case 0x2000: + if (extra_s & 1) // LDHS.A + set_global_register(SRC_CODE, (int32_t)(int16_t)READ_HW(extra_s)); + else // LDHU.A + set_global_register(SRC_CODE, READ_HW(extra_s)); + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.A + set_global_register(SRC_CODE, READ_W(extra_s)); + break; + case 1: // LDD.A + set_global_register(SRC_CODE, READ_W(extra_s)); + set_global_register(SRC_CODE + 1, READ_W(extra_s + 4)); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // LDW.IOA + set_global_register(SRC_CODE, IO_READ_W(extra_s)); + break; + case 3: // LDD.IOA + set_global_register(SRC_CODE, IO_READ_W(extra_s)); + set_global_register(SRC_CODE + 1, IO_READ_W((extra_s & ~3) + 4)); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + } + else + { + const uint32_t dreg = m_local_regs[(DST_CODE + GET_FP) & 0x3f]; + switch (sub_type) + { + case 0x0000: // LDBS.D + set_global_register(SRC_CODE, (int32_t)(int8_t)READ_B(dreg + extra_s)); + break; + + case 0x1000: // LDBU.D + set_global_register(SRC_CODE, READ_B(dreg + extra_s)); + break; + + case 0x2000: + if (extra_s & 1) + set_global_register(SRC_CODE, (int32_t)(int16_t)READ_HW(dreg + (extra_s & ~1))); + else + set_global_register(SRC_CODE, READ_HW(dreg + (extra_s & ~1))); + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.D + set_global_register(SRC_CODE, READ_W(dreg + (extra_s & ~1))); + break; + case 1: // LDD.D + set_global_register(SRC_CODE, READ_W(dreg + (extra_s & ~1))); + set_global_register(SRC_CODE + 1, READ_W(dreg + (extra_s & ~1) + 4)); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // LDW.IOD + set_global_register(SRC_CODE, IO_READ_W(dreg + (extra_s & ~3))); + break; + case 3: // LDD.IOD + set_global_register(SRC_CODE, IO_READ_W(dreg + (extra_s & ~3))); + set_global_register(SRC_CODE + 1, IO_READ_W(dreg + (extra_s & ~3) + 4)); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op93() { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR11(decode); - hyperstone_ldxx1(decode); + + const uint32_t fp = GET_FP; + const uint32_t src_code = (SRC_CODE + fp) & 0x3f; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code]; + + switch (sub_type) + { + case 0x0000: // LDBS.D + m_local_regs[src_code] = (int32_t)(int8_t)READ_B(dreg + extra_s); + break; + + case 0x1000: // LDBU.D + m_local_regs[src_code] = READ_B(dreg + extra_s); + break; + + case 0x2000: + if (extra_s & 1) + m_local_regs[src_code] = (int32_t)(int16_t)READ_HW(dreg + (extra_s & ~1)); + else + m_local_regs[src_code] = READ_HW(dreg + (extra_s & ~1)); + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.D + m_local_regs[src_code] = READ_W(dreg + (extra_s & ~1)); + break; + case 1: // LDD.D + m_local_regs[src_code] = READ_W(dreg + (extra_s & ~1)); + m_local_regs[(src_code + 1) & 0x3f] = READ_W(dreg + (extra_s & ~1) + 4); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // LDW.IOD + m_local_regs[src_code] = IO_READ_W(dreg + (extra_s & ~3)); + break; + case 3: // LDD.IOD + m_local_regs[src_code] = IO_READ_W(dreg + (extra_s & ~3)); + m_local_regs[(src_code + 1) & 0x3f] = IO_READ_W(dreg + (extra_s & ~3) + 4); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op94() @@ -1303,17 +3152,118 @@ void hyperstone_device::op94() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_ldxx2(decode); } void hyperstone_device::op95() { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR01(decode); - hyperstone_ldxx2(decode); + + const uint32_t fp = GET_FP; + const uint32_t src_code = (SRC_CODE + fp) & 0x3f; + const uint32_t srcf_code = (SRC_CODE + fp + 1) & 0x3f; + + const uint32_t dst_code = DST_CODE; + const uint32_t dreg = m_global_regs[dst_code]; + + if (dst_code < 2) + { + DEBUG_PRINTF(("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC)); + } + else + { + switch (sub_type) + { + case 0x0000: // LDBS.N + m_local_regs[src_code] = (int32_t)(int8_t)READ_B(dreg); + set_global_register(dst_code, dreg + extra_s); + break; + + case 0x1000: // LDBU.N + m_local_regs[src_code] = READ_B(dreg); + set_global_register(dst_code, dreg + extra_s); + break; + + case 0x2000: + if (extra_s & 1) // LDHS.N + m_local_regs[src_code] = (int32_t)(int16_t)READ_HW(dreg); + else // LDHU.N + m_local_regs[src_code] = READ_HW(dreg); + set_global_register(dst_code, dreg + (extra_s & ~1)); + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.N + m_local_regs[src_code] = READ_W(dreg); + set_global_register(dst_code, dreg + (extra_s & ~1)); + break; + case 1: // LDD.N + m_local_regs[src_code] = READ_W(dreg); + m_local_regs[srcf_code] = READ_W(dreg + 4); + set_global_register(dst_code, dreg + (extra_s & ~1)); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // Reserved + DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC)); + break; + case 3: // LDW.S + if (dreg < SP) + m_local_regs[src_code] = READ_W(dreg); + else + m_local_regs[src_code] = m_local_regs[(dreg & 0xfc) >> 2]; + set_global_register(dst_code, dreg + (extra_s & ~3)); + m_icount -= m_clock_cycles_2; // extra cycles + break; + } + break; + } + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op96() @@ -1321,17 +3271,110 @@ void hyperstone_device::op96() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_ldxx2(decode); } void hyperstone_device::op97() { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR11(decode); - hyperstone_ldxx2(decode); + + const uint32_t fp = GET_FP; + const uint32_t src_code = (SRC_CODE + fp) & 0x3f; + const uint32_t srcf_code = (SRC_CODE + fp + 1) & 0x3f; + + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code]; + + switch (sub_type) + { + case 0x0000: // LDBS.N + m_local_regs[src_code] = (int32_t)(int8_t)READ_B(dreg); + m_local_regs[dst_code] += extra_s; + break; + + case 0x1000: // LDBU.N + m_local_regs[src_code] = READ_B(dreg); + m_local_regs[dst_code] += extra_s; + break; + + case 0x2000: + if (extra_s & 1) // LDHS.N + m_local_regs[src_code] = (int32_t)(int16_t)READ_HW(dreg); + else // LDHU.N + m_local_regs[src_code] = READ_HW(dreg); + m_local_regs[dst_code] += extra_s & ~1; + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // LDW.N + m_local_regs[src_code] = READ_W(dreg); + m_local_regs[dst_code] += extra_s & ~1; + break; + case 1: // LDD.N + m_local_regs[src_code] = READ_W(dreg); + m_local_regs[srcf_code] = READ_W(dreg + 4); + m_local_regs[dst_code] += extra_s & ~1; + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // Reserved + DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC)); + break; + case 3: // LDW.S + if (dreg < SP) + m_local_regs[src_code] = READ_W(dreg); + else + m_local_regs[src_code] = m_local_regs[(dreg & 0xfc) >> 2]; + m_local_regs[dst_code] += extra_s & ~3; + m_icount -= m_clock_cycles_2; // extra cycles + break; + } + break; + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::op98() @@ -1339,35 +3382,294 @@ void hyperstone_device::op98() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_stxx1(decode); } -void hyperstone_device::op99() +void hyperstone_device::op99() // stxx1 global,local { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR01(decode); - hyperstone_stxx1(decode); + + const uint32_t dst_code = DST_CODE; + const uint32_t src_code = (SRC_CODE + GET_FP) & 0x3f; + const uint32_t sreg = m_local_regs[src_code]; + + if (dst_code == SR_REGISTER) + { + switch (sub_type) + { + case 0x0000: // STBS.A + WRITE_B(extra_s, (uint8_t)sreg); + // TODO: missing trap on range error + break; + + case 0x1000: // STBU.A + WRITE_B(extra_s, (uint8_t)sreg); + break; + + case 0x2000: // STHS.A & STHU.A + WRITE_HW(extra_s, (uint16_t)sreg); + // TODO: missing trap on range error with STHS.A + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // STW.A + WRITE_W(extra_s & ~1, sreg); + break; + case 1: // STD.A + WRITE_W(extra_s & ~1, sreg); + WRITE_W((extra_s & ~1) + 4, m_local_regs[(src_code + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // STW.IOA + IO_WRITE_W(extra_s & ~3, sreg); + break; + case 3: // STD.IOA + IO_WRITE_W(extra_s & ~3, sreg); + IO_WRITE_W((extra_s & ~3) + 4, m_local_regs[(src_code + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + } + else + { + const uint32_t dreg = m_global_regs[dst_code]; + switch (sub_type) + { + case 0x0000: // STBS.D + WRITE_B(dreg + extra_s, (uint8_t)sreg); + // TODO: missing trap on range error + break; + + case 0x1000: // STBU.D + WRITE_B(dreg + extra_s, (uint8_t)sreg); + break; + + case 0x2000: // STHS.D & STHU.D + WRITE_HW(dreg + (extra_s & ~1), (uint16_t)sreg); + // TODO: Missing trap on range error for STHS.D + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // STW.D + WRITE_W(dreg + (extra_s & ~1), sreg); + break; + case 1: // STD.D + WRITE_W(dreg + (extra_s & ~1), sreg); + WRITE_W(dreg + (extra_s & ~1) + 4, m_local_regs[(src_code + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // STW.IOD + IO_WRITE_W(dreg + (extra_s & ~3), sreg); + break; + case 3: // STD.IOD + IO_WRITE_W(dreg + (extra_s & ~3), sreg); + IO_WRITE_W(dreg + (extra_s & ~3) + 4, m_local_regs[(src_code + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } + } + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::op9a() +void hyperstone_device::op9a() // stxx1 local,global { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR10(decode); - hyperstone_stxx1(decode); + + const uint32_t fp = GET_FP; + const uint32_t src_code = SRC_CODE; + const uint32_t sreg = ((src_code == SR_REGISTER) ? 0 : m_global_regs[src_code]); + const uint32_t dreg = m_local_regs[(DST_CODE + fp) & 0x3f]; + + switch (sub_type) + { + case 0x0000: // STBS.D + /* TODO: missing trap on range error */ + WRITE_B(dreg + extra_s, (uint8_t)sreg); + break; + + case 0x1000: // STBU.D + WRITE_B(dreg + extra_s, (uint8_t)sreg); + break; + + case 0x2000: // STHS.D, STHU.D + WRITE_HW(dreg + (extra_s & ~1), (uint16_t)sreg); + // missing trap on range error with STHS.D + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // STW.D + WRITE_W(dreg + (extra_s & ~1), sreg); + break; + case 1: // STD.D + WRITE_W(dreg + (extra_s & ~1), sreg); + WRITE_W(dreg + (extra_s & ~1) + 4, src_code == SR_REGISTER ? 0 : m_global_regs[src_code + 1]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // STW.IOD + IO_WRITE_W(dreg + (extra_s & ~3), sreg); + break; + case 3: // STD.IOD + IO_WRITE_W(dreg + (extra_s & ~3), sreg); + IO_WRITE_W(dreg + (extra_s & ~3) + 4, src_code == SR_REGISTER ? 0 : m_global_regs[src_code + 1]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } } -void hyperstone_device::op9b() +void hyperstone_device::op9b() // stxx1 local,local { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR11(decode); - hyperstone_stxx1(decode); + + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dreg = m_local_regs[(DST_CODE + fp) & 0x3f]; + + switch (sub_type) + { + case 0x0000: // STBS.D + /* TODO: missing trap on range error */ + WRITE_B(dreg + extra_s, (uint8_t)sreg); + break; + + case 0x1000: // STBU.D + WRITE_B(dreg + extra_s, (uint8_t)sreg); + break; + + case 0x2000: // STHS.D, STHU.D + WRITE_HW(dreg + (extra_s & ~1), (uint16_t)sreg); + // missing trap on range error with STHS.D + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // STW.D + WRITE_W(dreg + (extra_s & ~1), sreg); + break; + case 1: // STD.D + WRITE_W(dreg + (extra_s & ~1), sreg); + WRITE_W(dreg + (extra_s & ~1) + 4, m_local_regs[(SRC_CODE + fp + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // STW.IOD + IO_WRITE_W(dreg + (extra_s & ~3), sreg); + break; + case 3: // STD.IOD + IO_WRITE_W(dreg + (extra_s & ~3), sreg); + IO_WRITE_W(dreg + (extra_s & ~3) + 4, m_local_regs[(SRC_CODE + fp + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + } + break; + } } void hyperstone_device::op9c() @@ -1375,7 +3677,20 @@ void hyperstone_device::op9c() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_stxx2(decode); } @@ -1384,7 +3699,20 @@ void hyperstone_device::op9d() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_stxx2(decode); } @@ -1393,17 +3721,109 @@ void hyperstone_device::op9e() regs_decode decode; decode_dis(decode); check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_stxx2(decode); } void hyperstone_device::op9f() { - regs_decode decode; - decode_dis(decode); + uint16_t next_1 = READ_OP(PC); + PC += 2; + + const uint16_t sub_type = next_1 & 0x3000; + + uint32_t extra_s; + if (next_1 & 0x8000) + { + const uint16_t next_2 = READ_OP(PC); + PC += 2; + m_instruction_length = (3<<19); + + extra_s = next_2; + extra_s |= ((next_1 & 0xfff) << 16); + + if (next_1 & 0x4000) + extra_s |= 0xf0000000; + } + else + { + m_instruction_length = (2<<19); + extra_s = next_1 & 0xfff; + + if (next_1 & 0x4000) + extra_s |= 0xfffff000; + } + check_delay_PC(); - decode_RR11(decode); - hyperstone_stxx2(decode); + const uint32_t fp = GET_FP; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code]; + + switch (sub_type) + { + case 0x0000: // STBS.N + /* TODO: missing trap on range error */ + WRITE_B(dreg, (uint8_t)sreg); + m_local_regs[dst_code] += extra_s; + break; + + case 0x1000: // STBU.N + WRITE_B(dreg, (uint8_t)sreg); + m_local_regs[dst_code] += extra_s; + break; + + case 0x2000: + WRITE_HW(dreg, (uint16_t)sreg); + m_local_regs[dst_code] += extra_s & ~1; + // Missing trap on range error with STHS.N + break; + + case 0x3000: + switch (extra_s & 3) + { + case 0: // STW.N + WRITE_W(dreg, sreg); + m_local_regs[dst_code] += extra_s & ~1; + break; + case 1: // STD.N + WRITE_W(dreg, sreg); + m_local_regs[dst_code] += extra_s & ~1; + if (((SRC_CODE + 1) & 0x3f) == DST_CODE) + WRITE_W(dreg + 4, m_local_regs[(SRC_CODE + fp + 1) & 0x3f] + (extra_s & ~1)); // because DREG == SREGF and DREG has been incremented + else + WRITE_W(dreg + 4, m_local_regs[(SRC_CODE + fp + 1) & 0x3f]); + m_icount -= m_clock_cycles_1; // extra cycle + break; + case 2: // Reserved + DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC)); + break; + case 3: // STW.S + if(dreg < SP) + WRITE_W(dreg, sreg); + else + m_local_regs[(dreg & 0xfc) >> 2] = sreg; + + m_local_regs[dst_code] += extra_s & ~3; + m_icount -= m_clock_cycles_2; // extra cycles + break; + } + } + + m_icount -= m_clock_cycles_1; } @@ -1413,7 +3833,11 @@ void hyperstone_device::opa0() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_shri(decode); } @@ -1422,26 +3846,37 @@ void hyperstone_device::opa1() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_shri(decode); } -void hyperstone_device::opa2() +void hyperstone_device::hyperstone_shri_local() // shri local,imm { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shri(decode); -} -void hyperstone_device::opa3() -{ - regs_decode decode; - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shri(decode); + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + uint32_t val = m_local_regs[dst_code]; + + SR &= ~(C_MASK | Z_MASK | N_MASK); + + const uint32_t n = N_VALUE; + if (n) + SR |= (val >> (n - 1)) & 1; + + val >>= n; + + m_local_regs[dst_code] = val; + + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(val); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::opa4() @@ -1449,7 +3884,12 @@ void hyperstone_device::opa4() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_sari(decode); } @@ -1458,7 +3898,12 @@ void hyperstone_device::opa5() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_sari(decode); } @@ -1467,53 +3912,90 @@ void hyperstone_device::opa6() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_sari(decode); } void hyperstone_device::opa7() { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_sari(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + + uint32_t val = m_local_regs[dst_code]; + uint32_t sign_bit = val & 0x80000000; + + const uint32_t n = N_VALUE; + + SR &= ~(C_MASK | Z_MASK | N_MASK); + if (n) + { + SR |= (val >> (n - 1)) & 1; + + val >>= n; + + if (sign_bit) + val |= 0xffffffff << (32 - n); + } + + m_local_regs[dst_code] = val; + if (val == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(val); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::opa8() +void hyperstone_device::hyperstone_shli_global() { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_shli(decode); + + const uint32_t dst_code = DST_CODE; + + uint32_t val = m_global_regs[dst_code]; + const uint32_t n = N_VALUE; + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + SR |= n ? (((val << (n - 1)) & 0x80000000) ? 1 : 0) : 0; + uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff; + uint32_t val2 = val << n; + + if (((val & mask) && (!(val2 & 0x80000000))) || (((val & mask) ^ mask) && (val2 & 0x80000000))) + SR |= V_MASK; + + set_global_register(dst_code, val2); + if (val2 == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(val2); + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::opa9() +void hyperstone_device::hyperstone_shli_local() { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_noh(decode); - hyperstone_shli(decode); -} -void hyperstone_device::opaa() -{ - regs_decode decode; - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shli(decode); -} + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; -void hyperstone_device::opab() -{ - regs_decode decode; - check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_shli(decode); + uint32_t val = m_local_regs[dst_code]; + const uint32_t n = N_VALUE; + SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); + SR |= n ? (((val << (n - 1)) & 0x80000000) ? 1 : 0) : 0; + uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff; + uint32_t val2 = val << n; + + if (((val & mask) && (!(val2 & 0x80000000))) || (((val & mask) ^ mask) && (val2 & 0x80000000))) + SR |= V_MASK; + + m_local_regs[dst_code] = val2; + if (val2 == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(val2); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::opac() @@ -1542,7 +4024,20 @@ void hyperstone_device::opb0() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_mulu(decode); } @@ -1550,7 +4045,20 @@ void hyperstone_device::opb1() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_mulu(decode); } @@ -1558,23 +4066,70 @@ void hyperstone_device::opb2() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_mulu(decode); } -void hyperstone_device::opb3() +void hyperstone_device::opb3() // mulu local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_mulu(decode); + + const uint32_t fp = GET_FP; + const uint32_t code = DST_CODE; + const uint32_t dst_code = (code + fp) & 0x3f; + const uint32_t dstf_code = (code + 1 + fp) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code]; + + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint64_t double_word = (uint64_t)sreg *(uint64_t)dreg; + + const uint32_t high_order = (uint32_t)(double_word >> 32); + + m_local_regs[dst_code] = high_order; + m_local_regs[dstf_code] = (uint32_t)double_word; + + SR &= ~(Z_MASK | N_MASK); + if (double_word == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(high_order); + + if(sreg <= 0xffff && dreg <= 0xffff) + m_icount -= m_clock_cycles_4; + else + m_icount -= m_clock_cycles_6; } void hyperstone_device::opb4() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_muls(decode); } @@ -1582,7 +4137,20 @@ void hyperstone_device::opb5() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_muls(decode); } @@ -1590,7 +4158,20 @@ void hyperstone_device::opb6() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_muls(decode); } @@ -1598,7 +4179,20 @@ void hyperstone_device::opb7() { regs_decode decode; check_delay_PC(); - decode_RR11(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_muls(decode); } @@ -1607,7 +4201,11 @@ void hyperstone_device::opb8() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_set(decode); } @@ -1616,17 +4214,219 @@ void hyperstone_device::opb9() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_noh(decode); + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + hyperstone_set(decode); } void hyperstone_device::opba() { - regs_decode decode; check_delay_PC(); - decode.dst = DST_CODE; - decode_dest_local(decode); - hyperstone_set(decode); + + const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; + const uint32_t n = N_VALUE; + + switch (n) + { + // SETADR + case 0: + m_local_regs[dst_code] = (SP & 0xfffffe00) | (GET_FP << 2) | (((SP & 0x100) && (SIGN_BIT(SR) == 0)) ? 1 : 0); + break; + + // Reserved + case 1: + case 16: + case 17: + case 19: + DEBUG_PRINTF(("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC)); + break; + + // SETxx + case 2: + m_local_regs[dst_code] = 1; + break; + + case 3: + m_local_regs[dst_code] = 0; + break; + + case 4: + if (SR & (N_MASK | Z_MASK)) + m_local_regs[dst_code] = 1; + else + m_local_regs[dst_code] = 0; + break; + + case 5: + if (SR & (N_MASK | Z_MASK)) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = 1; + break; + + case 6: + if (SR & N_MASK) + m_local_regs[dst_code] = 1; + else + m_local_regs[dst_code] = 0; + break; + + case 7: + if (SR & N_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = 1; + break; + + case 8: + if (SR & (C_MASK | Z_MASK)) + m_local_regs[dst_code] = 1; + else + m_local_regs[dst_code] = 0; + break; + + case 9: + if (SR & (C_MASK | Z_MASK)) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = 1; + break; + + case 10: + if (SR & C_MASK) + m_local_regs[dst_code] = 1; + else + m_local_regs[dst_code] = 0; + break; + + case 11: + if (SR & C_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = 1; + break; + + case 12: + if (SR & Z_MASK) + m_local_regs[dst_code] = 1; + else + m_local_regs[dst_code] = 0; + break; + + case 13: + if (SR & Z_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = 1; + break; + + case 14: + if (SR & V_MASK) + m_local_regs[dst_code] = 1; + else + m_local_regs[dst_code] = 0; + break; + + case 15: + if (SR & V_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = 1; + break; + + case 18: + m_local_regs[dst_code] = ~0; + break; + + case 20: + if (SR & (N_MASK | Z_MASK)) + m_local_regs[dst_code] = ~0; + else + m_local_regs[dst_code] = 0; + break; + + case 21: + if (SR & (N_MASK | Z_MASK)) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = ~0; + break; + + case 22: + if (SR & N_MASK) + m_local_regs[dst_code] = ~0; + else + m_local_regs[dst_code] = 0; + break; + + case 23: + if (SR & N_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = ~0; + break; + + case 24: + if (SR & (C_MASK | Z_MASK)) + m_local_regs[dst_code] = ~0; + else + m_local_regs[dst_code] = 0; + break; + + case 25: + if (SR & (C_MASK | Z_MASK)) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = ~0; + break; + + case 26: + if (SR & C_MASK) + m_local_regs[dst_code] = ~0; + else + m_local_regs[dst_code] = 0; + break; + + case 27: + if (SR & C_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = ~0; + break; + + case 28: + if (SR & Z_MASK) + m_local_regs[dst_code] = ~0; + else + m_local_regs[dst_code] = 0; + break; + + case 29: + if (SR & Z_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = ~0; + break; + + case 30: + if (SR & V_MASK) + m_local_regs[dst_code] = ~0; + else + m_local_regs[dst_code] = 0; + break; + + case 31: + if (SR & V_MASK) + m_local_regs[dst_code] = 0; + else + m_local_regs[dst_code] = ~0; + break; + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::opbb() @@ -1634,7 +4434,11 @@ void hyperstone_device::opbb() regs_decode decode; check_delay_PC(); decode.dst = DST_CODE; - decode_dest_local(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + hyperstone_set(decode); } @@ -1642,7 +4446,20 @@ void hyperstone_device::opbc() { regs_decode decode; check_delay_PC(); - decode_RR00(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 0; + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 0; + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == (DST_CODE + 1)); + decode.same_srcf_dst = ((SRC_CODE + 1) == DST_CODE); hyperstone_mul(decode); } @@ -1650,7 +4467,21 @@ void hyperstone_device::opbd() { regs_decode decode; check_delay_PC(); - decode_RR01(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 0; + + DREG = m_global_regs[decode.dst]; + DREGF = m_global_regs[decode.dst + 1]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_mul(decode); } @@ -1658,174 +4489,235 @@ void hyperstone_device::opbe() { regs_decode decode; check_delay_PC(); - decode_RR10(decode); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode.src_is_local = 0; + + SREG = m_global_regs[decode.src]; + SREGF = m_global_regs[decode.src + 1]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_mul(decode); } -void hyperstone_device::opbf() +void hyperstone_device::opbf() // mul local,local { - regs_decode decode; check_delay_PC(); - decode_RR11(decode); - hyperstone_mul(decode); + + const uint32_t fp = GET_FP; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t dreg = m_local_regs[dst_code]; + const uint32_t result = sreg * dreg; + + m_local_regs[dst_code] = result; + + SR &= ~(Z_MASK | N_MASK); + if (result == 0) + SR |= Z_MASK; + SR |= SIGN_TO_N(result); + + if ((sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff)) + m_icount -= 3 << m_clck_scale; + else + m_icount -= 5 << m_clck_scale; } - -void hyperstone_device::opc0() +void hyperstone_device::opce() // extend { - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fadd(decode); -} - -void hyperstone_device::opc1() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_faddd(decode); -} - -void hyperstone_device::opc2() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fsub(decode); -} - -void hyperstone_device::opc3() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fsubd(decode); -} - -void hyperstone_device::opc4() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fmul(decode); -} - -void hyperstone_device::opc5() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fmuld(decode); -} - -void hyperstone_device::opc6() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fdiv(decode); -} - -void hyperstone_device::opc7() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fdivd(decode); -} - -void hyperstone_device::opc8() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fcmp(decode); -} - -void hyperstone_device::opc9() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fcmpd(decode); -} - -void hyperstone_device::opca() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fcmpu(decode); -} - -void hyperstone_device::opcb() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fcmpud(decode); -} - -void hyperstone_device::opcc() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fcvt(decode); -} - -void hyperstone_device::opcd() -{ - regs_decode decode; - check_delay_PC(); - decode_LL(decode); - hyperstone_fcvtd(decode); -} - -void hyperstone_device::opce() -{ - regs_decode decode; m_instruction_length = (2<<19); - EXTRA_U = READ_OP(PC); + const uint32_t func = READ_OP(PC); PC += 2; check_delay_PC(); - decode_LL(decode); - hyperstone_extend(decode); + + //TODO: add locks, overflow error and other things + const uint32_t fp = GET_FP; + const uint32_t vals = m_local_regs[(SRC_CODE + fp) & 0x3f]; + const uint32_t vald = m_local_regs[(DST_CODE + fp) & 0x3f]; + + switch (func) // extended opcode + { + // signed or unsigned multiplication, single word product + case EMUL: + case 0x100: // used in "N" type cpu + m_global_regs[15] = (uint32_t)(vals * vald); + break; + + // unsigned multiplication, double word product + case EMULU: + { + const uint64_t result = (uint64_t)vals * (uint64_t)vald; + m_global_regs[14] = (uint32_t)(result >> 32); + 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; + } + + // signed multiply/add, single word product sum + case EMAC: + m_global_regs[15] += (int32_t)vals * (int32_t)vald; + break; + + // signed multiply/add, double word product sum + case EMACD: + { + 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 multiply/substract, single word product difference + case EMSUB: + m_global_regs[15] = (int32_t)m_global_regs[15] - ((int32_t)vals * (int32_t)vald); + break; + + // signed multiply/substract, double word product difference + case EMSUBD: + { + 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)); + 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)); + m_global_regs[14] = (uint32_t)(result >> 32); + m_global_regs[15] = (uint32_t)result; + break; + } + + // 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)); + 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)); + break; + + // half-word (complex) add/substract + // Ls is not used and should denote the same register as Ld + case EHCSUMD: + { + 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); + break; + } + + // half-word (complex) add/substract with fixed point adjustment + // Ls is not used and should denote the same register as Ld + case EHCFFTD: + { + const uint32_t r14 = m_global_regs[14]; + const uint32_t r15 = m_global_regs[15]; + m_global_regs[14] = (((((vals & 0xffff0000) >> 16) + (r14 >> 15)) << 16) & 0xffff0000) | (((vals & 0xffff) + (r15 >> 15)) & 0xffff); + m_global_regs[15] = (((((vals & 0xffff0000) >> 16) - (r14 >> 15)) << 16) & 0xffff0000) | (((vals & 0xffff) - (r15 >> 15)) & 0xffff); + break; + } + + // half-word (complex) add/substract with fixed point adjustment and shift + // Ls is not used and should denote the same register as Ld + case EHCFFTSD: + { + const uint32_t r14 = m_global_regs[14]; + const uint32_t r15 = m_global_regs[15]; + m_global_regs[14] = ((((((vals & 0xffff0000) >> 16) + (r14 >> 15)) >> 1) << 16) & 0xffff0000) | (((((vals & 0xffff) + (r15 >> 15)) >> 1) & 0xffff)); + m_global_regs[15] = ((((((vals & 0xffff0000) >> 16) - (r14 >> 15)) >> 1) << 16) & 0xffff0000) | (((((vals & 0xffff) - (r15 >> 15)) >> 1) & 0xffff)); + break; + } + + default: + DEBUG_PRINTF(("Executed Illegal extended opcode (%X). PC = %08X\n", func, PC)); + break; + } + + m_icount -= m_clock_cycles_1; //TODO: with the latency it can change } void hyperstone_device::opcf() { regs_decode decode; check_delay_PC(); - decode_LL(decode); + + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = (SRC_CODE == DST_CODE); + decode.same_src_dstf = (SRC_CODE == ((DST_CODE + 1) % 64)); + decode.same_srcf_dst = 0; + hyperstone_do(decode); } -void hyperstone_device::opd0() +void hyperstone_device::opd0() // ldwr global,local { - regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); - hyperstone_ldwr(decode); + set_global_register(SRC_CODE, READ_W(m_local_regs[(DST_CODE + GET_FP) & 0x3f])); + m_icount -= m_clock_cycles_1; } -void hyperstone_device::opd1() +void hyperstone_device::opd1() // ldwr local,local { - regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); - hyperstone_ldwr(decode); + const uint32_t fp = GET_FP; + m_local_regs[(SRC_CODE + fp) & 0x3f] = READ_W(m_local_regs[(DST_CODE + fp) & 0x3f]); + m_icount -= m_clock_cycles_1; } void hyperstone_device::opd2() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_lddr(decode); } @@ -1833,7 +4725,20 @@ void hyperstone_device::opd3() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_lddr(decode); } @@ -1841,7 +4746,17 @@ void hyperstone_device::opd4() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_ldwp(decode); } @@ -1849,7 +4764,20 @@ void hyperstone_device::opd5() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_ldwp(decode); } @@ -1857,23 +4785,58 @@ void hyperstone_device::opd6() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_lddp(decode); } void hyperstone_device::opd7() { - regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); - hyperstone_lddp(decode); + + const uint32_t fp = GET_FP; + const uint32_t src_code = SRC_CODE + fp; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + const uint32_t dreg = m_local_regs[dst_code]; + const bool same_srcf_dst = (((src_code + 1) & 0x3f) == dst_code); + + m_local_regs[src_code & 0x3f] = READ_W(dreg); + m_local_regs[(src_code + 1) & 0x3f] = READ_W(dreg + 4); + + // post increment the destination register if it's different from the source one + // and from the "next source" one + if (!(src_code == dst_code && (m_op & 0x100)) && !same_srcf_dst) + { + m_local_regs[dst_code] += 8; + } + + m_icount -= m_clock_cycles_2; } void hyperstone_device::opd8() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_stwr(decode); } @@ -1881,7 +4844,20 @@ void hyperstone_device::opd9() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_stwr(decode); } @@ -1889,7 +4865,17 @@ void hyperstone_device::opda() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_stdr(decode); } @@ -1897,7 +4883,20 @@ void hyperstone_device::opdb() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_stdr(decode); } @@ -1905,7 +4904,17 @@ void hyperstone_device::opdc() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_stwp(decode); } @@ -1913,7 +4922,20 @@ void hyperstone_device::opdd() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + + decode.src_is_local = 1; + SREG = m_local_regs[(decode.src + GET_FP) % 64]; + SREGF = m_local_regs[(decode.src + 1 + GET_FP) % 64]; + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = (((SRC_CODE + 1) % 64) == DST_CODE); hyperstone_stwp(decode); } @@ -1921,356 +4943,591 @@ void hyperstone_device::opde() { regs_decode decode; check_delay_PC(); - decode_LR(decode, 0); + decode.src = SRC_CODE; + decode.dst = DST_CODE; + decode_source_noh(decode); + + decode.dst_is_local = 1; + DREG = m_local_regs[(decode.dst + GET_FP) % 64]; /* registers offset by frame pointer */ + DREGF = m_local_regs[(decode.dst + 1 + GET_FP) % 64]; + + decode.same_src_dst = 0; + decode.same_src_dstf = 0; + decode.same_srcf_dst = 0; hyperstone_stdp(decode); } -void hyperstone_device::opdf() +void hyperstone_device::opdf() // stdp local, local { - regs_decode decode; check_delay_PC(); - decode_LR(decode, 1); - hyperstone_stdp(decode); + const uint32_t fp = GET_FP; + const uint32_t src_code = SRC_CODE + fp; + const uint32_t srcf_code = (SRC_CODE + fp + 1) & 0x3f; + const uint32_t dst_code = (DST_CODE + fp) & 0x3f; + + const uint32_t sreg = m_local_regs[src_code & 0x3f]; + const uint32_t sregf = m_local_regs[srcf_code]; + const uint32_t dreg = m_local_regs[dst_code]; /* registers offset by frame pointer */ + + bool same_srcf_dst = (srcf_code == dst_code); + + WRITE_W(dreg, sreg); + m_local_regs[dst_code] += 8; + + if (same_srcf_dst) + WRITE_W(dreg + 4, sregf + 8); // because DREG == SREGF and DREG has been incremented + else + WRITE_W(dreg + 4, sregf); + + m_icount -= m_clock_cycles_2; } void hyperstone_device::ope0() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_dbv(decode); + if (GET_V) + execute_dbr(offset); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope1() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_dbnv(decode); + if (!GET_V) + execute_dbr(offset); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope2() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dbe(decode); + if (SR & Z_MASK) + { + int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope3() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dbne(decode); + if (SR & Z_MASK) + { + ignore_pcrel(); + check_delay_PC(); + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope4() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_dbc(decode); + if (GET_C) + execute_dbr(offset); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope5() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dbnc(decode); + if (SR & C_MASK) + { + ignore_pcrel(); + check_delay_PC(); + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope6() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_dbse(decode); + if (GET_C || GET_Z) + execute_dbr(offset); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope7() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_dbht(decode); + if (!GET_C && !GET_Z) + execute_dbr(offset); + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope8() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dbn(decode); + if (SR & N_MASK) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::ope9() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dbnn(decode); + if (SR & N_MASK) + { + ignore_pcrel(); + check_delay_PC(); + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::opea() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dble(decode); + if (SR & (N_MASK | Z_MASK)) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + } + + m_icount -= m_clock_cycles_1; } void hyperstone_device::opeb() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_dbgt(decode); + if (SR & (N_MASK | Z_MASK)) + { + ignore_pcrel(); + check_delay_PC(); + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_dbr(offset); + } + + m_icount -= m_clock_cycles_1; } -void hyperstone_device::opec() +void hyperstone_device::opec() // dbr { - regs_decode decode; - decode_pcrel(decode); + const int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_dbr(decode); + + m_delay_slot = true; + m_delay_pc = PC + offset; + m_intblock = 3; } -void hyperstone_device::oped() +void hyperstone_device::oped() // frame { - regs_decode decode; check_delay_PC(); - decode_LL(decode); - hyperstone_frame(decode); + + uint8_t realfp = GET_FP - SRC_CODE; + uint8_t dst_code = DST_CODE; + + SET_FP(realfp); + SET_FL(dst_code); + SR &= ~M_MASK; + + int8_t difference = ((SP & 0x1fc) >> 2) + (64 - 10) - (realfp + GET_FL); // really it's 7 bits + + /* convert to 8 bits */ + if(difference > 63) + difference = (int8_t)(difference|0x80); + else if( difference < -64 ) + difference = difference & 0x7f; + + if (difference < 0) // else it's finished + { + bool tmp_flag = SP >= UB; + + for (; difference < 0; difference++) + { + WRITE_W(SP, m_local_regs[(SP & 0xfc) >> 2]); + SP += 4; + } + + if (tmp_flag) + { + uint32_t addr = get_trap_addr(TRAPNO_FRAME_ERROR); + execute_exception(addr); + } + } + + //TODO: no 1! + m_icount -= m_clock_cycles_1; } -void hyperstone_device::opee() +void hyperstone_device::opee() // call, global source { - regs_decode decode; - decode_const(decode); + uint16_t imm_1 = READ_OP(PC); + PC += 2; + + int32_t extra_s = 0; + + if (E_BIT(imm_1)) + { + uint16_t imm_2 = READ_OP(PC); + + PC += 2; + SET_ILC(3<<19); + + extra_s = imm_2; + extra_s |= ((imm_1 & 0x3fff) << 16); + + if (S_BIT_CONST(imm_1)) + extra_s |= 0xc0000000; + } + else + { + extra_s = imm_1 & 0x3fff; + + SET_ILC(2<<19); + + if (S_BIT_CONST(imm_1)) + extra_s |= 0xffffc000; + } + check_delay_PC(); - decode_LR(decode, 0); - hyperstone_call(decode); + + uint32_t src_code = SRC_CODE; + uint32_t dst_code = DST_CODE; + + uint32_t sreg = m_global_regs[src_code]; + + if (src_code == SR_REGISTER) + sreg = 0; + + if (!DST_CODE) + dst_code = 16; + + uint32_t fp = GET_FP; + uint32_t dreg_index = dst_code + fp; + m_local_regs[dreg_index & 0x3f] = (PC & ~1) | GET_S; + m_local_regs[(dreg_index + 1) & 0x3f] = SR; + + SET_FP(fp + dst_code); + SET_FL(6); //default value for call + SR &= ~M_MASK; + + PPC = PC; + PC = (extra_s & ~1) + sreg; // const value + + m_intblock = 2; + + //TODO: add interrupt locks, errors, .... + + //TODO: no 1! + m_icount -= m_clock_cycles_1; } -void hyperstone_device::opef() +void hyperstone_device::opef() // call, local source { - regs_decode decode; - decode_const(decode); + uint16_t imm_1 = READ_OP(PC); + PC += 2; + + int32_t extra_s = 0; + + if (E_BIT(imm_1)) + { + uint16_t imm_2 = READ_OP(PC); + + PC += 2; + SET_ILC(3<<19); + + extra_s = imm_2; + extra_s |= ((imm_1 & 0x3fff) << 16); + + if (S_BIT_CONST(imm_1)) + extra_s |= 0xc0000000; + } + else + { + extra_s = imm_1 & 0x3fff; + + SET_ILC(2<<19); + + if (S_BIT_CONST(imm_1)) + extra_s |= 0xffffc000; + } + check_delay_PC(); - decode_LR(decode, 1); - hyperstone_call(decode); + + uint32_t src_code = SRC_CODE; + uint32_t dst_code = DST_CODE; + + if (!DST_CODE) + dst_code = 16; + + uint32_t fp = GET_FP; + extra_s = (extra_s & ~1) + m_local_regs[(src_code + fp) & 0x3f]; + + uint32_t dreg_index = dst_code + fp; + m_local_regs[dreg_index & 0x3f] = (PC & ~1) | GET_S; + m_local_regs[(dreg_index + 1) & 0x3f] = SR; + + SET_FP(fp + dst_code); + SET_FL(6); //default value for call + SR &= ~M_MASK; + + PPC = PC; + PC = extra_s; // const value + + m_intblock = 2; + + //TODO: add interrupt locks, errors, .... + + //TODO: no 1! + m_icount -= m_clock_cycles_1; } void hyperstone_device::opf0() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_bv(decode); + if (GET_V) + execute_br(offset); + else + m_icount -= m_clock_cycles_1; } void hyperstone_device::opf1() { - regs_decode decode; - decode_pcrel(decode); + int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_bnv(decode); + if (!GET_V) + execute_br(offset); + else + m_icount -= m_clock_cycles_1; } void hyperstone_device::opf2() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_be(decode); + if (SR & Z_MASK) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } } void hyperstone_device::opf3() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bne(decode); + if (SR & Z_MASK) + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } } void hyperstone_device::opf4() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bc(decode); + if (SR & C_MASK) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } } void hyperstone_device::opf5() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bnc(decode); + if (SR & C_MASK) + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } } void hyperstone_device::opf6() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bse(decode); + if (SR & (C_MASK | Z_MASK)) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } } void hyperstone_device::opf7() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bht(decode); + if (SR & (C_MASK | Z_MASK)) + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } } void hyperstone_device::opf8() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bn(decode); + if (SR & N_MASK) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } } void hyperstone_device::opf9() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bnn(decode); + if (SR & N_MASK) + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } } void hyperstone_device::opfa() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_ble(decode); + if (SR & (N_MASK | Z_MASK)) + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } + else + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } } void hyperstone_device::opfb() { - regs_decode decode; - decode_pcrel(decode); - check_delay_PC(); - hyperstone_bgt(decode); + if (SR & (N_MASK | Z_MASK)) + { + ignore_pcrel(); + check_delay_PC(); + m_icount -= m_clock_cycles_1; + } + else + { + const int32_t offset = decode_pcrel(); + check_delay_PC(); + execute_br(offset); + } } void hyperstone_device::opfc() { - regs_decode decode; - decode_pcrel(decode); + const int32_t offset = decode_pcrel(); check_delay_PC(); - hyperstone_br(decode); + execute_br(offset); } void hyperstone_device::opfd() { - regs_decode decode; check_delay_PC(); - hyperstone_trap(decode); + hyperstone_trap(); } void hyperstone_device::opfe() { - regs_decode decode; check_delay_PC(); - hyperstone_trap(decode); + hyperstone_trap(); } void hyperstone_device::opff() { - regs_decode decode; check_delay_PC(); - hyperstone_trap(decode); + hyperstone_trap(); } - -const hyperstone_device::ophandler hyperstone_device::s_opcodetable[256] = -{ - &hyperstone_device::op00, &hyperstone_device::op01, &hyperstone_device::op02, &hyperstone_device::op03, - &hyperstone_device::op04, &hyperstone_device::op05, &hyperstone_device::op06, &hyperstone_device::op07, - &hyperstone_device::op08, &hyperstone_device::op09, &hyperstone_device::op0a, &hyperstone_device::op0b, - &hyperstone_device::op0c, &hyperstone_device::op0d, &hyperstone_device::op0e, &hyperstone_device::op0f, - - &hyperstone_device::op10, &hyperstone_device::op11, &hyperstone_device::op12, &hyperstone_device::op13, - &hyperstone_device::op14, &hyperstone_device::op15, &hyperstone_device::op16, &hyperstone_device::op17, - &hyperstone_device::op18, &hyperstone_device::op19, &hyperstone_device::op1a, &hyperstone_device::op1b, - &hyperstone_device::op1c, &hyperstone_device::op1d, &hyperstone_device::op1e, &hyperstone_device::op1f, - - &hyperstone_device::op20, &hyperstone_device::op21, &hyperstone_device::op22, &hyperstone_device::op23, - &hyperstone_device::op24, &hyperstone_device::op25, &hyperstone_device::op26, &hyperstone_device::op27, - &hyperstone_device::op28, &hyperstone_device::op29, &hyperstone_device::op2a, &hyperstone_device::op2b, - &hyperstone_device::op2c, &hyperstone_device::op2d, &hyperstone_device::op2e, &hyperstone_device::op2f, - - &hyperstone_device::op30, &hyperstone_device::op31, &hyperstone_device::op32, &hyperstone_device::op33, - &hyperstone_device::op34, &hyperstone_device::op35, &hyperstone_device::op36, &hyperstone_device::op37, - &hyperstone_device::op38, &hyperstone_device::op39, &hyperstone_device::op3a, &hyperstone_device::op3b, - &hyperstone_device::op3c, &hyperstone_device::op3d, &hyperstone_device::op3e, &hyperstone_device::op3f, - - &hyperstone_device::op40, &hyperstone_device::op41, &hyperstone_device::op42, &hyperstone_device::op43, - &hyperstone_device::op44, &hyperstone_device::op45, &hyperstone_device::op46, &hyperstone_device::op47, - &hyperstone_device::op48, &hyperstone_device::op49, &hyperstone_device::op4a, &hyperstone_device::op4b, - &hyperstone_device::op4c, &hyperstone_device::op4d, &hyperstone_device::op4e, &hyperstone_device::op4f, - - &hyperstone_device::op50, &hyperstone_device::op51, &hyperstone_device::op52, &hyperstone_device::op53, - &hyperstone_device::op54, &hyperstone_device::op55, &hyperstone_device::op56, &hyperstone_device::op57, - &hyperstone_device::op58, &hyperstone_device::op59, &hyperstone_device::op5a, &hyperstone_device::op5b, - &hyperstone_device::op5c, &hyperstone_device::op5d, &hyperstone_device::op5e, &hyperstone_device::op5f, - - &hyperstone_device::op60, &hyperstone_device::op61, &hyperstone_device::op62, &hyperstone_device::op63, - &hyperstone_device::op64, &hyperstone_device::op65, &hyperstone_device::op66, &hyperstone_device::op67, - &hyperstone_device::op68, &hyperstone_device::op69, &hyperstone_device::op6a, &hyperstone_device::op6b, - &hyperstone_device::op6c, &hyperstone_device::op6d, &hyperstone_device::op6e, &hyperstone_device::op6f, - - &hyperstone_device::op70, &hyperstone_device::op71, &hyperstone_device::op72, &hyperstone_device::op73, - &hyperstone_device::op74, &hyperstone_device::op75, &hyperstone_device::op76, &hyperstone_device::op77, - &hyperstone_device::op78, &hyperstone_device::op79, &hyperstone_device::op7a, &hyperstone_device::op7b, - &hyperstone_device::op7c, &hyperstone_device::op7d, &hyperstone_device::op7e, &hyperstone_device::op7f, - - &hyperstone_device::op80, &hyperstone_device::op81, &hyperstone_device::op82, &hyperstone_device::op83, - &hyperstone_device::op84, &hyperstone_device::op85, &hyperstone_device::op86, &hyperstone_device::op87, - &hyperstone_device::op88, &hyperstone_device::op89, &hyperstone_device::op8a, &hyperstone_device::op8b, - &hyperstone_device::op8c, &hyperstone_device::op8d, &hyperstone_device::op8e, &hyperstone_device::op8f, - - &hyperstone_device::op90, &hyperstone_device::op91, &hyperstone_device::op92, &hyperstone_device::op93, - &hyperstone_device::op94, &hyperstone_device::op95, &hyperstone_device::op96, &hyperstone_device::op97, - &hyperstone_device::op98, &hyperstone_device::op99, &hyperstone_device::op9a, &hyperstone_device::op9b, - &hyperstone_device::op9c, &hyperstone_device::op9d, &hyperstone_device::op9e, &hyperstone_device::op9f, - - &hyperstone_device::opa0, &hyperstone_device::opa1, &hyperstone_device::opa2, &hyperstone_device::opa3, - &hyperstone_device::opa4, &hyperstone_device::opa5, &hyperstone_device::opa6, &hyperstone_device::opa7, - &hyperstone_device::opa8, &hyperstone_device::opa9, &hyperstone_device::opaa, &hyperstone_device::opab, - &hyperstone_device::opac, &hyperstone_device::opad, &hyperstone_device::opae, &hyperstone_device::opaf, - - &hyperstone_device::opb0, &hyperstone_device::opb1, &hyperstone_device::opb2, &hyperstone_device::opb3, - &hyperstone_device::opb4, &hyperstone_device::opb5, &hyperstone_device::opb6, &hyperstone_device::opb7, - &hyperstone_device::opb8, &hyperstone_device::opb9, &hyperstone_device::opba, &hyperstone_device::opbb, - &hyperstone_device::opbc, &hyperstone_device::opbd, &hyperstone_device::opbe, &hyperstone_device::opbf, - - &hyperstone_device::opc0, &hyperstone_device::opc1, &hyperstone_device::opc2, &hyperstone_device::opc3, - &hyperstone_device::opc4, &hyperstone_device::opc5, &hyperstone_device::opc6, &hyperstone_device::opc7, - &hyperstone_device::opc8, &hyperstone_device::opc9, &hyperstone_device::opca, &hyperstone_device::opcb, - &hyperstone_device::opcc, &hyperstone_device::opcd, &hyperstone_device::opce, &hyperstone_device::opcf, - - &hyperstone_device::opd0, &hyperstone_device::opd1, &hyperstone_device::opd2, &hyperstone_device::opd3, - &hyperstone_device::opd4, &hyperstone_device::opd5, &hyperstone_device::opd6, &hyperstone_device::opd7, - &hyperstone_device::opd8, &hyperstone_device::opd9, &hyperstone_device::opda, &hyperstone_device::opdb, - &hyperstone_device::opdc, &hyperstone_device::opdd, &hyperstone_device::opde, &hyperstone_device::opdf, - - &hyperstone_device::ope0, &hyperstone_device::ope1, &hyperstone_device::ope2, &hyperstone_device::ope3, - &hyperstone_device::ope4, &hyperstone_device::ope5, &hyperstone_device::ope6, &hyperstone_device::ope7, - &hyperstone_device::ope8, &hyperstone_device::ope9, &hyperstone_device::opea, &hyperstone_device::opeb, - &hyperstone_device::opec, &hyperstone_device::oped, &hyperstone_device::opee, &hyperstone_device::opef, - - &hyperstone_device::opf0, &hyperstone_device::opf1, &hyperstone_device::opf2, &hyperstone_device::opf3, - &hyperstone_device::opf4, &hyperstone_device::opf5, &hyperstone_device::opf6, &hyperstone_device::opf7, - &hyperstone_device::opf8, &hyperstone_device::opf9, &hyperstone_device::opfa, &hyperstone_device::opfb, - &hyperstone_device::opfc, &hyperstone_device::opfd, &hyperstone_device::opfe, &hyperstone_device::opff -};