diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index f3cf65ee595..90e560430c0 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -1641,14 +1641,14 @@ void hyperstone_device::execute_run() case 0x05: hyperstone_movd(); break; case 0x06: hyperstone_movd(); break; case 0x07: hyperstone_movd(); break; - case 0x08: hyperstone_divu(); break; - case 0x09: hyperstone_divu(); break; - case 0x0a: hyperstone_divu(); break; - case 0x0b: hyperstone_divu(); break; - case 0x0c: hyperstone_divs(); break; - case 0x0d: hyperstone_divs(); break; - case 0x0e: hyperstone_divs(); break; - case 0x0f: hyperstone_divs(); break; + case 0x08: hyperstone_divsu(); break; + case 0x09: hyperstone_divsu(); break; + case 0x0a: hyperstone_divsu(); break; + case 0x0b: hyperstone_divsu(); break; + case 0x0c: hyperstone_divsu(); break; + case 0x0d: hyperstone_divsu(); break; + case 0x0e: hyperstone_divsu(); break; + case 0x0f: hyperstone_divsu(); break; case 0x10: hyperstone_xm(); break; case 0x11: hyperstone_xm(); break; case 0x12: hyperstone_xm(); break; @@ -1809,14 +1809,14 @@ void hyperstone_device::execute_run() case 0xad: hyperstone_reserved(); break; case 0xae: hyperstone_reserved(); break; case 0xaf: hyperstone_reserved(); break; - case 0xb0: hyperstone_mulu(); break; - case 0xb1: hyperstone_mulu(); break; - case 0xb2: hyperstone_mulu(); break; - case 0xb3: hyperstone_mulu(); break; - case 0xb4: hyperstone_muls(); break; - case 0xb5: hyperstone_muls(); break; - case 0xb6: hyperstone_muls(); break; - case 0xb7: hyperstone_muls(); break; + case 0xb0: hyperstone_mulsu(); break; + case 0xb1: hyperstone_mulsu(); break; + case 0xb2: hyperstone_mulsu(); break; + case 0xb3: hyperstone_mulsu(); break; + case 0xb4: hyperstone_mulsu(); break; + case 0xb5: hyperstone_mulsu(); break; + case 0xb6: hyperstone_mulsu(); break; + case 0xb7: hyperstone_mulsu(); break; case 0xb8: hyperstone_set(); break; case 0xb9: hyperstone_set(); break; case 0xba: hyperstone_set(); break; diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 1acc86d53e9..4a04e38ea3e 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -111,7 +111,13 @@ protected: enum shift_type { N_LO = 0, - N_HI = 1, + N_HI = 1 + }; + + enum sign_mode + { + IS_UNSIGNED = 0, + IS_SIGNED = 1 }; // construction/destruction @@ -216,8 +222,7 @@ private: template void hyperstone_chk(); template void hyperstone_movd(); - template void hyperstone_divu(); - template void hyperstone_divs(); + template void hyperstone_divsu(); template void hyperstone_xm(); template void hyperstone_mask(); template void hyperstone_sum(); @@ -265,8 +270,7 @@ private: template void hyperstone_stxx1(); template void hyperstone_stxx2(); - template void hyperstone_mulu(); - template void hyperstone_muls(); + template void hyperstone_mulsu(); template void hyperstone_mul(); template void hyperstone_set(); diff --git a/src/devices/cpu/e132xs/e132xsop.hxx b/src/devices/cpu/e132xs/e132xsop.hxx index 2a6915bab81..b0df1d1c778 100644 --- a/src/devices/cpu/e132xs/e132xsop.hxx +++ b/src/devices/cpu/e132xs/e132xsop.hxx @@ -119,8 +119,8 @@ void hyperstone_device::hyperstone_movd() } } -template -void hyperstone_device::hyperstone_divu() +template +void hyperstone_device::hyperstone_divsu() { check_delay_PC(); @@ -137,58 +137,11 @@ void hyperstone_device::hyperstone_divu() } const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code]; - - if (sreg == 0) - { - //Rd//Rdf -> undefined - //Z -> undefined - //N -> undefined - SR |= V_MASK; - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); - } - else - { - const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code]; - const uint32_t dregf = (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code]; - const uint64_t dividend = concat_64(dreg, dregf); - - /* TODO: add quotient overflow */ - uint32_t quotient = dividend / sreg; - (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = dividend % sreg; - (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = quotient; - - SR &= ~(V_MASK | Z_MASK | N_MASK); - if (quotient == 0) - SR |= Z_MASK; - SR |= SIGN_TO_N(quotient); - } - - m_icount -= 36 << m_clck_scale; -} - -template -void hyperstone_device::hyperstone_divs() -{ - check_delay_PC(); - - const uint32_t fp = GET_FP; - const uint32_t dst_code = DST_GLOBAL ? DST_CODE : ((DST_CODE + fp) & 0x3f); - const uint32_t dstf_code = DST_GLOBAL ? (dst_code + 1) : ((dst_code + 1) & 0x3f); - const uint32_t src_code = SRC_GLOBAL ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); - - if ((SRC_GLOBAL == DST_GLOBAL && (src_code == dst_code || src_code == dstf_code)) || (SRC_GLOBAL && src_code < 2)) - { - LOG("Denoted invalid register code in hyperstone_divs instruction. PC = %08X\n", PC); - m_icount -= 36 << m_clck_scale; - return; - } - - const int32_t sreg = (int32_t)(SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code]; const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code]; const uint32_t dregf = (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code]; - const int64_t dividend = (int64_t) concat_64(dreg, dregf); + const uint64_t dividend = concat_64(dreg, dregf); - if (sreg == 0 || (dividend & 0x8000000000000000U)) + if (sreg == 0 || (SIGNED && (dividend & 0x8000000000000000U))) { //Rd//Rdf -> undefined //Z -> undefined @@ -199,10 +152,9 @@ void hyperstone_device::hyperstone_divs() else { /* TODO: add quotient overflow */ - const int32_t quotient = dividend / sreg; - (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = dividend % sreg; - (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = quotient; - + const uint32_t quotient = SIGNED ? (uint32_t)((int64_t)dividend / (int32_t)sreg) : (dividend / sreg); + (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = SIGNED ? (uint32_t)((int64_t)dividend % (int32_t)sreg) : (dividend % sreg); + (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = (uint32_t)quotient; SR &= ~(V_MASK | Z_MASK | N_MASK); if (quotient == 0) SR |= Z_MASK; @@ -2239,8 +2191,8 @@ void hyperstone_device::hyperstone_shli() m_icount -= m_clock_cycles_1; } -template -void hyperstone_device::hyperstone_mulu() +template +void hyperstone_device::hyperstone_mulsu() { check_delay_PC(); @@ -2251,13 +2203,13 @@ void hyperstone_device::hyperstone_mulu() if ((SRC_GLOBAL && src_code < 2) || (DST_GLOBAL && dst_code < 2)) { - LOG("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC); + LOG("Denoted PC or SR in hyperstone_muls/u instruction. PC = %08X\n", PC); return; } const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code]; const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code]; - const uint64_t double_word = (uint64_t)sreg *(uint64_t)dreg; + const uint64_t double_word = SIGNED ? (uint64_t)((int64_t)(int32_t)sreg * (int64_t)(int32_t)dreg) : ((uint64_t)sreg *(uint64_t)dreg); const uint32_t high_order = (uint32_t)(double_word >> 32); @@ -2269,43 +2221,9 @@ void hyperstone_device::hyperstone_mulu() SR |= Z_MASK; SR |= SIGN_TO_N(high_order); - if(sreg <= 0xffff && dreg <= 0xffff) + if(SIGNED == IS_SIGNED && (sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff)) m_icount -= m_clock_cycles_4; - else - m_icount -= m_clock_cycles_6; -} - -template -void hyperstone_device::hyperstone_muls() -{ - check_delay_PC(); - - const uint32_t fp = GET_FP; - const uint32_t src_code = SRC_GLOBAL ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); - const uint32_t dst_code = DST_GLOBAL ? DST_CODE : ((DST_CODE + fp) & 0x3f); - const uint32_t dstf_code = DST_GLOBAL ? (dst_code + 1) : ((dst_code + 1) & 0x3f); - - if ((SRC_GLOBAL && src_code < 2) || (DST_GLOBAL && dst_code < 2)) - { - LOG("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC); - return; - } - - const int32_t dreg = (int32_t)(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code]; - const int32_t sreg = (int32_t)(SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code]; - const int64_t double_word = (int64_t)sreg * (int64_t)dreg; - - const uint32_t high_order = (uint32_t)(double_word >> 32); - - (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = high_order; - (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = (uint32_t)double_word; - - SR &= ~(Z_MASK | N_MASK); - if (double_word == 0) - SR |= Z_MASK; - SR |= SIGN_TO_N(high_order); - - if((sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff)) + else if(SIGNED == IS_UNSIGNED && sreg <= 0xffff && dreg <= 0xffff) m_icount -= m_clock_cycles_4; else m_icount -= m_clock_cycles_6;