summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/e132xs/e132xsop.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/e132xs/e132xsop.hxx')
-rw-r--r--src/devices/cpu/e132xs/e132xsop.hxx173
1 files changed, 76 insertions, 97 deletions
diff --git a/src/devices/cpu/e132xs/e132xsop.hxx b/src/devices/cpu/e132xs/e132xsop.hxx
index 1a82e5bb57c..03a35898a9d 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 <hyperstone_device::reg_bank DST_GLOBAL>
+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 <hyperstone_device::reg_bank DST_GLOBAL>
+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 <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
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_GLOBAL>(dst_code, dstf_code);
if (sreg == 0 || (SIGNED && (dividend & 0x8000000000000000U)))
{
@@ -1158,14 +1181,10 @@ void hyperstone_device::hyperstone_shrdi()
{
check_delay_PC();
- 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_core->local_regs[dst_code];
- const uint32_t low_order = m_core->local_regs[dstf_code];
+ const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f;
+ const uint32_t dstf_code = (dst_code + 1) & 0x3f;
- uint64_t val = concat_64(high_order, low_order);
+ uint64_t val = get_double_word<LOCAL>(dst_code, dstf_code);
SR &= ~(C_MASK | Z_MASK | N_MASK);
@@ -1177,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<LOCAL>(dst_code, dstf_code, val);
m_core->icount -= m_core->clock_cycles_2;
}
@@ -1196,9 +1212,8 @@ void hyperstone_device::hyperstone_shrd()
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;
+ const uint32_t dst_code = (DST_CODE + fp) & 0x3f;
+ const uint32_t dstf_code = (dst_code + 1) & 0x3f;
if (src_code == dst_code || src_code == dstf_code)
{
@@ -1206,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<LOCAL>(dst_code, dstf_code);
SR &= ~(C_MASK | Z_MASK | N_MASK);
@@ -1222,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<LOCAL>(dst_code, dstf_code, val);
m_core->icount -= m_core->clock_cycles_2;
}
@@ -1261,7 +1275,7 @@ void hyperstone_device::hyperstone_sardi()
const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f;
const uint32_t dstf_code = (dst_code + 1) & 0x3f;
- uint64_t val = concat_64(m_core->local_regs[dst_code], m_core->local_regs[dstf_code]);
+ uint64_t val = get_double_word<LOCAL>(dst_code, dstf_code);
SR &= ~(C_MASK | Z_MASK | N_MASK);
@@ -1279,10 +1293,9 @@ void hyperstone_device::hyperstone_sardi()
if (val == 0)
SR |= Z_MASK;
- SR |= SIGN_TO_N(m_core->local_regs[dst_code]);
+ 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<LOCAL>(dst_code, dstf_code, val);
m_core->icount -= m_core->clock_cycles_2;
}
@@ -1303,7 +1316,7 @@ void hyperstone_device::hyperstone_sard()
return;
}
- uint64_t val = concat_64(m_core->local_regs[dst_code], m_core->local_regs[dstf_code]);
+ uint64_t val = get_double_word<LOCAL>(dst_code, dstf_code);
SR &= ~(C_MASK | Z_MASK | N_MASK);
@@ -1313,22 +1326,18 @@ void hyperstone_device::hyperstone_sard()
{
SR |= (val >> (n - 1)) & 1;
- uint32_t sign_bit = val >> 63;
-
+ const uint64_t sign_bit = val >> 63;
val >>= n;
if (sign_bit)
- {
val |= 0xffffffff00000000L << (32 - n);
- }
}
if (val == 0)
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<LOCAL>(dst_code, dstf_code, val);
m_core->icount -= m_core->clock_cycles_2;
}
@@ -1375,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);
@@ -1397,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<LOCAL>(dst_code, dstf_code, val);
m_core->icount -= m_core->clock_cycles_2;
}
@@ -1421,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);
@@ -1443,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<LOCAL>(dst_code, dstf_code, val);
m_core->icount -= m_core->clock_cycles_2;
}
@@ -1459,7 +1466,7 @@ void hyperstone_device::hyperstone_shl()
uint32_t n = m_core->local_regs[src_code & 0x3f] & 0x1f;
uint32_t base = m_core->local_regs[dst_code & 0x3f]; /* registers offset by frame pointer */
- uint64_t mask = ((((uint64_t)1) << (32 - n)) - 1) ^ 0xffffffff;
+ uint32_t mask = n ? 0xffffffff << (32 - n) : 0;
SR &= ~(C_MASK | V_MASK | Z_MASK | N_MASK);
@@ -1484,14 +1491,7 @@ void hyperstone_device::hyperstone_testlz()
const uint32_t fp = GET_FP;
const uint32_t sreg = m_core->local_regs[(SRC_CODE + fp) & 0x3f];
- uint32_t zeros = 0;
- for (uint32_t mask = 0x80000000; mask != 0; mask >>= 1 )
- {
- if (sreg & mask)
- break;
- else
- zeros++;
- }
+ const uint32_t zeros = count_leading_zeros_32(sreg);
m_core->local_regs[(DST_CODE + fp) & 0x3f] = zeros;
@@ -1513,8 +1513,7 @@ void hyperstone_device::hyperstone_rol()
const uint32_t mask = (uint32_t)(0xffffffff00000000ULL >> n);
#endif
- if (n)
- val = (val << n) | (val >> (32 - n));
+ val = rotl_32(val, n);
#ifdef MISSIONCRAFT_FLAGS
SR &= ~(V_MASK | Z_MASK | C_MASK | N_MASK);
@@ -2069,7 +2068,7 @@ void hyperstone_device::hyperstone_shli()
SR |= (val & (0x80000000 >> (n - 1))) ? 1 : 0;
}
- uint64_t mask = ((1U << (32 - n)) - 1) ^ 0xffffffff;
+ uint32_t mask = n ? 0xffffffff << (32 - n) : 0;
uint32_t val2 = val << n;
if (((val & mask) && (!(val2 & 0x80000000))) || (((val & mask) ^ mask) && (val2 & 0x80000000)))
@@ -2105,20 +2104,17 @@ 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_GLOBAL>(dst_code, dstf_code, double_word);
m_core->icount -= m_core->clock_cycles_6;
- if(SIGNED == IS_SIGNED && (sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff))
+ if(SIGNED == IS_SIGNED && ((int32_t) sreg >= -0x8000 && (int32_t) sreg <= 0x7fff) && ((int32_t) dreg >= -0x8000 && (int32_t) dreg <= 0x7fff))
m_core->icount += m_core->clock_cycles_2;
else if(SIGNED == IS_UNSIGNED && sreg <= 0xffff && dreg <= 0xffff)
m_core->icount += m_core->clock_cycles_2;
@@ -2210,7 +2206,7 @@ void hyperstone_device::hyperstone_mul()
(DST_GLOBAL ? m_core->global_regs : m_core->local_regs)[dst_code] = result;
- if (sreg < 0xffff8000 || sreg > 0x7fff || dreg < 0xffff8000 || dreg > 0x7fff)
+ if ((int32_t)sreg < -0x8000 || (int32_t) sreg > 0x7fff || (int32_t) dreg < -0x8000 || (int32_t) dreg > 0x7fff)
m_core->icount -= 5 << m_core->clck_scale;
else
m_core->icount -= 3 << m_core->clck_scale;
@@ -2238,21 +2234,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<GLOBAL>(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<GLOBAL>(14, 15, mul_32x32(vals, vald));
break;
- }
// signed multiply/add, single word product sum
case EMAC:
@@ -2261,54 +2249,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<GLOBAL>(14, 15, get_double_word<GLOBAL>(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<GLOBAL>(14, 15, get_double_word<GLOBAL>(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] = m_core->global_regs[15] + get_lhs(vald) * get_lhs(vals) + get_rhs(vald) * get_rhs(vals);
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<GLOBAL>(14, 15) + int64_t(get_lhs(vald) * get_lhs(vals)) + int64_t(get_rhs(vald) * get_rhs(vals));
+ set_double_word<GLOBAL>(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] = get_lhs(vald) * get_lhs(vals) - get_rhs(vald) * get_rhs(vals);
+ m_core->global_regs[15] = get_lhs(vald) * get_rhs(vals) + get_rhs(vald) * get_lhs(vals);
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] += get_lhs(vald) * get_lhs(vals) - get_rhs(vald) * get_rhs(vals);
+ m_core->global_regs[15] += get_lhs(vald) * get_rhs(vals) + get_rhs(vald) * get_lhs(vals);
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:
{
@@ -2319,7 +2298,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:
{
@@ -2330,7 +2309,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:
{