From 496055720bf33c0abba6cf48e754da447c043ab8 Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 14 Jun 2022 21:06:31 -0400 Subject: [PATCH] e132xs: Cleanups - Add helper functions for double-word register accesses and multiplication - Make 16-bit multiplications signed for EHCMULD and EHCMACD - Correct typo in comments --- src/devices/cpu/e132xs/e132xs.h | 3 + src/devices/cpu/e132xs/e132xsop.hxx | 153 +++++++++++++--------------- 2 files changed, 74 insertions(+), 82 deletions(-) diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index fb50a3dfb5b..3c27a39d737 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -354,6 +354,9 @@ private: void execute_exception(uint32_t addr); void execute_software(); + template uint64_t get_double_word(uint8_t dst_code, uint8_t dstf_code) const; + template void set_double_word(uint8_t dst_code, uint8_t dstf_code, uint64_t val); + template void hyperstone_chk(); template void hyperstone_movd(); template void hyperstone_divsu(); diff --git a/src/devices/cpu/e132xs/e132xsop.hxx b/src/devices/cpu/e132xs/e132xsop.hxx index e1898880d89..0519eca538e 100644 --- a/src/devices/cpu/e132xs/e132xsop.hxx +++ b/src/devices/cpu/e132xs/e132xsop.hxx @@ -1,5 +1,30 @@ // license:BSD-3-Clause // copyright-holders:Pierpaolo Prazzoli + +template +uint64_t hyperstone_device::get_double_word(uint8_t dst_code, uint8_t dstf_code) const +{ + if(DST_GLOBAL) + return (uint64_t)m_core->global_regs[dst_code] << 32 | m_core->global_regs[dstf_code]; + else + return (uint64_t)m_core->local_regs[dst_code] << 32 | m_core->local_regs[dstf_code]; +} + +template +void hyperstone_device::set_double_word(uint8_t dst_code, uint8_t dstf_code, uint64_t val) +{ + if(DST_GLOBAL) + { + m_core->global_regs[dst_code] = (uint32_t)(val >> 32); + m_core->global_regs[dstf_code] = (uint32_t)val; + } + else + { + m_core->local_regs[dst_code] = (uint32_t)(val >> 32); + m_core->local_regs[dstf_code] = (uint32_t)val; + } +} + template void hyperstone_device::hyperstone_chk() { @@ -97,7 +122,7 @@ void hyperstone_device::hyperstone_movd() else // Rd doesn't denote PC and Rs doesn't denote SR { SR &= ~(Z_MASK | N_MASK); - if (concat_64(sreg, sregf) == 0) + if (sreg == 0 && sregf == 0) SR |= Z_MASK; SR |= SIGN_TO_N(sreg); @@ -134,9 +159,7 @@ void hyperstone_device::hyperstone_divsu() } const uint32_t sreg = (SRC_GLOBAL ? m_core->global_regs : m_core->local_regs)[src_code]; - const uint32_t dreg = (DST_GLOBAL ? m_core->global_regs : m_core->local_regs)[dst_code]; - const uint32_t dregf = (DST_GLOBAL ? m_core->global_regs : m_core->local_regs)[dstf_code]; - const uint64_t dividend = concat_64(dreg, dregf); + const uint64_t dividend = get_double_word(dst_code, dstf_code); if (sreg == 0 || (SIGNED && (dividend & 0x8000000000000000U))) { @@ -1160,10 +1183,8 @@ void hyperstone_device::hyperstone_shrdi() const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; const uint32_t dstf_code = (dst_code + 1) & 0x3f; - uint32_t high_order = m_core->local_regs[dst_code]; - const uint32_t low_order = m_core->local_regs[dstf_code]; - uint64_t val = concat_64(high_order, low_order); + uint64_t val = get_double_word(dst_code, dstf_code); SR &= ~(C_MASK | Z_MASK | N_MASK); @@ -1175,14 +1196,11 @@ void hyperstone_device::hyperstone_shrdi() val >>= n; } - high_order = extract_64hi(val); - if (val == 0) SR |= Z_MASK; - SR |= SIGN_TO_N(high_order); + SR |= SIGN64_TO_N(val); - m_core->local_regs[dst_code] = high_order; - m_core->local_regs[dstf_code] = extract_64lo(val); + set_double_word(dst_code, dstf_code, val); m_core->icount -= m_core->clock_cycles_2; } @@ -1203,7 +1221,7 @@ void hyperstone_device::hyperstone_shrd() return; } - uint64_t val = concat_64(m_core->local_regs[dst_code], m_core->local_regs[dstf_code]); + uint64_t val = get_double_word(dst_code, dstf_code); SR &= ~(C_MASK | Z_MASK | N_MASK); @@ -1219,8 +1237,7 @@ void hyperstone_device::hyperstone_shrd() SR |= Z_MASK; SR |= SIGN64_TO_N(val); - m_core->local_regs[dst_code] = (uint32_t)(val >> 32); - m_core->local_regs[dstf_code] = (uint32_t)val; + set_double_word(dst_code, dstf_code, val); m_core->icount -= m_core->clock_cycles_2; } @@ -1257,10 +1274,8 @@ void hyperstone_device::hyperstone_sardi() const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; const uint32_t dstf_code = (dst_code + 1) & 0x3f; - uint32_t high_order = m_core->local_regs[dst_code]; - const uint32_t low_order = m_core->local_regs[dstf_code]; - uint64_t val = concat_64(high_order, low_order); + uint64_t val = get_double_word(dst_code, dstf_code); SR &= ~(C_MASK | Z_MASK | N_MASK); @@ -1276,14 +1291,11 @@ void hyperstone_device::hyperstone_sardi() val |= 0xffffffff00000000U << (32 - n); } - high_order = extract_64hi(val); - if (val == 0) SR |= Z_MASK; - SR |= SIGN_TO_N(high_order); + SR |= SIGN64_TO_N(val); - m_core->local_regs[dst_code] = high_order; - m_core->local_regs[dstf_code] = extract_64lo(val); + set_double_word(dst_code, dstf_code, val); m_core->icount -= m_core->clock_cycles_2; } @@ -1304,10 +1316,7 @@ void hyperstone_device::hyperstone_sard() return; } - uint32_t high_order = m_core->local_regs[dst_code]; - const uint32_t low_order = m_core->local_regs[dstf_code]; - - uint64_t val = concat_64(high_order, low_order); + uint64_t val = get_double_word(dst_code, dstf_code); SR &= ~(C_MASK | Z_MASK | N_MASK); @@ -1324,14 +1333,11 @@ void hyperstone_device::hyperstone_sard() val |= 0xffffffff00000000L << (32 - n); } - high_order = extract_64hi(val); - if (val == 0) SR |= Z_MASK; - SR |= SIGN_TO_N(high_order); + SR |= SIGN64_TO_N(val); - m_core->local_regs[dst_code] = high_order; - m_core->local_regs[dstf_code] = extract_64lo(val); + set_double_word(dst_code, dstf_code, val); m_core->icount -= m_core->clock_cycles_2; } @@ -1378,10 +1384,10 @@ void hyperstone_device::hyperstone_shldi() 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_core->local_regs[dst_code]; - uint32_t low_order = m_core->local_regs[dstf_code]; + const uint32_t high_order = m_core->local_regs[dst_code]; + const uint32_t low_order = m_core->local_regs[dstf_code]; - uint64_t val = concat_64(high_order, low_order); + uint64_t val = (uint64_t)high_order << 32 | low_order; SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); @@ -1400,8 +1406,7 @@ void hyperstone_device::hyperstone_shldi() SR |= Z_MASK; SR |= SIGN64_TO_N(val); - m_core->local_regs[dst_code] = extract_64hi(val); - m_core->local_regs[dstf_code] = extract_64lo(val); + set_double_word(dst_code, dstf_code, val); m_core->icount -= m_core->clock_cycles_2; } @@ -1424,10 +1429,10 @@ void hyperstone_device::hyperstone_shld() return; } - uint32_t high_order = m_core->local_regs[dst_code]; - uint32_t low_order = m_core->local_regs[dstf_code]; + const uint32_t high_order = m_core->local_regs[dst_code]; + const uint32_t low_order = m_core->local_regs[dstf_code]; - uint64_t val = concat_64(high_order, low_order); + uint64_t val = (uint64_t)high_order << 32 | low_order; SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK); @@ -1446,8 +1451,7 @@ void hyperstone_device::hyperstone_shld() SR |= Z_MASK; SR |= SIGN64_TO_N(val); - m_core->local_regs[dst_code] = extract_64hi(val); - m_core->local_regs[dstf_code] = extract_64lo(val); + set_double_word(dst_code, dstf_code, val); m_core->icount -= m_core->clock_cycles_2; } @@ -2108,17 +2112,14 @@ void hyperstone_device::hyperstone_mulsu() const uint32_t dreg = (DST_GLOBAL ? m_core->global_regs : m_core->local_regs)[dst_code]; const uint32_t sreg = (SRC_GLOBAL ? m_core->global_regs : m_core->local_regs)[src_code]; - 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); + const uint64_t double_word = SIGNED ? (uint64_t)mul_32x32(sreg, dreg) : mulu_32x32(sreg, dreg); SR &= ~(Z_MASK | N_MASK); if (double_word == 0) SR |= Z_MASK; - SR |= SIGN_TO_N(high_order); + SR |= SIGN64_TO_N(double_word); - (DST_GLOBAL ? m_core->global_regs : m_core->local_regs)[dst_code] = high_order; - (DST_GLOBAL ? m_core->global_regs : m_core->local_regs)[dstf_code] = (uint32_t)double_word; + set_double_word(dst_code, dstf_code, double_word); m_core->icount -= m_core->clock_cycles_6; if(SIGNED == IS_SIGNED && ((int32_t) sreg >= -0x8000 && (int32_t) sreg <= 0x7fff) && ((int32_t) dreg >= -0x8000 && (int32_t) dreg <= 0x7fff)) @@ -2219,6 +2220,11 @@ void hyperstone_device::hyperstone_mul() m_core->icount -= 3 << m_core->clck_scale; } +static inline int32_t mul_16x16(int16_t halfd, int16_t halfs) +{ + return (int32_t)halfd * (int32_t)halfs; +} + void hyperstone_device::hyperstone_extend() { m_instruction_length = (2<<19); @@ -2241,21 +2247,13 @@ void hyperstone_device::hyperstone_extend() // unsigned multiplication, double word product case EMULU: - { - const uint64_t result = (uint64_t)vals * (uint64_t)vald; - m_core->global_regs[14] = (uint32_t)(result >> 32); - m_core->global_regs[15] = (uint32_t)result; + set_double_word(14, 15, mulu_32x32(vals, vald)); break; - } // signed multiplication, double word product case EMULS: - { - const int64_t result = (int64_t)(int32_t)vals * (int64_t)(int32_t)vald; - m_core->global_regs[14] = (uint32_t)(result >> 32); - m_core->global_regs[15] = (uint32_t)result; + set_double_word(14, 15, mul_32x32(vals, vald)); break; - } // signed multiply/add, single word product sum case EMAC: @@ -2264,54 +2262,45 @@ void hyperstone_device::hyperstone_extend() // signed multiply/add, double word product sum case EMACD: - { - int64_t result = (int64_t)concat_64(m_core->global_regs[14], m_core->global_regs[15]) + (int64_t)((int64_t)(int32_t)vals * (int64_t)(int32_t)vald); - m_core->global_regs[14] = (uint32_t)(result >> 32); - m_core->global_regs[15] = (uint32_t)result; + set_double_word(14, 15, get_double_word(14, 15) + mul_32x32(vals, vald)); break; - } - // signed multiply/substract, single word product difference + // signed multiply/subtract, single word product difference case EMSUB: - m_core->global_regs[15] = (int32_t)m_core->global_regs[15] - ((int32_t)vals * (int32_t)vald); + m_core->global_regs[15] -= (int32_t)vals * (int32_t)vald; break; - // signed multiply/substract, double word product difference + // signed multiply/subtract, double word product difference case EMSUBD: - { - int64_t result = (int64_t)concat_64(m_core->global_regs[14], m_core->global_regs[15]) - (int64_t)((int64_t)(int32_t)vals * (int64_t)(int32_t)vald); - m_core->global_regs[14] = (uint32_t)(result >> 32); - m_core->global_regs[15] = (uint32_t)result; + set_double_word(14, 15, get_double_word(14, 15) - mul_32x32(vals, vald)); break; - } // signed half-word multiply/add, single word product sum case EHMAC: - m_core->global_regs[15] = (int32_t)m_core->global_regs[15] + ((int32_t)(vald >> 16) * (int32_t)(vals >> 16)) + ((int32_t)(vald & 0xffff) * (int32_t)(vals & 0xffff)); + m_core->global_regs[15] = (int32_t)m_core->global_regs[15] + mul_16x16(vald >> 16, vals >> 16) + mul_16x16(vald & 0xffff, vals & 0xffff); break; // signed half-word multiply/add, double word product sum case EHMACD: { - int64_t result = (int64_t)concat_64(m_core->global_regs[14], m_core->global_regs[15]) + (int64_t)((int64_t)(int32_t)(vald >> 16) * (int64_t)(int32_t)(vals >> 16)) + ((int64_t)(int32_t)(vald & 0xffff) * (int64_t)(int32_t)(vals & 0xffff)); - m_core->global_regs[14] = (uint32_t)(result >> 32); - m_core->global_regs[15] = (uint32_t)result; + int64_t result = get_double_word(14, 15) + (int64_t)mul_16x16(vald >> 16, vals >> 16) + (int64_t)mul_16x16(vald & 0xffff, vals & 0xffff); + set_double_word(14, 15, result); break; } // half-word complex multiply case EHCMULD: - m_core->global_regs[14] = ((vald >> 16) * (vals >> 16 )) - ((vald & 0xffff) * (vals & 0xffff)); - m_core->global_regs[15] = ((vald >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * (vals >> 16 )); + m_core->global_regs[14] = mul_16x16(vald >> 16, vals >> 16 ) - mul_16x16(vald & 0xffff, vals & 0xffff); + m_core->global_regs[15] = mul_16x16(vald >> 16, vals & 0xffff) + mul_16x16(vald & 0xffff, vals >> 16 ); break; // half-word complex multiply/add case EHCMACD: - m_core->global_regs[14] += ((vald >> 16) * (vals >> 16 )) - ((vald & 0xffff) * (vals & 0xffff)); - m_core->global_regs[15] += ((vald >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * (vals >> 16 )); + m_core->global_regs[14] += mul_16x16(vald >> 16, vals >> 16 ) - mul_16x16(vald & 0xffff, vals & 0xffff); + m_core->global_regs[15] += mul_16x16(vald >> 16, vals & 0xffff) + mul_16x16(vald & 0xffff, vals >> 16 ); break; - // half-word (complex) add/substract + // half-word (complex) add/subtract // Ls is not used and should denote the same register as Ld case EHCSUMD: { @@ -2322,7 +2311,7 @@ void hyperstone_device::hyperstone_extend() break; } - // half-word (complex) add/substract with fixed point adjustment + // half-word (complex) add/subtract with fixed point adjustment // Ls is not used and should denote the same register as Ld case EHCFFTD: { @@ -2333,7 +2322,7 @@ void hyperstone_device::hyperstone_extend() break; } - // half-word (complex) add/substract with fixed point adjustment and shift + // half-word (complex) add/subtract with fixed point adjustment and shift // Ls is not used and should denote the same register as Ld case EHCFFTSD: {