summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-03-09 03:15:07 +1100
committer Vas Crabb <vas@vastheman.com>2026-03-09 03:15:07 +1100
commite916964bb3b084a70ddc40c665cd34cf9b596a9f (patch)
tree139a6a44b3f6cb0098a3d5475f6ae3eb54aaff8f /src/devices/cpu
parente6a9e0caa15ce23e659f3e5b8a0c0bb9c0fb3061 (diff)
cpu/sharc: Better ALU emulation for interpreter:
* Implemented fixed-point ALU overflow sticky flag (AOS). * More accurate implementation of Fn = -Fx, Fn = ABS Fx and Fn = PASS Fx. * Implemented Rn = ABS Rx and Fn = ABS(Fx - Fy). * Sorted computer function declarations and definitions to match order of instruction listings in documentation.
Diffstat (limited to 'src/devices/cpu')
-rw-r--r--src/devices/cpu/sharc/compute.hxx791
-rw-r--r--src/devices/cpu/sharc/sharc.h63
-rw-r--r--src/devices/cpu/sharc/sharcinternal.ipp1
-rw-r--r--src/devices/cpu/sharc/sharcops.hxx4
4 files changed, 468 insertions, 391 deletions
diff --git a/src/devices/cpu/sharc/compute.hxx b/src/devices/cpu/sharc/compute.hxx
index 1a6452a9739..f871ac04c81 100644
--- a/src/devices/cpu/sharc/compute.hxx
+++ b/src/devices/cpu/sharc/compute.hxx
@@ -5,16 +5,16 @@
#include <cmath>
#include <limits>
-#define CLEAR_ALU_FLAGS() do { m_core->astat &= ~(AZ|AN|AV|AC|AS|AI); } while (false)
+#define CLEAR_ALU_FLAGS() do { m_core->astat &= ~(AZ | AN | AV | AC | AS | AI); } while (false)
-#define SET_FLAG_AZ(r) do { m_core->astat |= (((r) == 0) ? AZ : 0); } while (false)
-#define SET_FLAG_AN(r) do { m_core->astat |= (((r) & 0x80000000) ? AN : 0); } while (false)
-#define SET_FLAG_AC_ADD(r,a,b) do { m_core->astat |= ((uint32_t(r) < uint32_t(a)) ? AC : 0); } while (false)
-#define SET_FLAG_AV_ADD(r,a,b) do { m_core->astat |= ((~((a) ^ (b)) & ((a) ^ (r)) & 0x80000000) ? AV : 0); } while (false)
-#define SET_FLAG_AC_SUB(r,a,b) do { m_core->astat |= ((uint32_t(r) <= uint32_t(a)) ? AC : 0); } while (false)
-#define SET_FLAG_AV_SUB(r,a,b) do { m_core->astat |= ((((a) ^ (b)) & ((a) ^ (r)) & 0x80000000) ? AV : 0); } while (false)
+#define SET_FLAG_AZ(r) do { m_core->astat |= ((r) == 0) ? AZ : 0; } while (false)
+#define SET_FLAG_AN(r) do { m_core->astat |= ((r) & 0x80000000) ? AN : 0; } while (false)
+#define SET_FLAG_AC_ADD(r,a,b) do { m_core->astat |= (uint32_t(r) < uint32_t(a)) ? AC : 0; } while (false)
+#define SET_FLAG_AC_SUB(r,a,b) do { m_core->astat |= (uint32_t(r) <= uint32_t(a)) ? AC : 0; } while (false)
+#define SET_FLAG_AV_ADD(r,a,b) do { if (~((a) ^ (b)) & ((a) ^ (r)) & 0x80000000) { m_core->astat |= AV; m_core->stky |= AOS; } } while (false)
+#define SET_FLAG_AV_SUB(r,a,b) do { if (((a) ^ (b)) & ((a) ^ (r)) & 0x80000000) { m_core->astat |= AV; m_core->stky |= AOS; } } while (false)
-#define CLEAR_MULTIPLIER_FLAGS() do { m_core->astat &= ~(MN|MV|MU|MI); } while (false)
+#define CLEAR_MULTIPLIER_FLAGS() do { m_core->astat &= ~(MN | MV | MU | MI); } while (false)
#define SET_FLAG_MN(r) do { m_core->astat |= (((r) & 0x80000000) ? MN : 0); } while (false)
#define SET_FLAG_MV(r) do { m_core->astat |= (((uint32_t((r) >> 32) != 0) && (uint32_t((r) >> 32) != 0xffffffff)) ? MV : 0); } while (false)
@@ -29,6 +29,7 @@ constexpr bool IS_FLOAT_ZERO(uint32_t r) { return (r & (FLOAT_EXPONENT_MA
constexpr bool IS_FLOAT_DENORMAL(uint32_t r) { return ((r & FLOAT_EXPONENT_MASK) == 0) && ((r & FLOAT_MANTISSA_MASK) != 0); }
constexpr bool IS_FLOAT_NAN(uint32_t r) { return ((r & FLOAT_EXPONENT_MASK) == FLOAT_EXPONENT_MASK) && ((r & FLOAT_MANTISSA_MASK) != 0); }
constexpr bool IS_FLOAT_INFINITY(uint32_t r) { return (r & (FLOAT_EXPONENT_MASK | FLOAT_MANTISSA_MASK)) == FLOAT_INFINITY; }
+constexpr bool IS_FLOAT_NEGATIVE(uint32_t r) { return (r & FLOAT_SIGN_MASK) && !IS_FLOAT_NAN(r); }
/*****************************************************************************/
@@ -107,6 +108,33 @@ const uint32_t adsp21062_device::rsqrts_mantissa_lookup[128] =
0x00370000, 0x00370000, 0x00360000, 0x00350000,
};
+uint32_t adsp21062_device::SCALB(SHARC_REG rx, int ry)
+{
+ uint32_t const mantissa = rx.r & FLOAT_MANTISSA_MASK;
+ uint32_t const sign = rx.r & FLOAT_SIGN_MASK;
+
+ int exponent = float_get_unbiased_exponent(rx.r);
+ exponent += int32_t(REG(ry));
+
+ if (exponent > 127)
+ {
+ // overflow
+ m_core->astat |= AV;
+ return sign | FLOAT_INFINITY;
+ }
+ else if (exponent < -126)
+ {
+ // denormal
+ m_core->astat |= AZ;
+ return sign;
+ }
+ else
+ {
+ return sign | float_make_biased_exponent(exponent) | mantissa;
+ }
+}
+
+
/*****************************************************************************/
/* Integer ALU operations */
@@ -126,7 +154,6 @@ void adsp21062_device::compute_add(int rn, int rx, int ry)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -146,7 +173,6 @@ void adsp21062_device::compute_sub(int rn, int rx, int ry)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -169,7 +195,6 @@ void adsp21062_device::compute_add_ci(int rn, int rx, int ry)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -191,20 +216,6 @@ void adsp21062_device::compute_sub_ci(int rn, int rx, int ry)
SET_FLAG_AZ(r);
REG(rn) = r;
-
- m_core->astat &= ~AF;
-}
-
-/* Rn = Rx AND Ry */
-void adsp21062_device::compute_and(int rn, int rx, int ry)
-{
- uint32_t const r = REG(rx) & REG(ry);
-
- CLEAR_ALU_FLAGS();
- SET_FLAG_AN(r);
- SET_FLAG_AZ(r);
- REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -228,45 +239,6 @@ void adsp21062_device::compute_comp(int rx, int ry)
m_core->astat &= ~AF;
}
-/* Rn = PASS Rx */
-void adsp21062_device::compute_pass(int rn, int rx)
-{
- CLEAR_ALU_FLAGS();
- /* TODO: floating-point extension field is set to 0 */
-
- REG(rn) = REG(rx);
- if (REG(rn) == 0)
- m_core->astat |= AZ;
- if (REG(rn) & 0x80000000)
- m_core->astat |= AN;
-
- m_core->astat &= ~AF;
-}
-
-/* Rn = Rx XOR Ry */
-void adsp21062_device::compute_xor(int rn, int rx, int ry)
-{
- uint32_t const r = REG(rx) ^ REG(ry);
- CLEAR_ALU_FLAGS();
- SET_FLAG_AN(r);
- SET_FLAG_AZ(r);
- REG(rn) = r;
-
- m_core->astat &= ~AF;
-}
-
-/* Rn = Rx OR Ry */
-void adsp21062_device::compute_or(int rn, int rx, int ry)
-{
- uint32_t const r = REG(rx) | REG(ry);
- CLEAR_ALU_FLAGS();
- SET_FLAG_AN(r);
- SET_FLAG_AZ(r);
- REG(rn) = r;
-
- m_core->astat &= ~AF;
-}
-
/* Rn = Rx + CI */
void adsp21062_device::compute_add_ci(int rn, int rx)
{
@@ -284,7 +256,6 @@ void adsp21062_device::compute_add_ci(int rn, int rx)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -305,7 +276,6 @@ void adsp21062_device::compute_sub_ci(int rn, int rx)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -325,7 +295,6 @@ void adsp21062_device::compute_inc(int rn, int rx)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
@@ -345,285 +314,160 @@ void adsp21062_device::compute_dec(int rn, int rx)
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
-/* Rn = MIN(Rx, Ry) */
-void adsp21062_device::compute_min(int rn, int rx, int ry)
+/* Rn = -Rx */
+void adsp21062_device::compute_neg(int rn, int rx)
{
- uint32_t const r = std::min(int32_t(REG(rx)), int32_t(REG(ry)));
+ uint32_t r = -int32_t(REG(rx));
CLEAR_ALU_FLAGS();
+ SET_FLAG_AV_SUB(r, 0, REG(rx));
+ SET_FLAG_AC_SUB(r, 0, REG(rx));
+
+ if ((m_core->mode1 & MODE1_ALUSAT) && (m_core->astat & AV))
+ SATURATE(r);
+
SET_FLAG_AN(r);
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
-/* Rn = MAX(Rx, Ry) */
-void adsp21062_device::compute_max(int rn, int rx, int ry)
+/* Rn = ABS Rx */
+void adsp21062_device::compute_abs(int rn, int rx)
{
- uint32_t const r = std::max(int32_t(REG(rx)), int32_t(REG(ry)));
+ uint32_t r = std::abs(int32_t(REG(rx)));
CLEAR_ALU_FLAGS();
+ if (int32_t(r) < 0)
+ {
+ m_core->astat |= AV;
+ m_core->stky |= AOS;
+ if (m_core->mode1 & MODE1_ALUSAT)
+ r = 0x7fffffff;
+ }
+
SET_FLAG_AN(r);
SET_FLAG_AZ(r);
+ m_core->astat |= (int32_t(REG(rx)) < 0) ? AS : 0;
REG(rn) = r;
-
m_core->astat &= ~AF;
}
-/* Rn = CLIP Rx BY Ry */
-void adsp21062_device::compute_clip(int rn, int rx, int ry)
+/* Rn = PASS Rx */
+void adsp21062_device::compute_pass(int rn, int rx)
{
- const int32_t absry = std::abs(int32_t(REG(ry)));
- const uint32_t r = std::clamp(int32_t(REG(rx)), -absry, absry);
-
CLEAR_ALU_FLAGS();
- SET_FLAG_AN(r);
- SET_FLAG_AZ(r);
+ /* TODO: floating-point extension field is set to 0 */
- REG(rn) = r;
+ REG(rn) = REG(rx);
+ if (REG(rn) == 0)
+ m_core->astat |= AZ;
+ if (REG(rn) & 0x80000000)
+ m_core->astat |= AN;
m_core->astat &= ~AF;
}
-/* Rn = -Rx */
-void adsp21062_device::compute_neg(int rn, int rx)
+/* Rn = Rx AND Ry */
+void adsp21062_device::compute_and(int rn, int rx, int ry)
{
- uint32_t r = -int32_t(REG(rx));
+ uint32_t const r = REG(rx) & REG(ry);
CLEAR_ALU_FLAGS();
- SET_FLAG_AV_SUB(r, 0, REG(rx));
- SET_FLAG_AC_SUB(r, 0, REG(rx));
-
- if ((m_core->mode1 & MODE1_ALUSAT) && (m_core->astat & AV))
- SATURATE(r);
-
SET_FLAG_AN(r);
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
-/* Rn = NOT Rx */
-void adsp21062_device::compute_not(int rn, int rx)
+/* Rn = Rx OR Ry */
+void adsp21062_device::compute_or(int rn, int rx, int ry)
{
- uint32_t const r = ~REG(rx);
+ uint32_t const r = REG(rx) | REG(ry);
CLEAR_ALU_FLAGS();
SET_FLAG_AN(r);
SET_FLAG_AZ(r);
REG(rn) = r;
-
m_core->astat &= ~AF;
}
-/*****************************************************************************/
-/* Floating-point ALU operations */
-
-uint32_t adsp21062_device::SCALB(SHARC_REG rx, int ry)
-{
- uint32_t mantissa = rx.r & FLOAT_MANTISSA_MASK;
- uint32_t sign = rx.r & FLOAT_SIGN_MASK;
-
- int exponent = float_get_unbiased_exponent(rx.r);
- exponent += int32_t(REG(ry));
-
- if (exponent > 127)
- {
- // overflow
- m_core->astat |= AV;
- return sign | FLOAT_INFINITY;
- }
- else if (exponent < -126)
- {
- // denormal
- m_core->astat |= AZ;
- return sign;
- }
- else
- {
- return sign | float_make_biased_exponent(exponent) | mantissa;
- }
-}
-
-/* Fn = FLOAT Rx */
-void adsp21062_device::compute_float(int rn, int rx)
+/* Rn = Rx XOR Ry */
+void adsp21062_device::compute_xor(int rn, int rx, int ry)
{
- // verified
- FREG(rn) = (float)(int32_t)REG(rx);
+ uint32_t const r = REG(rx) ^ REG(ry);
CLEAR_ALU_FLAGS();
- // AN
- SET_FLAG_AN(REG(rn));
- // AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
- // AUS
- m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
- /* TODO: AV flag */
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
- m_core->astat |= AF;
+ REG(rn) = r;
+ m_core->astat &= ~AF;
}
-/* Rn = FIX Fx */
-void adsp21062_device::compute_fix(int rn, int rx)
+/* Rn = NOT Rx */
+void adsp21062_device::compute_not(int rn, int rx)
{
- int32_t alu_i;
- SHARC_REG r_alu;
-
- r_alu.f = FREG(rx);
- if (m_core->mode1 & MODE1_TRUNCATE)
- {
- alu_i = int32_t(floorf(r_alu.f));
- }
- else
- {
- alu_i = int32_t(nearbyintf(r_alu.f)); // assume rounding mode is set to FE_TONEAREST
- }
+ uint32_t const r = ~REG(rx);
CLEAR_ALU_FLAGS();
- SET_FLAG_AN(alu_i);
- // AZ
- SET_FLAG_AZ(alu_i);
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
- /* TODO: AV flag */
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
- REG(rn) = alu_i;
- m_core->astat |= AF;
+ REG(rn) = r;
+ m_core->astat &= ~AF;
}
-/* Rn = FIX Fx BY Ry */
-void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry)
+/* Rn = MIN(Rx, Ry) */
+void adsp21062_device::compute_min(int rn, int rx, int ry)
{
- int32_t alu_i;
- SHARC_REG r_alu;
-
- r_alu.r = SCALB(m_core->r[rx], ry);
- if (m_core->mode1 & MODE1_TRUNCATE)
- {
- alu_i = int32_t(floorf(r_alu.f));
- }
- else
- {
- alu_i = int32_t(nearbyintf(r_alu.f)); // assume rounding mode is set to FE_TONEAREST
- }
+ uint32_t const r = std::min(int32_t(REG(rx)), int32_t(REG(ry)));
CLEAR_ALU_FLAGS();
- SET_FLAG_AN(alu_i);
- // AZ
- SET_FLAG_AZ(alu_i);
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
- /* TODO: AV flag */
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
- REG(rn) = alu_i;
- m_core->astat |= AF;
+ REG(rn) = r;
+ m_core->astat &= ~AF;
}
-/* Fn = FLOAT Rx BY Ry */
-void adsp21062_device::compute_float_scaled(int rn, int rx, int ry)
+/* Rn = MAX(Rx, Ry) */
+void adsp21062_device::compute_max(int rn, int rx, int ry)
{
- SHARC_REG x;
- x.f = float(int32_t(REG(rx)));
+ uint32_t const r = std::max(int32_t(REG(rx)), int32_t(REG(ry)));
- // verified
CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
- REG(rn) = SCALB(x, ry);
-
- // AN
- SET_FLAG_AN(REG(rn));
- // AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
-
- m_core->astat |= AF;
+ REG(rn) = r;
+ m_core->astat &= ~AF;
}
-/* Rn = LOGB Fx */
-void adsp21062_device::compute_logb(int rn, int rx)
+/* Rn = CLIP Rx BY Ry */
+void adsp21062_device::compute_clip(int rn, int rx, int ry)
{
- // verified
- uint32_t r = REG(rx);
+ const int32_t absry = std::abs(int32_t(REG(ry)));
+ const uint32_t r = std::clamp(int32_t(REG(rx)), -absry, absry);
CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
- if (IS_FLOAT_INFINITY(REG(rx)))
- {
- REG(rn) = FLOAT_INFINITY;
-
- m_core->astat |= AV;
- }
- else if (IS_FLOAT_ZERO(REG(rx)))
- {
- REG(rn) = FLOAT_SIGN_MASK | FLOAT_INFINITY;
-
- m_core->astat |= AV;
- }
- else if (IS_FLOAT_NAN(REG(rx)))
- {
- REG(rn) = 0xffffffff;
-
- m_core->astat |= AI;
- m_core->stky |= AIS;
- }
- else
- {
- int exponent = float_get_unbiased_exponent(r);
-
- // AN
- SET_FLAG_AN(exponent);
- // AZ
- SET_FLAG_AZ(exponent);
-
- REG(rn) = exponent;
- }
- m_core->astat |= AF;
+ REG(rn) = r;
+ m_core->astat &= ~AF;
}
-/* Fn = SCALB Fx BY Fy */
-void adsp21062_device::compute_scalb(int rn, int rx, int ry)
-{
- // verified
- SHARC_REG r;
- CLEAR_ALU_FLAGS();
-
- if (IS_FLOAT_NAN(REG(rx)))
- {
- m_core->astat |= AI;
- m_core->stky |= AIS;
-
- REG(rn) = 0xffffffff;
- }
- else
- {
- r.r = SCALB(m_core->r[rx], ry);
-
- // AN
- SET_FLAG_AN(r.r);
- // AZ
- m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
- // AUS
- m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
- FREG(rn) = r.f;
- }
- m_core->astat |= AF;
-}
+/*****************************************************************************/
+/* Floating-point ALU operations */
/* Fn = Fx + Fy */
void adsp21062_device::compute_fadd(int rn, int rx, int ry)
@@ -649,11 +493,11 @@ void adsp21062_device::compute_fadd(int rn, int rx, int ry)
m_core->astat |= AF;
}
-/* Fn = (Fx + Fy) / 2 */
-void adsp21062_device::compute_favg(int rn, int rx, int ry)
+/* Fn = Fx - Fy */
+void adsp21062_device::compute_fsub(int rn, int rx, int ry)
{
SHARC_REG r;
- r.f = (FREG(rx) + FREG(ry)) / 2.0f;
+ r.f = FREG(rx) - FREG(ry);
CLEAR_ALU_FLAGS();
// AN
@@ -673,22 +517,21 @@ void adsp21062_device::compute_favg(int rn, int rx, int ry)
m_core->astat |= AF;
}
-/* Fn = Fx - Fy */
-void adsp21062_device::compute_fsub(int rn, int rx, int ry)
+/* Fn = ABS(Fx + Fy) */
+void adsp21062_device::compute_fadd_abs(int rn, int rx, int ry)
{
SHARC_REG r;
- r.f = FREG(rx) - FREG(ry);
+ r.f = fabsf(FREG(rx) + FREG(ry));
CLEAR_ALU_FLAGS();
- // AN
- m_core->astat |= (r.f < 0.0f) ? AN : 0;
// AZ
m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
// AUS
m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
// AI
m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
- /* TODO: AV flag */
+ // AV
+ m_core->astat |= (IS_FLOAT_INFINITY(r.r)) ? AV : 0;
// AIS
if (m_core->astat & AI) m_core->stky |= AIS;
@@ -697,19 +540,45 @@ void adsp21062_device::compute_fsub(int rn, int rx, int ry)
m_core->astat |= AF;
}
-/* Fn = -Fx */
-void adsp21062_device::compute_fneg(int rn, int rx)
+/* Fn = ABS(Fx - Fy) */
+void adsp21062_device::compute_fsub_abs(int rn, int rx, int ry)
{
SHARC_REG r;
- r.f = -FREG(rx);
+ r.f = fabsf(FREG(rx) - FREG(ry));
CLEAR_ALU_FLAGS();
// AZ
- m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AUS
+ m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
+ // AI
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ // AV
+ m_core->astat |= (IS_FLOAT_INFINITY(r.r)) ? AV : 0;
+
+ // AIS
+ if (m_core->astat & AI) m_core->stky |= AIS;
+
+ FREG(rn) = r.f;
+ m_core->astat |= AF;
+}
+
+/* Fn = (Fx + Fy) / 2 */
+void adsp21062_device::compute_favg(int rn, int rx, int ry)
+{
+ SHARC_REG r;
+ r.f = (FREG(rx) + FREG(ry)) / 2.0f;
+
+ CLEAR_ALU_FLAGS();
// AN
m_core->astat |= (r.f < 0.0f) ? AN : 0;
+ // AZ
+ m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AUS
+ m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
// AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
// AIS
if (m_core->astat & AI) m_core->stky |= AIS;
@@ -748,107 +617,266 @@ void adsp21062_device::compute_fcomp(int rx, int ry)
m_core->astat |= AF;
}
-/* Fn = ABS(Fx + Fy) */
-void adsp21062_device::compute_fabs_plus(int rn, int rx, int ry)
+/* Fn = -Fx */
+void adsp21062_device::compute_fneg(int rn, int rx)
{
+ CLEAR_ALU_FLAGS();
+
SHARC_REG r;
- r.f = fabsf(FREG(rx) + FREG(ry));
+ if (IS_FLOAT_NAN(REG(rx)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ if (IS_FLOAT_DENORMAL(REG(rx)))
+ {
+ r.r = ~REG(rx) & FLOAT_SIGN_MASK;
+ m_core->astat |= AZ;
+ }
+ else
+ {
+ r.r = REG(rx) ^ FLOAT_SIGN_MASK;
+ m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
+ }
+ m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
+ }
+
+ FREG(rn) = r.f;
+ m_core->astat |= AF;
+}
+/* Fn = ABS Fx */
+void adsp21062_device::compute_fabs(int rn, int rx)
+{
CLEAR_ALU_FLAGS();
- // AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
- // AUS
- m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
- // AV
- m_core->astat |= (IS_FLOAT_INFINITY(r.r)) ? AV : 0;
- // AIS
- if (m_core->astat & AI) m_core->stky |= AIS;
+ SHARC_REG r;
+ if (IS_FLOAT_NAN(REG(rx)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ if (IS_FLOAT_DENORMAL(REG(rx)))
+ {
+ r.r = 0;
+ m_core->astat |= AZ;
+ }
+ else
+ {
+ r.r = REG(rx) & ~FLOAT_SIGN_MASK;
+ m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
+ }
+ m_core->astat |= (REG(rx) & FLOAT_SIGN_MASK) ? AS : 0;
+ }
FREG(rn) = r.f;
m_core->astat |= AF;
}
-/* Fn = MAX(Fx, Fy) */
-void adsp21062_device::compute_fmax(int rn, int rx, int ry)
+/* Fn = PASS Fx */
+void adsp21062_device::compute_fpass(int rn, int rx)
{
+ CLEAR_ALU_FLAGS();
+
+ SHARC_REG r;
+ if (IS_FLOAT_NAN(REG(rx)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ if (IS_FLOAT_DENORMAL(REG(rx)))
+ {
+ r.r = REG(rx) & FLOAT_SIGN_MASK;
+ m_core->astat |= AZ;
+ }
+ else
+ {
+ r.r = REG(rx);
+ m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
+ }
+ m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
+ }
+
+ FREG(rn) = r.f;
+ m_core->astat |= AF;
+}
+
+/* Fn = SCALB Fx BY Fy */
+void adsp21062_device::compute_scalb(int rn, int rx, int ry)
+{
+ // verified
+ SHARC_REG r;
+ CLEAR_ALU_FLAGS();
+
+ if (IS_FLOAT_NAN(REG(rx)))
+ {
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+
+ REG(rn) = FLOAT_CANONICAL_NAN;
+ }
+ else
+ {
+ r.r = SCALB(m_core->r[rx], ry);
+
+ // AN
+ SET_FLAG_AN(r.r);
+ // AZ
+ m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
+ // AUS
+ m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
+
+ FREG(rn) = r.f;
+ }
+ m_core->astat |= AF;
+}
+
+/* Rn = LOGB Fx */
+void adsp21062_device::compute_logb(int rn, int rx)
+{
+ // verified
+ uint32_t r = REG(rx);
+
+ CLEAR_ALU_FLAGS();
+
+ if (IS_FLOAT_INFINITY(REG(rx)))
+ {
+ REG(rn) = FLOAT_INFINITY;
+
+ m_core->astat |= AV;
+ }
+ else if (IS_FLOAT_ZERO(REG(rx)))
+ {
+ REG(rn) = FLOAT_SIGN_MASK | FLOAT_INFINITY;
+
+ m_core->astat |= AV;
+ }
+ else if (IS_FLOAT_NAN(REG(rx)))
+ {
+ REG(rn) = FLOAT_CANONICAL_NAN;
+
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ int exponent = float_get_unbiased_exponent(r);
+
+ // AN
+ SET_FLAG_AN(exponent);
+ // AZ
+ SET_FLAG_AZ(exponent);
+
+ REG(rn) = exponent;
+ }
+ m_core->astat |= AF;
+}
+
+/* Rn = FIX Fx BY Ry */
+void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry)
+{
+ int32_t alu_i;
SHARC_REG r_alu;
- r_alu.f = std::max(FREG(rx), FREG(ry));
+ r_alu.r = SCALB(m_core->r[rx], ry);
+ if (m_core->mode1 & MODE1_TRUNCATE)
+ {
+ alu_i = int32_t(floorf(r_alu.f));
+ }
+ else
+ {
+ alu_i = int32_t(nearbyintf(r_alu.f)); // assume rounding mode is set to FE_TONEAREST
+ }
CLEAR_ALU_FLAGS();
- m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ SET_FLAG_AN(alu_i);
// AZ
- m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ SET_FLAG_AZ(alu_i);
// AU
m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
// AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
/* TODO: AV flag */
- FREG(rn) = r_alu.f;
+ REG(rn) = alu_i;
m_core->astat |= AF;
}
-/* Fn = MIN(Fx, Fy) */
-void adsp21062_device::compute_fmin(int rn, int rx, int ry)
+/* Rn = FIX Fx */
+void adsp21062_device::compute_fix(int rn, int rx)
{
+ int32_t alu_i;
SHARC_REG r_alu;
- r_alu.f = std::min(FREG(rx), FREG(ry));
+ r_alu.f = FREG(rx);
+ if (m_core->mode1 & MODE1_TRUNCATE)
+ {
+ alu_i = int32_t(floorf(r_alu.f));
+ }
+ else
+ {
+ alu_i = int32_t(nearbyintf(r_alu.f)); // assume rounding mode is set to FE_TONEAREST
+ }
CLEAR_ALU_FLAGS();
- m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ SET_FLAG_AN(alu_i);
// AZ
- m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ SET_FLAG_AZ(alu_i);
// AU
m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
// AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
/* TODO: AV flag */
- FREG(rn) = r_alu.f;
+ REG(rn) = alu_i;
m_core->astat |= AF;
}
-/* Fn = COPYSIGN(Fx, Fy) */
-void adsp21062_device::compute_fcopysign(int rn, int rx, int ry)
+/* Fn = FLOAT Rx BY Ry */
+void adsp21062_device::compute_float_scaled(int rn, int rx, int ry)
{
- SHARC_REG r_alu;
-
- r_alu.r = (REG(rx) & (FLOAT_EXPONENT_MASK | FLOAT_MANTISSA_MASK)) | (REG(ry) & FLOAT_SIGN_MASK); // TODO DENORM and NAN cases ?
+ SHARC_REG x;
+ x.f = float(int32_t(REG(rx)));
+ // verified
CLEAR_ALU_FLAGS();
- m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
+
+ REG(rn) = SCALB(x, ry);
+
+ // AN
+ SET_FLAG_AN(REG(rn));
// AZ
- m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
+ // AU
+ m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
- FREG(rn) = r_alu.f;
m_core->astat |= AF;
}
-/* Fn = CLIP Fx BY Fy */
-void adsp21062_device::compute_fclip(int rn, int rx, int ry)
+/* Fn = FLOAT Rx */
+void adsp21062_device::compute_float(int rn, int rx)
{
- SHARC_REG r_alu;
-
- const float absry = fabsf(FREG(ry));
- r_alu.f = std::clamp(FREG(rx), -absry, absry);
+ // verified
+ FREG(rn) = (float)(int32_t)REG(rx);
CLEAR_ALU_FLAGS();
- SET_FLAG_AN(r_alu.r);
+ // AN
+ SET_FLAG_AN(REG(rn));
// AZ
- m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
+ // AUS
+ m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
+ /* TODO: AV flag */
- FREG(rn) = r_alu.f;
m_core->astat |= AF;
}
@@ -863,7 +891,7 @@ void adsp21062_device::compute_recips(int rn, int rx)
if (IS_FLOAT_NAN(REG(rx)))
{
// NaN
- r = 0xffffffff;
+ r = FLOAT_CANONICAL_NAN;
// AI
m_core->astat |= AI;
@@ -904,10 +932,8 @@ void adsp21062_device::compute_recips(int rn, int rx)
m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
}
- // AF
- m_core->astat |= AF;
-
REG(rn) = r;
+ m_core->astat |= AF;
}
/* Fn = RSQRTS Fx */
@@ -919,12 +945,12 @@ void adsp21062_device::compute_rsqrts(int rn, int rx)
if (uint32_t(REG(rx)) > 0x80000000)
{
// non-zero negative
- r = 0xffffffff;
+ r = FLOAT_CANONICAL_NAN;
}
else if (IS_FLOAT_NAN(REG(rx)))
{
// NaN
- r = 0xffffffff;
+ r = FLOAT_CANONICAL_NAN;
}
else
{
@@ -948,60 +974,93 @@ void adsp21062_device::compute_rsqrts(int rn, int rx)
m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || (REG(rx) & FLOAT_SIGN_MASK)) ? AI : 0;
// AIS
if (m_core->astat & AI) m_core->stky |= AIS;
- // AF
- m_core->astat |= AF;
REG(rn) = r;
+ m_core->astat |= AF;
}
+/* Fn = COPYSIGN(Fx, Fy) */
+void adsp21062_device::compute_fcopysign(int rn, int rx, int ry)
+{
+ SHARC_REG r_alu;
-/* Fn = PASS Fx */
-void adsp21062_device::compute_fpass(int rn, int rx)
+ r_alu.r = (REG(rx) & (FLOAT_EXPONENT_MASK | FLOAT_MANTISSA_MASK)) | (REG(ry) & FLOAT_SIGN_MASK); // TODO DENORM and NAN cases ?
+
+ CLEAR_ALU_FLAGS();
+ m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ // AZ
+ m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AI
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+
+ FREG(rn) = r_alu.f;
+ m_core->astat |= AF;
+}
+
+/* Fn = MIN(Fx, Fy) */
+void adsp21062_device::compute_fmin(int rn, int rx, int ry)
{
- SHARC_REG r;
- r.f = FREG(rx);
+ SHARC_REG r_alu;
+
+ r_alu.f = std::min(FREG(rx), FREG(ry));
CLEAR_ALU_FLAGS();
- // AN
- m_core->astat |= (r.f < 0.0f) ? AN : 0;
+ m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
// AZ
- m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
// AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
- FREG(rn) = r.f;
+ FREG(rn) = r_alu.f;
m_core->astat |= AF;
}
-/* Fn = ABS Fx */
-void adsp21062_device::compute_fabs(int rn, int rx)
+/* Fn = MAX(Fx, Fy) */
+void adsp21062_device::compute_fmax(int rn, int rx, int ry)
{
- SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)))
- {
- r.r = 0xffffffff;
- }
- else if (IS_FLOAT_DENORMAL(REG(rx)))
- {
- r.r = 0;
- }
- else
- {
- r.r = REG(rx) & 0x7fffffff;
- }
+ SHARC_REG r_alu;
+
+ r_alu.f = std::max(FREG(rx), FREG(ry));
CLEAR_ALU_FLAGS();
+ m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
// AZ
- m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
- // AS
- m_core->astat |= (REG(rx) < 0.0f) ? AS : 0;
+ m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
// AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
- FREG(rn) = r.f;
+ FREG(rn) = r_alu.f;
m_core->astat |= AF;
}
+/* Fn = CLIP Fx BY Fy */
+void adsp21062_device::compute_fclip(int rn, int rx, int ry)
+{
+ SHARC_REG r_alu;
+
+ const float absry = fabsf(FREG(ry));
+ r_alu.f = std::clamp(FREG(rx), -absry, absry);
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r_alu.r);
+ // AZ
+ m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+
+ FREG(rn) = r_alu.f;
+ m_core->astat |= AF;
+}
+
+
/*****************************************************************************/
/* Multiplier opcodes */
diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h
index fd41dd9d7b2..93f0d321386 100644
--- a/src/devices/cpu/sharc/sharc.h
+++ b/src/devices/cpu/sharc/sharc.h
@@ -388,56 +388,66 @@ private:
void sharcop_nop();
void sharcop_idle();
[[noreturn]] void sharcop_unimplemented() ATTR_COLD;
+ inline uint32_t SCALB(SHARC_REG rx, int ry);
+
+ // ALU fixed-point
inline void compute_add(int rn, int rx, int ry);
inline void compute_sub(int rn, int rx, int ry);
inline void compute_add_ci(int rn, int rx, int ry);
inline void compute_sub_ci(int rn, int rx, int ry);
- inline void compute_and(int rn, int rx, int ry);
inline void compute_comp(int rx, int ry);
- inline void compute_pass(int rn, int rx);
- inline void compute_xor(int rn, int rx, int ry);
- inline void compute_or(int rn, int rx, int ry);
inline void compute_add_ci(int rn, int rx);
inline void compute_sub_ci(int rn, int rx);
inline void compute_inc(int rn, int rx);
inline void compute_dec(int rn, int rx);
+ inline void compute_neg(int rn, int rx);
+ inline void compute_abs(int rn, int rx);
+ inline void compute_pass(int rn, int rx);
+ inline void compute_and(int rn, int rx, int ry);
+ inline void compute_or(int rn, int rx, int ry);
+ inline void compute_xor(int rn, int rx, int ry);
+ inline void compute_not(int rn, int rx);
inline void compute_min(int rn, int rx, int ry);
inline void compute_max(int rn, int rx, int ry);
inline void compute_clip(int rn, int rx, int ry);
- inline void compute_neg(int rn, int rx);
- inline void compute_not(int rn, int rx);
- inline uint32_t SCALB(SHARC_REG rx, int ry);
- inline void compute_float(int rn, int rx);
- inline void compute_fix(int rn, int rx);
- inline void compute_fix_scaled(int rn, int rx, int ry);
- inline void compute_float_scaled(int rn, int rx, int ry);
- inline void compute_logb(int rn, int rx);
- inline void compute_scalb(int rn, int rx, int ry);
+
+ // ALU floating-point
inline void compute_fadd(int rn, int rx, int ry);
inline void compute_fsub(int rn, int rx, int ry);
+ inline void compute_fadd_abs(int rn, int rx, int ry);
+ inline void compute_fsub_abs(int rn, int rx, int ry);
inline void compute_favg(int rn, int rx, int ry);
- inline void compute_fneg(int rn, int rx);
inline void compute_fcomp(int rx, int ry);
- inline void compute_fabs_plus(int rn, int rx, int ry);
- inline void compute_fmax(int rn, int rx, int ry);
- inline void compute_fmin(int rn, int rx, int ry);
- inline void compute_fcopysign(int rn, int rx, int ry);
- inline void compute_fclip(int rn, int rx, int ry);
+ inline void compute_fneg(int rn, int rx);
+ inline void compute_fabs(int rn, int rx);
+ inline void compute_fpass(int rn, int rx);
+ inline void compute_scalb(int rn, int rx, int ry);
+ inline void compute_logb(int rn, int rx);
+ inline void compute_fix_scaled(int rn, int rx, int ry);
+ inline void compute_fix(int rn, int rx);
+ inline void compute_float_scaled(int rn, int rx, int ry);
+ inline void compute_float(int rn, int rx);
inline void compute_recips(int rn, int rx);
inline void compute_rsqrts(int rn, int rx);
- inline void compute_fpass(int rn, int rx);
- inline void compute_fabs(int rn, int rx);
+ inline void compute_fcopysign(int rn, int rx, int ry);
+ inline void compute_fmin(int rn, int rx, int ry);
+ inline void compute_fmax(int rn, int rx, int ry);
+ inline void compute_fclip(int rn, int rx, int ry);
+
+ // Multiplier
inline void compute_mul_uuin(int rn, int rx, int ry);
inline void compute_mul_ssin(int rn, int rx, int ry);
inline uint32_t compute_mrf_plus_mul_ssin(int rx, int ry);
inline uint32_t compute_mrb_plus_mul_ssin(int rx, int ry);
inline void compute_fmul(int rn, int rx, int ry);
- inline void compute_multi_mr_to_reg(int ai, int rk);
- inline void compute_multi_reg_to_mr(int ai, int rk);
+
+ // Dual add/subtract
inline void compute_dual_add_sub(int ra, int rs, int rx, int ry);
+ inline void compute_dual_fadd_fsub(int ra, int rs, int rx, int ry);
+
+ // Parallel multiplier and ALU
inline void compute_mul_ssfr_add(int rm, int rxm, int rym, int ra, int rxa, int rya);
inline void compute_mul_ssfr_sub(int rm, int rxm, int rym, int ra, int rxa, int rya);
- inline void compute_dual_fadd_fsub(int ra, int rs, int rx, int ry);
inline void compute_fmul_fadd(int fm, int fxm, int fym, int fa, int fxa, int fya);
inline void compute_fmul_fsub(int fm, int fxm, int fym, int fa, int fxa, int fya);
inline void compute_fmul_float_scaled(int fm, int fxm, int fym, int fa, int fxa, int fya);
@@ -446,8 +456,13 @@ private:
inline void compute_fmul_abs(int fm, int fxm, int fym, int fa, int fxa, int fya);
inline void compute_fmul_fmax(int fm, int fxm, int fym, int fa, int fxa, int fya);
inline void compute_fmul_fmin(int fm, int fxm, int fym, int fa, int fxa, int fya);
+
+ // Parallel multiplier and dual add/subtract
inline void compute_fmul_dual_fadd_fsub(int fm, int fxm, int fym, int fa, int fs, int fxa, int fya);
+ inline void compute_multi_mr_to_reg(int ai, int rk);
+ inline void compute_multi_reg_to_mr(int ai, int rk);
+
// internal compiler state
struct compiler_state
{
diff --git a/src/devices/cpu/sharc/sharcinternal.ipp b/src/devices/cpu/sharc/sharcinternal.ipp
index e4ad191122a..8af23d5dfa4 100644
--- a/src/devices/cpu/sharc/sharcinternal.ipp
+++ b/src/devices/cpu/sharc/sharcinternal.ipp
@@ -9,6 +9,7 @@
// constants for IEEE754 single-precision float format
+constexpr uint32_t FLOAT_CANONICAL_NAN = 0xffffffff;
constexpr uint32_t FLOAT_INFINITY = 0x7f800000;
constexpr uint32_t FLOAT_SIGN_MASK = 0x80000000;
constexpr uint32_t FLOAT_EXPONENT_MASK = 0x7f800000;
diff --git a/src/devices/cpu/sharc/sharcops.hxx b/src/devices/cpu/sharc/sharcops.hxx
index d78f05a27c6..0a2a116a199 100644
--- a/src/devices/cpu/sharc/sharcops.hxx
+++ b/src/devices/cpu/sharc/sharcops.hxx
@@ -847,6 +847,7 @@ void adsp21062_device::COMPUTE(uint32_t opcode)
case 0x26: compute_sub_ci(rn, rx); break;
case 0x29: compute_inc(rn, rx); break;
case 0x2a: compute_dec(rn, rx); break;
+ case 0x30: compute_abs(rn, rx); break;
case 0x40: compute_and(rn, rx, ry); break;
case 0x41: compute_or(rn, rx, ry); break;
case 0x42: compute_xor(rn, rx, ry); break;
@@ -858,7 +859,8 @@ void adsp21062_device::COMPUTE(uint32_t opcode)
case 0x82: compute_fsub(rn, rx, ry); break;
case 0x89: compute_favg(rn, rx, ry); break;
case 0x8a: compute_fcomp(rx, ry); break;
- case 0x91: compute_fabs_plus(rn, rx, ry); break;
+ case 0x91: compute_fadd_abs(rn, rx, ry); break;
+ case 0x92: compute_fsub_abs(rn, rx, ry); break;
case 0xa1: compute_fpass(rn, rx); break;
case 0xa2: compute_fneg(rn, rx); break;
case 0xb0: compute_fabs(rn, rx); break;