summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-03-10 04:36:22 +1100
committer Vas Crabb <vas@vastheman.com>2026-03-10 04:36:22 +1100
commit550d001cd43054c60401b2001267e410822d2d46 (patch)
tree372abe9c688890bb955d9bea35fc048c87afae3f /src/devices/cpu
parent20b736540e8353730b2d154120b734467fa14292 (diff)
cpu/sharc/compute.hxx: Share interpreter code for some single ALU ops and dual multiplier/ALU ops, be stricter about Rn vs Fn.
Diffstat (limited to 'src/devices/cpu')
-rw-r--r--src/devices/cpu/sharc/compute.hxx712
-rw-r--r--src/devices/cpu/sharc/sharc.h64
-rw-r--r--src/devices/cpu/sharc/sharcops.hxx6
3 files changed, 382 insertions, 400 deletions
diff --git a/src/devices/cpu/sharc/compute.hxx b/src/devices/cpu/sharc/compute.hxx
index 2c8917b7794..77fbc935559 100644
--- a/src/devices/cpu/sharc/compute.hxx
+++ b/src/devices/cpu/sharc/compute.hxx
@@ -125,12 +125,202 @@ const uint32_t adsp21062_device::rsqrts_mantissa_lookup[128] =
0x00370000, 0x00370000, 0x00360000, 0x00350000,
};
-uint32_t adsp21062_device::SCALB(SHARC_REG rx, int ry)
+
+/*****************************************************************************/
+/* ALU helpers */
+
+/* Fx + Fy */
+adsp21062_device::SHARC_REG adsp21062_device::FADD(int fx, int fy)
+{
+ SHARC_REG r;
+ if (IS_FLOAT_NAN_ADD(REG(fx), REG(fy)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ SHARC_REG x, y;
+ x.r = FLOAT_FLUSH_DENORMAL(REG(fx));
+ y.r = FLOAT_FLUSH_DENORMAL(REG(fy));
+ r.f = x.f + y.f;
+
+ if (IS_FLOAT_INFINITY(r.r))
+ {
+ m_core->astat |= AV;
+ m_core->stky |= AVS;
+ if (m_core->mode1 & MODE1_TRUNCATE)
+ r.r = (r.r & FLOAT_SIGN_MASK) | 0x7f7fffff;
+ }
+ else if (IS_FLOAT_DENORMAL_OR_ZERO(r.r))
+ {
+ m_core->astat |= AZ;
+ m_core->stky |= ((r.r & FLOAT_MANTISSA_MASK) != 0) ? AUS : 0;
+ r.r &= FLOAT_SIGN_MASK;
+ }
+ m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
+ }
+
+ m_core->astat |= AF;
+ return r;
+}
+
+/* Fx - Fy */
+adsp21062_device::SHARC_REG adsp21062_device::FSUB(int fx, int fy)
+{
+ SHARC_REG r;
+ if (IS_FLOAT_NAN_SUB(REG(fx), REG(fy)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ SHARC_REG x, y;
+ x.r = FLOAT_FLUSH_DENORMAL(REG(fx));
+ y.r = FLOAT_FLUSH_DENORMAL(REG(fy));
+ r.f = x.f - y.f;
+
+ if (IS_FLOAT_INFINITY(r.r))
+ {
+ m_core->astat |= AV;
+ m_core->stky |= AVS;
+ if (m_core->mode1 & MODE1_TRUNCATE)
+ r.r = (r.r & FLOAT_SIGN_MASK) | 0x7f7fffff;
+ }
+ else if (IS_FLOAT_DENORMAL_OR_ZERO(r.r))
+ {
+ m_core->astat |= AZ;
+ m_core->stky |= ((r.r & FLOAT_MANTISSA_MASK) != 0) ? AUS : 0;
+ r.r &= FLOAT_SIGN_MASK;
+ }
+ m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
+ }
+
+ m_core->astat |= AF;
+ return r;
+}
+
+// (Fx + Fy) / 2
+adsp21062_device::SHARC_REG adsp21062_device::FAVG(int fx, int fy)
+{
+ SHARC_REG r;
+ if (IS_FLOAT_NAN_ADD(REG(fx), REG(fy)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ // TODO: this loses one bit of range due to the intermediate sub being constrained to single precision
+ SHARC_REG x, y;
+ x.r = FLOAT_FLUSH_DENORMAL(REG(fx));
+ y.r = FLOAT_FLUSH_DENORMAL(REG(fy));
+ r.f = (x.f + y.f) * 0.5f;
+
+ if (IS_FLOAT_INFINITY(r.r))
+ {
+ m_core->astat |= AV;
+ m_core->stky |= AVS;
+ if (m_core->mode1 & MODE1_TRUNCATE)
+ r.r = (r.r & FLOAT_SIGN_MASK) | 0x7f7fffff;
+ }
+ else if (IS_FLOAT_DENORMAL_OR_ZERO(r.r))
+ {
+ m_core->astat |= AZ;
+ m_core->stky |= ((r.r & FLOAT_MANTISSA_MASK) != 0) ? AUS : 0;
+ r.r &= FLOAT_SIGN_MASK;
+ }
+ m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
+ }
+
+ m_core->astat |= AF;
+ return r;
+}
+
+// ABS Fx
+adsp21062_device::SHARC_REG adsp21062_device::FABS(int fx)
+{
+ SHARC_REG r;
+ if (IS_FLOAT_NAN(REG(fx)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ if (IS_FLOAT_DENORMAL_OR_ZERO(REG(fx)))
+ {
+ r.r = 0;
+ m_core->astat |= AZ;
+ }
+ else
+ {
+ r.r = REG(fx) & ~FLOAT_SIGN_MASK;
+ }
+ m_core->astat |= (REG(fx) & FLOAT_SIGN_MASK) ? AS : 0;
+ }
+
+ m_core->astat |= AF;
+ return r;
+}
+
+// MIN(Fx, Fy)
+adsp21062_device::SHARC_REG adsp21062_device::FMIN(int fx, int fy)
+{
+ SHARC_REG r;
+ if (IS_FLOAT_NAN(REG(fx)) || IS_FLOAT_NAN(REG(fy)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ // TODO: flush denormals to zero, handle negative versus positive zero
+ r.f = std::min(FREG(fx), FREG(fy));
+
+ m_core->astat |= (r.f < 0.0f) ? AN : 0;
+ m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ }
+
+ m_core->astat |= AF;
+ return r;
+}
+
+// MAX(Fx, Fy)
+adsp21062_device::SHARC_REG adsp21062_device::FMAX(int fx, int fy)
+{
+ SHARC_REG r;
+ if (IS_FLOAT_NAN(REG(fx)) || IS_FLOAT_NAN(REG(fy)))
+ {
+ r.r = FLOAT_CANONICAL_NAN;
+ m_core->astat |= AI;
+ m_core->stky |= AIS;
+ }
+ else
+ {
+ // TODO: flush denormals to zero, handle negative versus positive zero
+ r.f = std::max(FREG(fx), FREG(fy));
+
+ m_core->astat |= (r.f < 0.0f) ? AN : 0;
+ m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ }
+
+ m_core->astat |= AF;
+ return r;
+}
+
+uint32_t adsp21062_device::SCALB(SHARC_REG fx, int ry)
{
- uint32_t const mantissa = rx.r & FLOAT_MANTISSA_MASK;
- uint32_t const sign = rx.r & FLOAT_SIGN_MASK;
+ uint32_t const mantissa = fx.r & FLOAT_MANTISSA_MASK;
+ uint32_t const sign = fx.r & FLOAT_SIGN_MASK;
- int exponent = float_get_unbiased_exponent(rx.r);
+ int exponent = float_get_unbiased_exponent(fx.r);
exponent += int32_t(REG(ry));
if (exponent > 127)
@@ -487,90 +677,26 @@ void adsp21062_device::compute_clip(int rn, int rx, int ry)
/* Floating-point ALU operations */
/* Fn = Fx + Fy */
-void adsp21062_device::compute_fadd(int rn, int rx, int ry)
+void adsp21062_device::compute_fadd(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
-
- SHARC_REG r;
- if (IS_FLOAT_NAN_ADD(REG(rx), REG(ry)))
- {
- r.r = FLOAT_CANONICAL_NAN;
- m_core->astat |= AI;
- m_core->stky |= AIS;
- }
- else
- {
- SHARC_REG x, y;
- x.r = FLOAT_FLUSH_DENORMAL(REG(rx));
- y.r = FLOAT_FLUSH_DENORMAL(REG(ry));
- r.f = x.f + y.f;
-
- if (IS_FLOAT_INFINITY(r.r))
- {
- m_core->astat |= AV;
- m_core->stky |= AVS;
- if (m_core->mode1 & MODE1_TRUNCATE)
- r.r = (r.r & FLOAT_SIGN_MASK) | 0x7f7fffff;
- }
- else if (IS_FLOAT_DENORMAL_OR_ZERO(r.r))
- {
- m_core->astat |= AZ;
- m_core->stky |= ((r.r & FLOAT_MANTISSA_MASK) != 0) ? AUS : 0;
- r.r &= FLOAT_SIGN_MASK;
- }
- m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
- }
-
- FREG(rn) = r.f;
- m_core->astat |= AF;
+ FREG(fn) = FADD(fx, fy).f;
}
/* Fn = Fx - Fy */
-void adsp21062_device::compute_fsub(int rn, int rx, int ry)
+void adsp21062_device::compute_fsub(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
-
- SHARC_REG r;
- if (IS_FLOAT_NAN_SUB(REG(rx), REG(ry)))
- {
- r.r = FLOAT_CANONICAL_NAN;
- m_core->astat |= AI;
- m_core->stky |= AIS;
- }
- else
- {
- SHARC_REG x, y;
- x.r = FLOAT_FLUSH_DENORMAL(REG(rx));
- y.r = FLOAT_FLUSH_DENORMAL(REG(ry));
- r.f = x.f - y.f;
-
- if (IS_FLOAT_INFINITY(r.r))
- {
- m_core->astat |= AV;
- m_core->stky |= AVS;
- if (m_core->mode1 & MODE1_TRUNCATE)
- r.r = (r.r & FLOAT_SIGN_MASK) | 0x7f7fffff;
- }
- else if (IS_FLOAT_DENORMAL_OR_ZERO(r.r))
- {
- m_core->astat |= AZ;
- m_core->stky |= ((r.r & FLOAT_MANTISSA_MASK) != 0) ? AUS : 0;
- r.r &= FLOAT_SIGN_MASK;
- }
- m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
- }
-
- FREG(rn) = r.f;
- m_core->astat |= AF;
+ FREG(fn) = FSUB(fx, fy).f;
}
/* Fn = ABS(Fx + Fy) */
-void adsp21062_device::compute_fadd_abs(int rn, int rx, int ry)
+void adsp21062_device::compute_fadd_abs(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
SHARC_REG r;
- if (IS_FLOAT_NAN_ADD(REG(rx), REG(ry)))
+ if (IS_FLOAT_NAN_ADD(REG(fx), REG(fy)))
{
r.r = FLOAT_CANONICAL_NAN;
m_core->astat |= AI;
@@ -579,8 +705,8 @@ void adsp21062_device::compute_fadd_abs(int rn, int rx, int ry)
else
{
SHARC_REG x, y;
- x.r = FLOAT_FLUSH_DENORMAL(REG(rx));
- y.r = FLOAT_FLUSH_DENORMAL(REG(ry));
+ x.r = FLOAT_FLUSH_DENORMAL(REG(fx));
+ y.r = FLOAT_FLUSH_DENORMAL(REG(fy));
r.f = x.f + y.f;
r.r &= ~FLOAT_SIGN_MASK;
@@ -599,17 +725,17 @@ void adsp21062_device::compute_fadd_abs(int rn, int rx, int ry)
}
}
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
m_core->astat |= AF;
}
/* Fn = ABS(Fx - Fy) */
-void adsp21062_device::compute_fsub_abs(int rn, int rx, int ry)
+void adsp21062_device::compute_fsub_abs(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
SHARC_REG r;
- if (IS_FLOAT_NAN_SUB(REG(rx), REG(ry)))
+ if (IS_FLOAT_NAN_SUB(REG(fx), REG(fy)))
{
r.r = FLOAT_CANONICAL_NAN;
m_core->astat |= AI;
@@ -618,8 +744,8 @@ void adsp21062_device::compute_fsub_abs(int rn, int rx, int ry)
else
{
SHARC_REG x, y;
- x.r = FLOAT_FLUSH_DENORMAL(REG(rx));
- y.r = FLOAT_FLUSH_DENORMAL(REG(ry));
+ x.r = FLOAT_FLUSH_DENORMAL(REG(fx));
+ y.r = FLOAT_FLUSH_DENORMAL(REG(fy));
r.f = x.f - y.f;
r.r &= ~FLOAT_SIGN_MASK;
@@ -638,64 +764,31 @@ void adsp21062_device::compute_fsub_abs(int rn, int rx, int ry)
}
}
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
m_core->astat |= AF;
}
/* Fn = (Fx + Fy) / 2 */
-void adsp21062_device::compute_favg(int rn, int rx, int ry)
+void adsp21062_device::compute_favg(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
-
- SHARC_REG r;
- if (IS_FLOAT_NAN_ADD(REG(rx), REG(ry)))
- {
- r.r = FLOAT_CANONICAL_NAN;
- m_core->astat |= AI;
- m_core->stky |= AIS;
- }
- else
- {
- // TODO: this loses one bit of range due to the intermediate sub being constrained to single precision
- SHARC_REG x, y;
- x.r = FLOAT_FLUSH_DENORMAL(REG(rx));
- y.r = FLOAT_FLUSH_DENORMAL(REG(ry));
- r.f = (x.f + y.f) * 0.5f;
-
- if (IS_FLOAT_INFINITY(r.r))
- {
- m_core->astat |= AV;
- m_core->stky |= AVS;
- if (m_core->mode1 & MODE1_TRUNCATE)
- r.r = (r.r & FLOAT_SIGN_MASK) | 0x7f7fffff;
- }
- else if (IS_FLOAT_DENORMAL_OR_ZERO(r.r))
- {
- m_core->astat |= AZ;
- m_core->stky |= ((r.r & FLOAT_MANTISSA_MASK) != 0) ? AUS : 0;
- r.r &= FLOAT_SIGN_MASK;
- }
- m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
- }
-
- FREG(rn) = r.f;
- m_core->astat |= AF;
+ FREG(fn) = FAVG(fx, fy).f;
}
/* COMP(Fx, Fy) */
-void adsp21062_device::compute_fcomp(int rx, int ry)
+void adsp21062_device::compute_fcomp(int fx, int fy)
{
CLEAR_ALU_FLAGS();
- if (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry)))
+ if (IS_FLOAT_NAN(REG(fx)) || IS_FLOAT_NAN(REG(fy)))
{
m_core->astat |= AI;
m_core->stky |= AIS;
}
else
{
- if (FREG(rx) == FREG(ry))
+ if (FREG(fx) == FREG(fy))
m_core->astat |= AZ;
- else if (FREG(rx) < FREG(ry))
+ else if (FREG(fx) < FREG(fy))
m_core->astat |= AN;
}
@@ -712,12 +805,12 @@ void adsp21062_device::compute_fcomp(int rx, int ry)
}
/* Fn = -Fx */
-void adsp21062_device::compute_fneg(int rn, int rx)
+void adsp21062_device::compute_fneg(int fn, int fx)
{
CLEAR_ALU_FLAGS();
SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)))
+ if (IS_FLOAT_NAN(REG(fx)))
{
r.r = FLOAT_CANONICAL_NAN;
m_core->astat |= AI;
@@ -725,59 +818,36 @@ void adsp21062_device::compute_fneg(int rn, int rx)
}
else
{
- if (IS_FLOAT_DENORMAL_OR_ZERO(REG(rx)))
+ if (IS_FLOAT_DENORMAL_OR_ZERO(REG(fx)))
{
- r.r = ~REG(rx) & FLOAT_SIGN_MASK;
+ r.r = ~REG(fx) & FLOAT_SIGN_MASK;
m_core->astat |= AZ;
}
else
{
- r.r = REG(rx) ^ FLOAT_SIGN_MASK;
+ r.r = REG(fx) ^ FLOAT_SIGN_MASK;
}
m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
}
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
m_core->astat |= AF;
}
/* Fn = ABS Fx */
-void adsp21062_device::compute_fabs(int rn, int rx)
+void adsp21062_device::compute_fabs(int fn, int fx)
{
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_OR_ZERO(REG(rx)))
- {
- r.r = 0;
- m_core->astat |= AZ;
- }
- else
- {
- r.r = REG(rx) & ~FLOAT_SIGN_MASK;
- }
- m_core->astat |= (REG(rx) & FLOAT_SIGN_MASK) ? AS : 0;
- }
-
- FREG(rn) = r.f;
- m_core->astat |= AF;
+ FREG(fn) = FABS(fx).f;
}
/* Fn = PASS Fx */
-void adsp21062_device::compute_fpass(int rn, int rx)
+void adsp21062_device::compute_fpass(int fn, int fx)
{
CLEAR_ALU_FLAGS();
SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)))
+ if (IS_FLOAT_NAN(REG(fx)))
{
r.r = FLOAT_CANONICAL_NAN;
m_core->astat |= AI;
@@ -785,39 +855,39 @@ void adsp21062_device::compute_fpass(int rn, int rx)
}
else
{
- if (IS_FLOAT_DENORMAL_OR_ZERO(REG(rx)))
+ if (IS_FLOAT_DENORMAL_OR_ZERO(REG(fx)))
{
- r.r = REG(rx) & FLOAT_SIGN_MASK;
+ r.r = REG(fx) & FLOAT_SIGN_MASK;
m_core->astat |= AZ;
}
else
{
- r.r = REG(rx);
+ r.r = REG(fx);
}
m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
}
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
m_core->astat |= AF;
}
/* Fn = SCALB Fx BY Fy */
-void adsp21062_device::compute_scalb(int rn, int rx, int ry)
+void adsp21062_device::compute_scalb(int fn, int fx, int ry)
{
// verified
SHARC_REG r;
CLEAR_ALU_FLAGS();
- if (IS_FLOAT_NAN(REG(rx)))
+ if (IS_FLOAT_NAN(REG(fx)))
{
m_core->astat |= AI;
m_core->stky |= AIS;
- REG(rn) = FLOAT_CANONICAL_NAN;
+ REG(fn) = FLOAT_CANONICAL_NAN;
}
else
{
- r.r = SCALB(m_core->r[rx], ry);
+ r.r = SCALB(m_core->r[fx], ry);
// AN
SET_FLAG_AN(r.r);
@@ -826,32 +896,32 @@ void adsp21062_device::compute_scalb(int rn, int rx, int ry)
// AUS
m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
}
m_core->astat |= AF;
}
/* Rn = LOGB Fx */
-void adsp21062_device::compute_logb(int rn, int rx)
+void adsp21062_device::compute_logb(int rn, int fx)
{
// verified
- uint32_t r = REG(rx);
+ uint32_t r = REG(fx);
CLEAR_ALU_FLAGS();
- if (IS_FLOAT_INFINITY(REG(rx)))
+ if (IS_FLOAT_INFINITY(REG(fx)))
{
REG(rn) = FLOAT_INFINITY;
m_core->astat |= AV;
}
- else if (IS_FLOAT_ZERO(REG(rx)))
+ else if (IS_FLOAT_ZERO(REG(fx)))
{
REG(rn) = FLOAT_SIGN_MASK | FLOAT_INFINITY;
m_core->astat |= AV;
}
- else if (IS_FLOAT_NAN(REG(rx)))
+ else if (IS_FLOAT_NAN(REG(fx)))
{
REG(rn) = FLOAT_CANONICAL_NAN;
@@ -873,12 +943,12 @@ void adsp21062_device::compute_logb(int rn, int rx)
}
/* Rn = FIX Fx BY Ry */
-void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry)
+void adsp21062_device::compute_fix_scaled(int rn, int fx, int ry)
{
int32_t alu_i;
SHARC_REG r_alu;
- r_alu.r = SCALB(m_core->r[rx], ry);
+ r_alu.r = SCALB(m_core->r[fx], ry);
if (m_core->mode1 & MODE1_TRUNCATE)
{
alu_i = int32_t(floorf(r_alu.f));
@@ -895,7 +965,7 @@ void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry)
// 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(fx))) ? AI : 0;
/* TODO: AV flag */
REG(rn) = alu_i;
@@ -903,12 +973,12 @@ void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry)
}
/* Rn = FIX Fx */
-void adsp21062_device::compute_fix(int rn, int rx)
+void adsp21062_device::compute_fix(int rn, int fx)
{
int32_t alu_i;
SHARC_REG r_alu;
- r_alu.f = FREG(rx);
+ r_alu.f = FREG(fx);
if (m_core->mode1 & MODE1_TRUNCATE)
{
alu_i = int32_t(floorf(r_alu.f));
@@ -925,7 +995,7 @@ void adsp21062_device::compute_fix(int rn, int rx)
// 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(fx))) ? AI : 0;
/* TODO: AV flag */
REG(rn) = alu_i;
@@ -933,7 +1003,7 @@ void adsp21062_device::compute_fix(int rn, int rx)
}
/* Fn = FLOAT Rx BY Ry */
-void adsp21062_device::compute_float_scaled(int rn, int rx, int ry)
+void adsp21062_device::compute_float_scaled(int fn, int rx, int ry)
{
SHARC_REG x;
x.f = float(int32_t(REG(rx)));
@@ -941,45 +1011,45 @@ void adsp21062_device::compute_float_scaled(int rn, int rx, int ry)
// verified
CLEAR_ALU_FLAGS();
- REG(rn) = SCALB(x, ry);
+ REG(fn) = SCALB(x, ry);
// AN
- SET_FLAG_AN(REG(rn));
+ SET_FLAG_AN(REG(fn));
// AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
+ m_core->astat |= IS_FLOAT_DENORMAL_OR_ZERO(REG(fn)) ? AZ : 0;
// AU
- m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
+ m_core->stky |= IS_FLOAT_DENORMAL(REG(fn)) ? AUS : 0;
m_core->astat |= AF;
}
/* Fn = FLOAT Rx */
-void adsp21062_device::compute_float(int rn, int rx)
+void adsp21062_device::compute_float(int fn, int rx)
{
// verified
- FREG(rn) = (float)(int32_t)REG(rx);
+ FREG(fn) = (float)(int32_t)REG(rx);
CLEAR_ALU_FLAGS();
// AN
- SET_FLAG_AN(REG(rn));
+ SET_FLAG_AN(REG(fn));
// AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
+ m_core->astat |= IS_FLOAT_DENORMAL_OR_ZERO(REG(fn)) ? AZ : 0;
// AUS
- m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
+ m_core->stky |= IS_FLOAT_DENORMAL(REG(fn)) ? AUS : 0;
/* TODO: AV flag */
m_core->astat |= AF;
}
/* Fn = RECIPS Fx */
-void adsp21062_device::compute_recips(int rn, int rx)
+void adsp21062_device::compute_recips(int fn, int fx)
{
// verified
uint32_t r;
CLEAR_ALU_FLAGS();
- if (IS_FLOAT_NAN(REG(rx)))
+ if (IS_FLOAT_NAN(REG(fx)))
{
// NaN
r = FLOAT_CANONICAL_NAN;
@@ -990,19 +1060,19 @@ void adsp21062_device::compute_recips(int rn, int rx)
// AIS
m_core->stky |= AIS;
}
- else if (IS_FLOAT_ZERO(REG(rx)))
+ else if (IS_FLOAT_ZERO(REG(fx)))
{
// +- Zero
- r = (REG(rx) & FLOAT_SIGN_MASK) | FLOAT_INFINITY;
+ r = (REG(fx) & FLOAT_SIGN_MASK) | FLOAT_INFINITY;
m_core->astat |= AV;
}
else
{
- uint32_t mantissa = REG(rx) & FLOAT_MANTISSA_MASK;
- uint32_t sign = REG(rx) & FLOAT_SIGN_MASK;
+ uint32_t mantissa = REG(fx) & FLOAT_MANTISSA_MASK;
+ uint32_t sign = REG(fx) & FLOAT_SIGN_MASK;
- int res_exponent = -float_get_unbiased_exponent(REG(rx)) - 1;
+ int res_exponent = -float_get_unbiased_exponent(REG(fx)) - 1;
uint32_t res_mantissa = recips_mantissa_lookup[mantissa >> 16];
@@ -1018,37 +1088,37 @@ void adsp21062_device::compute_recips(int rn, int rx)
r = sign | (uint32_t(res_exponent) << FLOAT_EXPONENT_SHIFT) | res_mantissa;
- SET_FLAG_AN(REG(rx));
+ SET_FLAG_AN(REG(fx));
// AZ
m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
}
- REG(rn) = r;
+ REG(fn) = r;
m_core->astat |= AF;
}
/* Fn = RSQRTS Fx */
-void adsp21062_device::compute_rsqrts(int rn, int rx)
+void adsp21062_device::compute_rsqrts(int fn, int fx)
{
// verified
uint32_t r;
- if (uint32_t(REG(rx)) > 0x80000000)
+ if (uint32_t(REG(fx)) > 0x80000000)
{
// non-zero negative
r = FLOAT_CANONICAL_NAN;
}
- else if (IS_FLOAT_NAN(REG(rx)))
+ else if (IS_FLOAT_NAN(REG(fx)))
{
// NaN
r = FLOAT_CANONICAL_NAN;
}
else
{
- uint32_t mantissa = REG(rx) & 0xffffff; // mantissa + LSB of biased exponent
- uint32_t sign = REG(rx) & FLOAT_SIGN_MASK;
+ uint32_t mantissa = REG(fx) & 0xffffff; // mantissa + LSB of biased exponent
+ uint32_t sign = REG(fx) & FLOAT_SIGN_MASK;
- int32_t res_exponent = -(float_get_unbiased_exponent(REG(rx)) >> 1) - 1;
+ int32_t res_exponent = -(float_get_unbiased_exponent(REG(fx)) >> 1) - 1;
uint32_t res_mantissa = rsqrts_mantissa_lookup[mantissa >> 17];
@@ -1057,26 +1127,26 @@ void adsp21062_device::compute_rsqrts(int rn, int rx)
CLEAR_ALU_FLAGS();
// AN
- m_core->astat |= (REG(rx) == 0x80000000) ? AN : 0;
+ m_core->astat |= (REG(fx) == 0x80000000) ? AN : 0;
// AZ & AV
m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
- m_core->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0;
+ m_core->astat |= (IS_FLOAT_ZERO(REG(fx))) ? AV : 0;
// AI
- m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || (REG(rx) & FLOAT_SIGN_MASK)) ? AI : 0;
+ m_core->astat |= (IS_FLOAT_NAN(REG(fx)) || (REG(fx) & FLOAT_SIGN_MASK)) ? AI : 0;
// AIS
if (m_core->astat & AI) m_core->stky |= AIS;
- REG(rn) = r;
+ REG(fn) = r;
m_core->astat |= AF;
}
/* Fn = COPYSIGN(Fx, Fy) */
-void adsp21062_device::compute_fcopysign(int rn, int rx, int ry)
+void adsp21062_device::compute_fcopysign(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry)))
+ if (IS_FLOAT_NAN(REG(fx)) || IS_FLOAT_NAN(REG(fy)))
{
r.r = FLOAT_CANONICAL_NAN;
m_core->astat |= AI;
@@ -1084,75 +1154,39 @@ void adsp21062_device::compute_fcopysign(int rn, int rx, int ry)
}
else
{
- r.r = REG(ry) & FLOAT_SIGN_MASK;
+ r.r = REG(fy) & FLOAT_SIGN_MASK;
m_core->astat |= r.r ? AN : 0; // only the sign bit is set here so it avoids need to mask
- if (IS_FLOAT_DENORMAL_OR_ZERO(REG(rx)))
+ if (IS_FLOAT_DENORMAL_OR_ZERO(REG(fx)))
m_core->astat |= AZ;
else
- r.r |= REG(rx) & ~FLOAT_SIGN_MASK;
+ r.r |= REG(fx) & ~FLOAT_SIGN_MASK;
}
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
m_core->astat |= AF;
}
/* Fn = MIN(Fx, Fy) */
-void adsp21062_device::compute_fmin(int rn, int rx, int ry)
+void adsp21062_device::compute_fmin(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
-
- SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry)))
- {
- r.r = FLOAT_CANONICAL_NAN;
- m_core->astat |= AI;
- m_core->stky |= AIS;
- }
- else
- {
- // TODO: flush denormals to zero, handle negative versus positive zero
- r.f = std::min(FREG(rx), FREG(ry));
-
- m_core->astat |= (r.f < 0.0f) ? AN : 0;
- m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
- }
-
- FREG(rn) = r.f;
- m_core->astat |= AF;
+ FREG(fn) = FMIN(fx, fy).f;
}
/* Fn = MAX(Fx, Fy) */
-void adsp21062_device::compute_fmax(int rn, int rx, int ry)
+void adsp21062_device::compute_fmax(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
-
- SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry)))
- {
- r.r = FLOAT_CANONICAL_NAN;
- m_core->astat |= AI;
- m_core->stky |= AIS;
- }
- else
- {
- // TODO: flush denormals to zero, handle negative versus positive zero
- r.f = std::max(FREG(rx), FREG(ry));
-
- m_core->astat |= (r.f < 0.0f) ? AN : 0;
- m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
- }
-
- FREG(rn) = r.f;
- m_core->astat |= AF;
+ FREG(fn) = FMAX(fx, fy).f;
}
/* Fn = CLIP Fx BY Fy */
-void adsp21062_device::compute_fclip(int rn, int rx, int ry)
+void adsp21062_device::compute_fclip(int fn, int fx, int fy)
{
CLEAR_ALU_FLAGS();
SHARC_REG r;
- if (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry)))
+ if (IS_FLOAT_NAN(REG(fx)) || IS_FLOAT_NAN(REG(fy)))
{
r.r = FLOAT_CANONICAL_NAN;
m_core->astat |= AI;
@@ -1160,23 +1194,23 @@ void adsp21062_device::compute_fclip(int rn, int rx, int ry)
}
else
{
- if (IS_FLOAT_DENORMAL_OR_ZERO(REG(rx)) || IS_FLOAT_DENORMAL_OR_ZERO(REG(ry)))
+ if (IS_FLOAT_DENORMAL_OR_ZERO(REG(fx)) || IS_FLOAT_DENORMAL_OR_ZERO(REG(fy)))
{
- r.r = REG(rx) & FLOAT_SIGN_MASK;
+ r.r = REG(fx) & FLOAT_SIGN_MASK;
m_core->astat |= AZ;
}
else
{
SHARC_REG absry, negabsry;
- absry.r = REG(ry) & ~FLOAT_SIGN_MASK;
- negabsry.r = REG(ry) | FLOAT_SIGN_MASK;
- r.f = std::clamp(FREG(rx), negabsry.f, absry.f);
+ absry.r = REG(fy) & ~FLOAT_SIGN_MASK;
+ negabsry.r = REG(fy) | FLOAT_SIGN_MASK;
+ r.f = std::clamp(FREG(fx), negabsry.f, absry.f);
m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
}
m_core->astat |= (r.r & FLOAT_SIGN_MASK) ? AN : 0;
}
- FREG(rn) = r.f;
+ FREG(fn) = r.f;
m_core->astat |= AF;
}
@@ -1367,8 +1401,6 @@ void adsp21062_device::compute_mul_ssfr_sub(int rm, int rxm, int rym, int ra, in
}
-/* floating-point */
-
/* Fa = Fx + Fy, Fs = Fx - Fy */
void adsp21062_device::compute_dual_fadd_fsub(int ra, int rs, int rx, int ry)
{
@@ -1380,8 +1412,8 @@ void adsp21062_device::compute_dual_fadd_fsub(int ra, int rs, int rx, int ry)
// AN
m_core->astat |= ((r_add.f < 0.0f) || (r_sub.f < 0.0f)) ? AN : 0;
// AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) ||
- IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
+ m_core->astat |= (IS_FLOAT_DENORMAL_OR_ZERO(r_add.r) ||
+ IS_FLOAT_DENORMAL_OR_ZERO(r_sub.r)) ? AZ : 0;
// AUS
m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
// AI
@@ -1396,78 +1428,60 @@ void adsp21062_device::compute_dual_fadd_fsub(int ra, int rs, int rx, int ry)
m_core->astat |= AF;
}
+
+/*****************************************************************************/
+/* Floating-point multiplication and ALU operation */
+
/* Fm = Fxm * Fym, Fa = Fxa + Fya */
void adsp21062_device::compute_fmul_fadd(int fm, int fxm, int fym, int fa, int fxa, int fya)
{
- SHARC_REG r_mul, r_add;
+ CLEAR_MULTIPLIER_FLAGS();
+ CLEAR_ALU_FLAGS();
+
+ SHARC_REG r_mul;
r_mul.f = FREG(fxm) * FREG(fym);
- r_add.f = FREG(fxa) + FREG(fya);
- CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
/* TODO: MV flag */
/* TODO: MU flag */
/* TODO: MI flag */
- CLEAR_ALU_FLAGS();
- m_core->astat |= (r_add.f < 0.0f) ? AN : 0;
- // AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r)) ? AZ : 0;
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
- /* TODO: AV flag */
-
- // AIS
- if (m_core->astat & AI) m_core->stky |= AIS;
+ SHARC_REG r_alu = FADD(fxa, fya);
FREG(fm) = r_mul.f;
- FREG(fa) = r_add.f;
- m_core->astat |= AF;
+ FREG(fa) = r_alu.f;
}
/* Fm = Fxm * Fym, Fa = Fxa - Fya */
void adsp21062_device::compute_fmul_fsub(int fm, int fxm, int fym, int fa, int fxa, int fya)
{
- SHARC_REG r_mul, r_sub;
+ CLEAR_MULTIPLIER_FLAGS();
+ CLEAR_ALU_FLAGS();
+
+ SHARC_REG r_mul;
r_mul.f = FREG(fxm) * FREG(fym);
- r_sub.f = FREG(fxa) - FREG(fya);
- CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
/* TODO: MV flag */
/* TODO: MU flag */
/* TODO: MI flag */
- CLEAR_ALU_FLAGS();
- m_core->astat |= (r_sub.f < 0.0f) ? AN : 0;
- // AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
- /* TODO: AV flag */
-
- // AIS
- if (m_core->astat & AI) m_core->stky |= AIS;
+ SHARC_REG r_alu = FSUB(fxa, fya);
FREG(fm) = r_mul.f;
- FREG(fa) = r_sub.f;
- m_core->astat |= AF;
+ FREG(fa) = r_alu.f;
}
-/* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Fya */
-void adsp21062_device::compute_fmul_float_scaled(int fm, int fxm, int fym, int fa, int fxa, int fya)
+/* Fm = Fxm * Fym, Fa = FLOAT Rxa BY Rya */
+void adsp21062_device::compute_fmul_float_scaled(int fm, int fxm, int fym, int fa, int rxa, int rya)
{
SHARC_REG x;
SHARC_REG r_mul, r_alu;
r_mul.f = FREG(fxm) * FREG(fym);
- x.f = float(int32_t(REG(fxa)));
+ x.f = float(int32_t(REG(rxa)));
- r_alu.r = SCALB(x, fya);
+ r_alu.r = SCALB(x, rya);
CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
@@ -1478,9 +1492,9 @@ void adsp21062_device::compute_fmul_float_scaled(int fm, int fxm, int fym, int f
CLEAR_ALU_FLAGS();
m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
// AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(r_alu.r) || IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ m_core->astat |= IS_FLOAT_DENORMAL_OR_ZERO(r_alu.r) ? AZ : 0;
// AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ m_core->stky |= IS_FLOAT_DENORMAL(r_alu.r) ? AUS : 0;
/* TODO: set AV if overflowed */
FREG(fm) = r_mul.f;
@@ -1488,14 +1502,14 @@ void adsp21062_device::compute_fmul_float_scaled(int fm, int fxm, int fym, int f
m_core->astat |= AF;
}
-/* Fm = Fxm * Fym, Fa = FIX Fxa BY Fya */
-void adsp21062_device::compute_fmul_fix_scaled(int fm, int fxm, int fym, int fa, int fxa, int fya)
+/* Fm = Fxm * Fym, Ra = FIX Fxa BY Rya */
+void adsp21062_device::compute_fmul_fix_scaled(int fm, int fxm, int fym, int ra, int fxa, int rya)
{
int32_t alu_i;
SHARC_REG r_mul, r_alu;
r_mul.f = FREG(fxm) * FREG(fym);
- r_alu.r = SCALB(m_core->r[fxa], fya);
+ r_alu.r = SCALB(m_core->r[fxa], rya);
if (m_core->mode1 & MODE1_TRUNCATE)
{
@@ -1523,134 +1537,92 @@ void adsp21062_device::compute_fmul_fix_scaled(int fm, int fxm, int fym, int fa,
/* TODO: AV flag */
FREG(fm) = r_mul.f;
- REG(fa) = alu_i; // TODO: check this, should be RA?
+ REG(ra) = alu_i;
m_core->astat |= AF;
}
void adsp21062_device::compute_fmul_avg(int fm, int fxm, int fym, int fa, int fxa, int fya)
{
- SHARC_REG r_mul, r_alu;
+ CLEAR_MULTIPLIER_FLAGS();
+ CLEAR_ALU_FLAGS();
+
+ SHARC_REG r_mul;
r_mul.f = FREG(fxm) * FREG(fym);
- r_alu.f = (FREG(fxa) + FREG(fya)) / 2.0f;
- CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
/* TODO: MV flag */
/* TODO: MU flag */
/* TODO: MI flag */
- CLEAR_ALU_FLAGS();
- // AN
- m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
- // AZ
- m_core->astat |= (IS_FLOAT_DENORMAL(r_alu.r) || IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
- // AUS
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
- /* TODO: AV flag */
+ SHARC_REG r_alu = FAVG(fxa, fya);
FREG(fm) = r_mul.f;
FREG(fa) = r_alu.f;
- m_core->astat |= AF;
}
-void adsp21062_device::compute_fmul_abs(int fm, int fxm, int fym, int fa, int fxa, int fya)
+void adsp21062_device::compute_fmul_abs(int fm, int fxm, int fym, int fa, int fxa)
{
- SHARC_REG r_mul, r_alu;
+ CLEAR_MULTIPLIER_FLAGS();
+ CLEAR_ALU_FLAGS();
+
+ SHARC_REG r_mul;
r_mul.f = FREG(fxm) * FREG(fym);
- if (IS_FLOAT_NAN(REG(fxa)))
- {
- r_alu.r = 0xffffffff;
- }
- else if (IS_FLOAT_DENORMAL(REG(fxa)))
- {
- r_alu.r = 0;
- }
- else
- {
- r_alu.r = REG(fxa) & 0x7fffffff;
- }
- CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
/* TODO: MV flag */
/* TODO: MU flag */
/* TODO: MI flag */
- CLEAR_ALU_FLAGS();
- // AZ
- m_core->astat |= IS_FLOAT_ZERO(r_alu.r) ? AZ : 0;
- // AS
- m_core->astat |= (REG(fxa) < 0.0f) ? AS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0;
+ SHARC_REG r_alu = FABS(fxa);
FREG(fm) = r_mul.f;
FREG(fa) = r_alu.f;
- m_core->astat |= AF;
}
/* Fm = Fxm * Fym, Fa = MAX(Fxa, Fya) */
void adsp21062_device::compute_fmul_fmax(int fm, int fxm, int fym, int fa, int fxa, int fya)
{
- SHARC_REG r_mul, r_alu;
- r_mul.f = FREG(fxm) * FREG(fym);
+ CLEAR_MULTIPLIER_FLAGS();
+ CLEAR_ALU_FLAGS();
- r_alu.f = std::max(FREG(fxa), FREG(fya));
+ SHARC_REG r_mul;
+ r_mul.f = FREG(fxm) * FREG(fym);
- CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
/* TODO: MV flag */
/* TODO: MU flag */
/* TODO: MI flag */
- 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;
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
- /* TODO: AV flag */
+ SHARC_REG r_alu = FMAX(fxa, fya);
FREG(fm) = r_mul.f;
FREG(fa) = r_alu.f;
- m_core->astat |= AF;
}
/* Fm = Fxm * Fym, Fa = MIN(Fxa, Fya) */
void adsp21062_device::compute_fmul_fmin(int fm, int fxm, int fym, int fa, int fxa, int fya)
{
- SHARC_REG r_mul, r_alu;
- r_mul.f = FREG(fxm) * FREG(fym);
+ CLEAR_MULTIPLIER_FLAGS();
+ CLEAR_ALU_FLAGS();
- r_alu.f = std::min(FREG(fxa), FREG(fya));
+ SHARC_REG r_mul;
+ r_mul.f = FREG(fxm) * FREG(fym);
- CLEAR_MULTIPLIER_FLAGS();
SET_FLAG_MN(r_mul.r);
/* TODO: MV flag */
/* TODO: MU flag */
/* TODO: MI flag */
- 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;
- // AU
- m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
- // AI
- m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
- /* TODO: AV flag */
+ SHARC_REG r_alu = FMIN(fxa, fya);
FREG(fm) = r_mul.f;
FREG(fa) = r_alu.f;
- m_core->astat |= AF;
}
+/*****************************************************************************/
+/* Multiplication and dual add/subtract */
/* Fm = Fxm * Fym, Fa = Fxa + Fya, Fs = Fxa - Fya */
void adsp21062_device::compute_fmul_dual_fadd_fsub(int fm, int fxm, int fym, int fa, int fs, int fxa, int fya)
diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h
index 93f0d321386..032e7edc671 100644
--- a/src/devices/cpu/sharc/sharc.h
+++ b/src/devices/cpu/sharc/sharc.h
@@ -388,7 +388,15 @@ private:
void sharcop_nop();
void sharcop_idle();
[[noreturn]] void sharcop_unimplemented() ATTR_COLD;
- inline uint32_t SCALB(SHARC_REG rx, int ry);
+
+ // ALU helpers
+ inline SHARC_REG FADD(int fx, int fy);
+ inline SHARC_REG FSUB(int fx, int fy);
+ inline SHARC_REG FAVG(int fx, int fy);
+ inline SHARC_REG FABS(int fx);
+ inline SHARC_REG FMIN(int fx, int fy);
+ inline SHARC_REG FMAX(int fx, int fy);
+ inline uint32_t SCALB(SHARC_REG fx, int ry);
// ALU fixed-point
inline void compute_add(int rn, int rx, int ry);
@@ -412,27 +420,27 @@ private:
inline void compute_clip(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_fcomp(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_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);
+ inline void compute_fadd(int fn, int fx, int fy);
+ inline void compute_fsub(int fn, int fx, int fy);
+ inline void compute_fadd_abs(int fn, int fx, int fy);
+ inline void compute_fsub_abs(int fn, int fx, int fy);
+ inline void compute_favg(int fn, int fx, int fy);
+ inline void compute_fcomp(int fx, int fy);
+ inline void compute_fneg(int fn, int fx);
+ inline void compute_fabs(int fn, int fx);
+ inline void compute_fpass(int fn, int fx);
+ inline void compute_scalb(int fn, int fx, int ry);
+ inline void compute_logb(int rn, int fx);
+ inline void compute_fix_scaled(int rn, int fx, int ry);
+ inline void compute_fix(int rn, int fx);
+ inline void compute_float_scaled(int fn, int rx, int ry);
+ inline void compute_float(int fn, int rx);
+ inline void compute_recips(int fn, int fx);
+ inline void compute_rsqrts(int fn, int fx);
+ inline void compute_fcopysign(int fn, int fx, int fy);
+ inline void compute_fmin(int fn, int fx, int fy);
+ inline void compute_fmax(int fn, int fx, int fy);
+ inline void compute_fclip(int fn, int fx, int fy);
// Multiplier
inline void compute_mul_uuin(int rn, int rx, int ry);
@@ -445,19 +453,21 @@ private:
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
+ // Fixed-Point multiply/accumulate and add, subtract or average
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);
+
+ // Floating-Point multiplication and ALU operation
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);
- inline void compute_fmul_fix_scaled(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 rxa, int rya);
+ inline void compute_fmul_fix_scaled(int fm, int fxm, int fym, int ra, int fxa, int rya);
inline void compute_fmul_avg(int fm, int fxm, int fym, int fa, int fxa, int fya);
- inline void compute_fmul_abs(int fm, int fxm, int fym, int fa, int fxa, int fya);
+ inline void compute_fmul_abs(int fm, int fxm, int fym, int fa, int fxa);
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
+ // Multiplication 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);
diff --git a/src/devices/cpu/sharc/sharcops.hxx b/src/devices/cpu/sharc/sharcops.hxx
index 0a2a116a199..2cc071ccfe7 100644
--- a/src/devices/cpu/sharc/sharcops.hxx
+++ b/src/devices/cpu/sharc/sharcops.hxx
@@ -777,13 +777,13 @@ void adsp21062_device::COMPUTE(uint32_t opcode)
break;
}
- case 0x1a: /* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Fya */
+ case 0x1a: /* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Rya */
{
compute_fmul_float_scaled(fm, fxm, fym, fa, fxa, fya);
break;
}
- case 0x1b: /* Fm = Fxm * Fym, Fa = FIX Fxa BY Fya */
+ case 0x1b: /* Fm = Fxm * Fym, Ra = FIX Fxa BY Rya */
{
compute_fmul_fix_scaled(fm, fxm, fym, fa, fxa, fya);
break;
@@ -797,7 +797,7 @@ void adsp21062_device::COMPUTE(uint32_t opcode)
case 0x1d: /* Fm = Fxm * Fym, Fa = ABS Fxa */
{
- compute_fmul_abs(fm, fxm, fym, fa, fxa, fya);
+ compute_fmul_abs(fm, fxm, fym, fa, fxa);
break;
}