mirror of
https://github.com/hch12907/orbum.git
synced 2024-06-02 19:38:16 -04:00
Updated MMI instructions.
This commit is contained in:
parent
b2a6b71049
commit
4e310e2a77
|
@ -157,37 +157,53 @@ void CEeCoreInterpreter::PDIVBW(const EeCoreInstruction inst) const
|
|||
auto& lo = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
|
||||
auto val_source2 = static_cast<shword>(reg_source2->read_uhword(0)); // Constant.
|
||||
shword divisor = static_cast<shword>(reg_source2->read_uhword(0));
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<sword>(reg_source1->read_uword(i));
|
||||
auto div = [divisor](const uword a) -> std::tuple<uword, uword>
|
||||
{
|
||||
sword sa = static_cast<sword>(a);
|
||||
|
||||
// Check for VALUE_S32_MIN / -1 (special condition).
|
||||
if (val_source1 == VALUE_SWORD_MIN &&
|
||||
val_source2 == -1)
|
||||
{
|
||||
lo.write_uword(i, static_cast<sword>(VALUE_SWORD_MIN));
|
||||
hi.write_uword(i, static_cast<sword>(0));
|
||||
}
|
||||
// Check for divide by 0, in which case result is undefined (do nothing).
|
||||
else if (val_source2 == 0)
|
||||
{
|
||||
// TODO: check if old PCSX2 code is required (sets HI to the dividend and LO to 1 or -1 depending on if divisor is positive or negative).
|
||||
}
|
||||
// Else perform normal operation.
|
||||
else
|
||||
{
|
||||
sword resultQ = val_source1 / val_source2;
|
||||
sword resultR = val_source1 % val_source2;
|
||||
// Check for VALUE_S32_MIN / -1 (special condition).
|
||||
if (sa == VALUE_SWORD_MIN && divisor == -1)
|
||||
{
|
||||
return {
|
||||
static_cast<uword>(VALUE_SWORD_MIN),
|
||||
static_cast<uword>(0)
|
||||
};
|
||||
}
|
||||
// Check for divide by 0, in which case result is undefined (do nothing).
|
||||
else if (divisor == 0)
|
||||
{
|
||||
// TODO: check if old PCSX2 code is required (sets HI to the dividend and LO to 1 or -1 depending on if divisor is positive or negative).
|
||||
return {
|
||||
static_cast<uword>(0),
|
||||
static_cast<uword>(0)
|
||||
};
|
||||
}
|
||||
// Else perform normal operation.
|
||||
else
|
||||
{
|
||||
return {
|
||||
static_cast<uword>(sa / divisor),
|
||||
static_cast<uword>(sa % divisor)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Quotient.
|
||||
lo.write_uword(i, resultQ);
|
||||
auto[q0, r0] = div(reg_source1->read_uword(0));
|
||||
auto[q1, r1] = div(reg_source1->read_uword(1));
|
||||
auto[q2, r2] = div(reg_source1->read_uword(2));
|
||||
auto[q3, r3] = div(reg_source1->read_uword(3));
|
||||
|
||||
// Remainder.
|
||||
hi.write_uword(i, resultR);
|
||||
}
|
||||
}
|
||||
lo.write_uword(0, q0);
|
||||
lo.write_uword(1, q1);
|
||||
lo.write_uword(2, q2);
|
||||
lo.write_uword(3, q3);
|
||||
|
||||
hi.write_uword(0, r0);
|
||||
hi.write_uword(1, r1);
|
||||
hi.write_uword(2, r2);
|
||||
hi.write_uword(3, r3);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PDIVUW(const EeCoreInstruction inst) const
|
||||
|
@ -201,29 +217,35 @@ void CEeCoreInterpreter::PDIVUW(const EeCoreInstruction inst) const
|
|||
auto& lo = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
auto val_source1 = static_cast<uword>(reg_source1->read_uword(i));
|
||||
auto val_source2 = static_cast<uword>(reg_source2->read_uword(i));
|
||||
auto div = [](const uword a, const uword b) -> std::tuple<udword, udword>
|
||||
{
|
||||
// Check for divide by 0, in which case result is undefined (do nothing).
|
||||
if (b == 0)
|
||||
{
|
||||
// TODO: check if old PCSX2 code is required (sets HI to the dividend and LO to 1 or -1 depending on if divisor is positive or negative).
|
||||
return {
|
||||
static_cast<udword>(0),
|
||||
static_cast<udword>(0)
|
||||
};
|
||||
}
|
||||
// Else perform normal operation.
|
||||
else
|
||||
{
|
||||
return {
|
||||
static_cast<udword>(static_cast<sdword>(static_cast<sword>(a / b))),
|
||||
static_cast<udword>(static_cast<sdword>(static_cast<sword>(a % b)))
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Check for divide by 0, in which case result is undefined (do nothing).
|
||||
if (val_source2 == 0)
|
||||
{
|
||||
// TODO: check if old PCSX2 code is required (sets HI to the dividend and LO to -1).
|
||||
}
|
||||
// Else perform normal operation.
|
||||
else
|
||||
{
|
||||
udword resultQ = val_source1 / val_source2;
|
||||
udword resultR = val_source1 % val_source2;
|
||||
auto[q0, r0] = div(reg_source1->read_uword(0), reg_source2->read_uword(0));
|
||||
auto[q1, r1] = div(reg_source1->read_uword(2), reg_source2->read_uword(2));
|
||||
|
||||
// Quotient.
|
||||
lo.write_udword(i / 2, resultQ);
|
||||
lo.write_udword(0, q0);
|
||||
lo.write_udword(1, q1);
|
||||
|
||||
// Remainder.
|
||||
hi.write_udword(i / 2, resultR);
|
||||
}
|
||||
}
|
||||
hi.write_udword(0, r0);
|
||||
hi.write_udword(1, r1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PDIVW(const EeCoreInstruction inst) const
|
||||
|
@ -237,36 +259,45 @@ void CEeCoreInterpreter::PDIVW(const EeCoreInstruction inst) const
|
|||
auto& lo = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
auto val_source1 = static_cast<uword>(reg_source1->read_uword(i));
|
||||
auto val_source2 = static_cast<uword>(reg_source2->read_uword(i));
|
||||
auto div = [](const uword a, const uword b) -> std::tuple<udword, udword>
|
||||
{
|
||||
sword sa = static_cast<sword>(a);
|
||||
sword sb = static_cast<sword>(b);
|
||||
|
||||
// Check for VALUE_S32_MIN / -1 (special condition).
|
||||
if (val_source1 == VALUE_SWORD_MIN &&
|
||||
val_source2 == -1)
|
||||
{
|
||||
lo.write_udword(i / 2, static_cast<sdword>(VALUE_SWORD_MIN));
|
||||
hi.write_udword(i / 2, static_cast<sdword>(0));
|
||||
}
|
||||
// Check for divide by 0, in which case result is undefined (do nothing).
|
||||
else if (val_source2 == 0)
|
||||
{
|
||||
// TODO: check if old PCSX2 code is required (sets HI to the dividend and LO to 1 or -1 depending on if divisor is positive or negative).
|
||||
}
|
||||
// Else perform normal operation.
|
||||
else
|
||||
{
|
||||
udword resultQ = val_source1 / val_source2;
|
||||
udword resultR = val_source1 % val_source2;
|
||||
if (a == VALUE_SWORD_MIN && b == -1)
|
||||
{
|
||||
return {
|
||||
static_cast<udword>(static_cast<sdword>(VALUE_SWORD_MIN)),
|
||||
static_cast<udword>(static_cast<sdword>(0))
|
||||
};
|
||||
}
|
||||
// Check for divide by 0, in which case result is undefined (do nothing).
|
||||
if (b == 0)
|
||||
{
|
||||
// TODO: check if old PCSX2 code is required (sets HI to the dividend and LO to 1 or -1 depending on if divisor is positive or negative).
|
||||
return {
|
||||
static_cast<udword>(0),
|
||||
static_cast<udword>(0)
|
||||
};
|
||||
}
|
||||
// Else perform normal operation.
|
||||
else
|
||||
{
|
||||
return {
|
||||
static_cast<udword>(static_cast<sdword>(sa / sb)),
|
||||
static_cast<udword>(static_cast<sdword>(sa % sb))
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Quotient.
|
||||
lo.write_udword(i / 2, resultQ);
|
||||
auto[q0, r0] = div(reg_source1->read_uword(0), reg_source2->read_uword(0));
|
||||
auto[q1, r1] = div(reg_source1->read_uword(2), reg_source2->read_uword(2));
|
||||
|
||||
// Remainder.
|
||||
hi.write_udword(i / 2, resultR);
|
||||
}
|
||||
}
|
||||
lo.write_udword(0, q0);
|
||||
lo.write_udword(1, q1);
|
||||
|
||||
hi.write_udword(0, r0);
|
||||
hi.write_udword(1, r1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMULTH(const EeCoreInstruction inst) const
|
||||
|
@ -281,20 +312,38 @@ void CEeCoreInterpreter::PMULTH(const EeCoreInstruction inst) const
|
|||
auto& lo = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<shword>(reg_source1->read_uhword(i));
|
||||
auto val_source2 = static_cast<shword>(reg_source2->read_uhword(i));
|
||||
sword result = val_source1 * val_source2;
|
||||
uword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
if (i % 2 == 0)
|
||||
reg_dest->write_uword(i / 2, result); // Write to Rd for even indexes. A0xB0, A2xB2, A4xB4, A6xB6.
|
||||
auto mult = [](const uhword a, const uhword b) -> uword
|
||||
{
|
||||
sword sa = static_cast<sword>(static_cast<shword>(a));
|
||||
sword sb = static_cast<sword>(static_cast<shword>(b));
|
||||
return static_cast<uword>(sa * sb);
|
||||
};
|
||||
|
||||
if ((i / 2) % 2 == 0)
|
||||
lo.write_uword(((i / 2 > 0) ? i - 2 : i), result); // A0xB0, A1xB1, A4xB4, A5xB5. Array ternary operator is to select the correct index from 0 -> 3.
|
||||
else
|
||||
hi.write_uword(((i / 2 > 1) ? i - 4 : i - 2), result); // A2xB2, A3xB3, A6xB6, A7xB7. Array ternary operator is to select the correct index from 0 -> 3.
|
||||
}
|
||||
value[0] = mult(reg_source1->read_uhword(0), reg_source2->read_uhword(0));
|
||||
value[1] = mult(reg_source1->read_uhword(1), reg_source2->read_uhword(1));
|
||||
value[2] = mult(reg_source1->read_uhword(2), reg_source2->read_uhword(2));
|
||||
value[3] = mult(reg_source1->read_uhword(3), reg_source2->read_uhword(3));
|
||||
value[4] = mult(reg_source1->read_uhword(4), reg_source2->read_uhword(4));
|
||||
value[5] = mult(reg_source1->read_uhword(5), reg_source2->read_uhword(5));
|
||||
value[6] = mult(reg_source1->read_uhword(6), reg_source2->read_uhword(6));
|
||||
value[7] = mult(reg_source1->read_uhword(7), reg_source2->read_uhword(7));
|
||||
|
||||
reg_dest->write_uword(0, value[0]);
|
||||
reg_dest->write_uword(1, value[2]);
|
||||
reg_dest->write_uword(2, value[4]);
|
||||
reg_dest->write_uword(3, value[6]);
|
||||
|
||||
lo.write_uword(0, value[0]);
|
||||
lo.write_uword(1, value[1]);
|
||||
lo.write_uword(2, value[4]);
|
||||
lo.write_uword(3, value[5]);
|
||||
|
||||
hi.write_uword(0, value[2]);
|
||||
hi.write_uword(1, value[3]);
|
||||
hi.write_uword(2, value[6]);
|
||||
hi.write_uword(3, value[7]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMULTUW(const EeCoreInstruction inst) const
|
||||
|
@ -309,16 +358,29 @@ void CEeCoreInterpreter::PMULTUW(const EeCoreInstruction inst) const
|
|||
auto& lo = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
auto val_source1 = static_cast<uword>(reg_source1->read_uword(i));
|
||||
auto val_source2 = static_cast<uword>(reg_source2->read_uword(i));
|
||||
udword result = val_source1 * val_source2;
|
||||
auto mult = [](const uword a, const uword b) -> std::tuple<udword, udword, udword>
|
||||
{
|
||||
udword da = static_cast<udword>(a);
|
||||
udword db = static_cast<udword>(b);
|
||||
udword result = da * db;
|
||||
return {
|
||||
result,
|
||||
static_cast<udword>(static_cast<sdword>(static_cast<sword>(result & 0xFFFFFFFF))),
|
||||
static_cast<udword>(static_cast<sdword>(static_cast<sword>(result >> 32)))
|
||||
};
|
||||
};
|
||||
|
||||
lo.write_udword(i / 2, static_cast<udword>(static_cast<uword>(result & 0xFFFFFFFF)));
|
||||
hi.write_udword(i / 2, static_cast<udword>(static_cast<uword>(result >> 32)));
|
||||
reg_dest->write_udword(i / 2, result);
|
||||
}
|
||||
auto[value0, lo0, hi0] = mult(reg_source1->read_uword(0), reg_source1->read_uword(0));
|
||||
auto[value1, lo1, hi1] = mult(reg_source1->read_uword(2), reg_source1->read_uword(2));
|
||||
|
||||
reg_dest->write_udword(0, value0);
|
||||
reg_dest->write_udword(1, value0);
|
||||
|
||||
lo.write_udword(0, lo0);
|
||||
lo.write_udword(1, lo1);
|
||||
|
||||
hi.write_udword(0, hi0);
|
||||
hi.write_udword(1, hi1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMULTW(const EeCoreInstruction inst) const
|
||||
|
@ -333,14 +395,27 @@ void CEeCoreInterpreter::PMULTW(const EeCoreInstruction inst) const
|
|||
auto& lo = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
auto val_source1 = static_cast<sword>(reg_source1->read_uword(i));
|
||||
auto val_source2 = static_cast<sword>(reg_source2->read_uword(i));
|
||||
sdword result = val_source1 * val_source2;
|
||||
auto mult = [](const uword a, const uword b) -> std::tuple<udword, udword, udword>
|
||||
{
|
||||
sdword sda = static_cast<sdword>(static_cast<sword>(a));
|
||||
sdword sdb = static_cast<sdword>(static_cast<sword>(b));
|
||||
sdword result = sda * sdb;
|
||||
return {
|
||||
static_cast<udword>(result),
|
||||
static_cast<udword>(static_cast<sdword>(static_cast<sword>(result & 0xFFFFFFFF))),
|
||||
static_cast<udword>(static_cast<sdword>(static_cast<sword>(result >> 32)))
|
||||
};
|
||||
};
|
||||
|
||||
lo.write_udword(i / 2, static_cast<sdword>(static_cast<sword>(result & 0xFFFFFFFF)));
|
||||
hi.write_udword(i / 2, static_cast<sdword>(static_cast<sword>(result >> 32)));
|
||||
reg_dest->write_udword(i / 2, result);
|
||||
}
|
||||
auto[value0, lo0, hi0] = mult(reg_source1->read_uword(0), reg_source1->read_uword(0));
|
||||
auto[value1, lo1, hi1] = mult(reg_source1->read_uword(2), reg_source1->read_uword(2));
|
||||
|
||||
reg_dest->write_udword(0, value0);
|
||||
reg_dest->write_udword(1, value0);
|
||||
|
||||
lo.write_udword(0, lo0);
|
||||
lo.write_udword(1, lo1);
|
||||
|
||||
hi.write_udword(0, hi0);
|
||||
hi.write_udword(1, hi1);
|
||||
}
|
|
@ -17,13 +17,20 @@ void CEeCoreInterpreter::PMAXH(const EeCoreInstruction inst) const
|
|||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<shword>(reg_source1->read_uhword(i));
|
||||
auto val_source2 = static_cast<shword>(reg_source2->read_uhword(i));
|
||||
shword result = std::max(val_source2, val_source1); // Format parameters this way as std::max returns parameter 0 if they are equal, and value in Rt is returned according to docs if they are equal.
|
||||
reg_dest->write_uhword(i, result);
|
||||
}
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
auto max = [](const uhword a, const uhword b) -> uhword
|
||||
{
|
||||
shword sa = static_cast<shword>(a);
|
||||
shword sb = static_cast<shword>(b);
|
||||
return static_cast<uhword>(std::max(a, b));
|
||||
};
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
value[i] = max(reg_source1->read_uhword(i), reg_source2->read_uhword(i));
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMAXW(const EeCoreInstruction inst) const
|
||||
|
@ -36,13 +43,20 @@ void CEeCoreInterpreter::PMAXW(const EeCoreInstruction inst) const
|
|||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<sword>(reg_source1->read_uword(i));
|
||||
auto val_source2 = static_cast<sword>(reg_source2->read_uword(i));
|
||||
sword result = std::max(val_source2, val_source1); // Format parameters this way as std::max returns parameter 0 if they are equal, and value in Rt is returned according to docs if they are equal.
|
||||
reg_dest->write_uword(i, result);
|
||||
}
|
||||
uword value[NUMBER_WORDS_IN_QWORD];
|
||||
|
||||
auto max = [](const uword a, const uword b) -> uword
|
||||
{
|
||||
sword sa = static_cast<sword>(a);
|
||||
sword sb = static_cast<sword>(b);
|
||||
return static_cast<uword>(std::max(a, b));
|
||||
};
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
value[i] = max(reg_source1->read_uword(i), reg_source2->read_uword(i));
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMINH(const EeCoreInstruction inst) const
|
||||
|
@ -55,13 +69,20 @@ void CEeCoreInterpreter::PMINH(const EeCoreInstruction inst) const
|
|||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<shword>(reg_source1->read_uhword(i));
|
||||
auto val_source2 = static_cast<shword>(reg_source2->read_uhword(i));
|
||||
shword result = std::min(val_source1, val_source2); // Format parameters this way as std::min returns parameter 0 if they are equal, and value in Rs is returned according to docs if they are equal.
|
||||
reg_dest->write_uhword(i, result);
|
||||
}
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
auto max = [](const uhword a, const uhword b) -> uhword
|
||||
{
|
||||
shword sa = static_cast<shword>(a);
|
||||
shword sb = static_cast<shword>(b);
|
||||
return static_cast<uhword>(std::min(a, b));
|
||||
};
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
value[i] = max(reg_source1->read_uhword(i), reg_source2->read_uhword(i));
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMINW(const EeCoreInstruction inst) const
|
||||
|
@ -74,13 +95,20 @@ void CEeCoreInterpreter::PMINW(const EeCoreInstruction inst) const
|
|||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<sword>(reg_source1->read_uword(i));
|
||||
auto val_source2 = static_cast<sword>(reg_source2->read_uword(i));
|
||||
sword result = std::min(val_source1, val_source2); // Format parameters this way as std::min returns parameter 0 if they are equal, and value in Rs is returned according to docs if they are equal.
|
||||
reg_dest->write_uword(i, result);
|
||||
}
|
||||
uword value[NUMBER_WORDS_IN_QWORD];
|
||||
|
||||
auto max = [](const uword a, const uword b) -> uword
|
||||
{
|
||||
sword sa = static_cast<sword>(a);
|
||||
sword sb = static_cast<sword>(b);
|
||||
return static_cast<uword>(std::min(a, b));
|
||||
};
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
value[i] = max(reg_source1->read_uword(i), reg_source2->read_uword(i));
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::MAX_S(const EeCoreInstruction inst) const
|
||||
|
|
|
@ -169,19 +169,22 @@ void CEeCoreInterpreter::PMFHL_LH(const EeCoreInstruction inst) const
|
|||
|
||||
// Rd = (HI, LO). No exceptions.
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
auto& reg_source1 = r.ee.core.r5900.hi;
|
||||
auto& reg_source2 = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
auto& lo = r.ee.core.r5900.lo;
|
||||
|
||||
// Use mappings to implement this instruction, -1 means not used, and >0 number means the index within Rd.
|
||||
sword HIIndex[] = { 2, -1, 3, -1, 6, -1, 7, -1 };
|
||||
sword LOIndex[] = { 0, -1, 1, -1, 4, -1, 5, -1 };
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
if (HIIndex[i] != -1)
|
||||
reg_dest->write_uhword(HIIndex[i], reg_source1.read_uhword(i));
|
||||
if (LOIndex[i] != -1)
|
||||
reg_dest->write_uhword(LOIndex[i], reg_source2.read_uhword(i));
|
||||
}
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
value[0] = lo.read_uhword(0);
|
||||
value[1] = lo.read_uhword(2);
|
||||
value[2] = hi.read_uhword(0);
|
||||
value[3] = hi.read_uhword(2);
|
||||
value[4] = lo.read_uhword(4);
|
||||
value[5] = lo.read_uhword(6);
|
||||
value[6] = hi.read_uhword(4);
|
||||
value[7] = hi.read_uhword(6);
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMFHL_LW(const EeCoreInstruction inst) const
|
||||
|
@ -190,19 +193,18 @@ void CEeCoreInterpreter::PMFHL_LW(const EeCoreInstruction inst) const
|
|||
|
||||
// Rd = (HI, LO). No exceptions.
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
auto& reg_source1 = r.ee.core.r5900.hi;
|
||||
auto& reg_source2 = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
auto& lo = r.ee.core.r5900.lo;
|
||||
|
||||
// Use mappings to implement this instruction, -1 means not used, and >0 number means the index within Rd.
|
||||
sword HIIndex[] = { 1, -1, 3, -1 };
|
||||
sword LOIndex[] = { 0, -1, 2, -1 };
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
if (HIIndex[i] != -1)
|
||||
reg_dest->write_uword(HIIndex[i], reg_source1.read_uword(i));
|
||||
if (LOIndex[i] != -1)
|
||||
reg_dest->write_uword(LOIndex[i], reg_source2.read_uword(i));
|
||||
}
|
||||
uword value[NUMBER_WORDS_IN_QWORD];
|
||||
|
||||
value[0] = lo.read_uword(0);
|
||||
value[1] = hi.read_uword(0);
|
||||
value[2] = lo.read_uword(2);
|
||||
value[3] = hi.read_uword(2);
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMFHL_SH(const EeCoreInstruction inst) const
|
||||
|
@ -211,22 +213,29 @@ void CEeCoreInterpreter::PMFHL_SH(const EeCoreInstruction inst) const
|
|||
|
||||
// Rd = (HI, LO). No exceptions.
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
auto& reg_source1 = r.ee.core.r5900.hi;
|
||||
auto& reg_source2 = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
auto& lo = r.ee.core.r5900.lo;
|
||||
|
||||
// Use mappings to implement this instruction, -1 means not used, and >0 number means the index within Rd.
|
||||
sword HIIndex[] = { 2, 3, 6, 7 };
|
||||
sword LOIndex[] = { 0, 1, 4, 5 };
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
auto val_source1 = static_cast<sword>(reg_source1.read_uword(i));
|
||||
auto val_source2 = static_cast<sword>(reg_source2.read_uword(i));
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
if (HIIndex[i] != -1)
|
||||
reg_dest->write_uhword(HIIndex[i], saturating_word_to_hword(val_source1));
|
||||
if (LOIndex[i] != -1)
|
||||
reg_dest->write_uhword(LOIndex[i], saturating_word_to_hword(val_source2));
|
||||
}
|
||||
auto saturate = [](const uword value) -> uhword
|
||||
{
|
||||
sword svalue = static_cast<sword>(value);
|
||||
shword shvalue = saturate_word_to_hword(svalue);
|
||||
return static_cast<uhword>(shvalue);
|
||||
};
|
||||
|
||||
value[0] = saturate(lo.read_uword(0));
|
||||
value[1] = saturate(lo.read_uword(1));
|
||||
value[2] = saturate(hi.read_uword(0));
|
||||
value[3] = saturate(hi.read_uword(1));
|
||||
value[4] = saturate(lo.read_uword(2));
|
||||
value[5] = saturate(lo.read_uword(3));
|
||||
value[6] = saturate(hi.read_uword(2));
|
||||
value[7] = saturate(hi.read_uword(3));
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMFHL_SLW(const EeCoreInstruction inst) const
|
||||
|
@ -235,20 +244,22 @@ void CEeCoreInterpreter::PMFHL_SLW(const EeCoreInstruction inst) const
|
|||
|
||||
// Rd = (HI, LO). No exceptions.
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
auto& reg_source1 = r.ee.core.r5900.hi;
|
||||
auto& reg_source2 = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
auto& lo = r.ee.core.r5900.lo;
|
||||
|
||||
// Indexes 0 and 2 get copied.
|
||||
sdword tempValue;
|
||||
sword result;
|
||||
auto clamp = [] (const uword lo, const uword hi) -> udword
|
||||
{
|
||||
udword dhi = static_cast<udword>(hi) << 32;
|
||||
udword dlo = static_cast<udword>(lo);
|
||||
sdword dvalue = static_cast<sdword>(saturate_dword_to_word(static_cast<sdword>(hi | lo)));
|
||||
return static_cast<udword>(dvalue);
|
||||
};
|
||||
|
||||
tempValue = static_cast<sdword>((static_cast<udword>(reg_source1.read_uword(0)) << 32) | static_cast<udword>(reg_source2.read_uword(0)));
|
||||
result = saturating_dword_to_word(tempValue);
|
||||
reg_dest->write_udword(0, result);
|
||||
udword value0 = clamp(lo.read_uword(0), hi.read_uword(0));
|
||||
udword value1 = clamp(lo.read_uword(2), hi.read_uword(2));
|
||||
|
||||
tempValue = static_cast<sdword>((static_cast<udword>(reg_source1.read_uword(2)) << 32) | static_cast<udword>(reg_source2.read_uword(2)));
|
||||
result = saturating_dword_to_word(tempValue);
|
||||
reg_dest->write_udword(1, result);
|
||||
reg_dest->write_udword(0, value0);
|
||||
reg_dest->write_udword(1, value1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMFHL_UW(const EeCoreInstruction inst) const
|
||||
|
@ -257,19 +268,18 @@ void CEeCoreInterpreter::PMFHL_UW(const EeCoreInstruction inst) const
|
|||
|
||||
// Rd = (HI, LO). No exceptions.
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
auto& reg_source1 = r.ee.core.r5900.hi;
|
||||
auto& reg_source2 = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
auto& lo = r.ee.core.r5900.lo;
|
||||
|
||||
// Use mappings to implement this instruction, -1 means not used, and >0 number means the index within Rd.
|
||||
sword HIIndex[] = { -1, 1, -1, 3 };
|
||||
sword LOIndex[] = { -1, 0, -1, 2 };
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
if (HIIndex[i] != -1)
|
||||
reg_dest->write_uword(HIIndex[i], reg_source1.read_uword(i));
|
||||
if (LOIndex[i] != -1)
|
||||
reg_dest->write_uword(LOIndex[i], reg_source2.read_uword(i));
|
||||
}
|
||||
uword value0 = lo.read_uword(1);
|
||||
uword value1 = hi.read_uword(1);
|
||||
uword value2 = lo.read_uword(3);
|
||||
uword value3 = hi.read_uword(3);
|
||||
|
||||
reg_dest->write_uword(0, value0);
|
||||
reg_dest->write_uword(1, value1);
|
||||
reg_dest->write_uword(2, value2);
|
||||
reg_dest->write_uword(3, value3);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMFLO(const EeCoreInstruction inst) const
|
||||
|
@ -302,16 +312,19 @@ void CEeCoreInterpreter::PMTHL_LW(const EeCoreInstruction inst) const
|
|||
|
||||
// (HI, LO) = Rs. No exceptions.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rs()];
|
||||
auto& reg_dest1 = r.ee.core.r5900.hi;
|
||||
auto& reg_dest2 = r.ee.core.r5900.lo;
|
||||
auto& hi = r.ee.core.r5900.hi;
|
||||
auto& lo = r.ee.core.r5900.lo;
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
reg_dest2.write_uword(i, reg_source1->read_uword(i));
|
||||
else
|
||||
reg_dest1.write_uword(i - 1, reg_source1->read_uword(i));
|
||||
}
|
||||
uword value0 = reg_source1->read_uword(0);
|
||||
uword value1 = reg_source1->read_uword(1);
|
||||
uword value2 = reg_source1->read_uword(2);
|
||||
uword value3 = reg_source1->read_uword(3);
|
||||
|
||||
lo.write_uword(0, value0);
|
||||
lo.write_uword(2, value2);
|
||||
|
||||
hi.write_uword(0, value1);
|
||||
hi.write_uword(2, value3);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PMTLO(const EeCoreInstruction inst) const
|
||||
|
|
|
@ -222,12 +222,15 @@ void CEeCoreInterpreter::PSLLH(const EeCoreInstruction inst) const
|
|||
// No Exceptions generated.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
ubyte shamt = inst.shamt() & 0xF;
|
||||
int shamt = inst.shamt() & 0xF;
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
reg_dest->write_uhword(i, reg_source1->read_uhword(i) << shamt);
|
||||
}
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
value[i] = reg_source1->read_uhword(i) << shamt;
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSLLVW(const EeCoreInstruction inst) const
|
||||
|
@ -239,13 +242,25 @@ void CEeCoreInterpreter::PSLLVW(const EeCoreInstruction inst) const
|
|||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rs()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
auto shift = [](const uword value, const int shamt) -> udword
|
||||
{
|
||||
sdword result = static_cast<sdword>(static_cast<sword>(value << shamt));
|
||||
return static_cast<udword>(result);
|
||||
};
|
||||
|
||||
udword value0 = shift(
|
||||
reg_source1->read_uword(0),
|
||||
reg_source2->read_uword(0) & 0x1F
|
||||
);
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
ubyte shamt = reg_source2->read_uword(i) & 0x1F;
|
||||
sdword result = static_cast<sdword>(reg_source1->read_uword(i) << shamt);
|
||||
reg_dest->write_udword(i / 2, result);
|
||||
}
|
||||
udword value1 = shift(
|
||||
reg_source1->read_uword(2),
|
||||
reg_source2->read_uword(2) & 0x1F
|
||||
);
|
||||
|
||||
reg_dest->write_udword(0, value0);
|
||||
reg_dest->write_udword(1, value1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSLLW(const EeCoreInstruction inst) const
|
||||
|
@ -256,12 +271,15 @@ void CEeCoreInterpreter::PSLLW(const EeCoreInstruction inst) const
|
|||
// No Exceptions generated.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
ubyte shamt = inst.shamt();
|
||||
int shamt = inst.shamt();
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
reg_dest->write_uword(i, reg_source1->read_uword(i) << shamt);
|
||||
}
|
||||
uword value[NUMBER_WORDS_IN_QWORD];
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
value[i] = reg_source1->read_uword(i) << shamt;
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSRAH(const EeCoreInstruction inst) const
|
||||
|
@ -272,12 +290,15 @@ void CEeCoreInterpreter::PSRAH(const EeCoreInstruction inst) const
|
|||
// No Exceptions generated.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
ubyte shamt = inst.shamt() & 0xF;
|
||||
int shamt = inst.shamt() & 0xF;
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
reg_dest->write_uhword(i, static_cast<shword>(reg_source1->read_uhword(i)) >> shamt);
|
||||
}
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
value[i] = static_cast<uhword>(static_cast<shword>(reg_source1->read_uhword(i)) >> shamt);
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSRAVW(const EeCoreInstruction inst) const
|
||||
|
@ -290,12 +311,24 @@ void CEeCoreInterpreter::PSRAVW(const EeCoreInstruction inst) const
|
|||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rs()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
ubyte shamt = reg_source2->read_uword(i) & 0x1F;
|
||||
sdword result = static_cast<sdword>(static_cast<sword>(reg_source1->read_uword(i)) >> shamt);
|
||||
reg_dest->write_udword(i / 2, result);
|
||||
}
|
||||
auto shift = [](const uword value, const int shamt) -> udword
|
||||
{
|
||||
sdword result = static_cast<sdword>(static_cast<sword>(value) >> shamt);
|
||||
return static_cast<udword>(result);
|
||||
};
|
||||
|
||||
udword value0 = shift(
|
||||
reg_source1->read_uword(0),
|
||||
reg_source2->read_uword(0) & 0x1F
|
||||
);
|
||||
|
||||
udword value1 = shift(
|
||||
reg_source1->read_uword(2),
|
||||
reg_source2->read_uword(2) & 0x1F
|
||||
);
|
||||
|
||||
reg_dest->write_udword(0, value0);
|
||||
reg_dest->write_udword(1, value1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSRAW(const EeCoreInstruction inst) const
|
||||
|
@ -306,12 +339,15 @@ void CEeCoreInterpreter::PSRAW(const EeCoreInstruction inst) const
|
|||
// No Exceptions generated.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
ubyte shamt = inst.shamt();
|
||||
int shamt = inst.shamt();
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
reg_dest->write_uword(i, static_cast<sword>(reg_source1->read_uword(i)) >> shamt);
|
||||
}
|
||||
uword value[NUMBER_WORDS_IN_QWORD];
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
value[i] = static_cast<uword>(static_cast<sword>(reg_source1->read_uword(i)) >> shamt);
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSRLH(const EeCoreInstruction inst) const
|
||||
|
@ -322,12 +358,15 @@ void CEeCoreInterpreter::PSRLH(const EeCoreInstruction inst) const
|
|||
// No Exceptions generated.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
ubyte shamt = inst.shamt() & 0xF;
|
||||
int shamt = inst.shamt() & 0xF;
|
||||
|
||||
for (auto i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
{
|
||||
reg_dest->write_uhword(i, reg_source1->read_uhword(i) >> shamt);
|
||||
}
|
||||
uhword value[NUMBER_HWORDS_IN_QWORD];
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
value[i] = reg_source1->read_uhword(i) >> shamt;
|
||||
|
||||
for (int i = 0; i < NUMBER_HWORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uhword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSRLVW(const EeCoreInstruction inst) const
|
||||
|
@ -340,12 +379,24 @@ void CEeCoreInterpreter::PSRLVW(const EeCoreInstruction inst) const
|
|||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rs()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i += 2)
|
||||
{
|
||||
ubyte shamt = reg_source2->read_uword(i) & 0x1F;
|
||||
sdword result = static_cast<sdword>(reg_source1->read_uword(i) >> shamt);
|
||||
reg_dest->write_udword(i / 2, result);
|
||||
}
|
||||
auto shift = [](const uword value, const int shamt) -> udword
|
||||
{
|
||||
sdword result = static_cast<sdword>(static_cast<sword>(value >> shamt));
|
||||
return static_cast<udword>(result);
|
||||
};
|
||||
|
||||
udword value0 = shift(
|
||||
reg_source1->read_uword(0),
|
||||
reg_source2->read_uword(0) & 0x1F
|
||||
);
|
||||
|
||||
udword value1 = shift(
|
||||
reg_source1->read_uword(2),
|
||||
reg_source2->read_uword(2) & 0x1F
|
||||
);
|
||||
|
||||
reg_dest->write_udword(0, value0);
|
||||
reg_dest->write_udword(1, value1);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::PSRLW(const EeCoreInstruction inst) const
|
||||
|
@ -356,12 +407,15 @@ void CEeCoreInterpreter::PSRLW(const EeCoreInstruction inst) const
|
|||
// No Exceptions generated.
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
ubyte shamt = inst.shamt();
|
||||
int shamt = inst.shamt();
|
||||
|
||||
for (auto i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
{
|
||||
reg_dest->write_uword(i, reg_source1->read_uword(i) >> shamt);
|
||||
}
|
||||
uword value[NUMBER_WORDS_IN_QWORD];
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
value[i] = reg_source1->read_uword(i) >> shamt;
|
||||
|
||||
for (int i = 0; i < NUMBER_WORDS_IN_QWORD; i++)
|
||||
reg_dest->write_uword(i, value[i]);
|
||||
}
|
||||
|
||||
void CEeCoreInterpreter::QFSRV(const EeCoreInstruction inst) const
|
||||
|
@ -370,7 +424,7 @@ void CEeCoreInterpreter::QFSRV(const EeCoreInstruction inst) const
|
|||
|
||||
// Rd (lower 128-bits) = (Rs || Rt)(256-bit concatenation) >> SA. Logical shift? Not specified, but assumed to be.
|
||||
// No Exceptions generated.
|
||||
// TODO: check this instruction... were they high when they created this???
|
||||
// TODO: check this instruction... not sure how to make this efficient???
|
||||
auto& reg_source1 = r.ee.core.r5900.gpr[inst.rt()];
|
||||
auto& reg_source2 = r.ee.core.r5900.gpr[inst.rs()];
|
||||
auto& reg_dest = r.ee.core.r5900.gpr[inst.rd()];
|
||||
|
|
|
@ -4,21 +4,21 @@
|
|||
|
||||
#include "Utilities/Utilities.hpp"
|
||||
|
||||
uword count_leading_bits(sword value)
|
||||
int count_leading_bits(const sword value)
|
||||
{
|
||||
|
||||
// If the value is 0, return 32 automatically.
|
||||
if (value == 0)
|
||||
return 32;
|
||||
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
if (value < 0)
|
||||
value = ~value;
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
sword conditioned = value < 0 ? ~value : value;
|
||||
|
||||
// Perform our count leading zero.
|
||||
uword num_leading_bits = 0;
|
||||
for (int i = CHAR_BIT * sizeof value; i > 0; i--)
|
||||
int num_leading_bits = 0;
|
||||
for (int i = CHAR_BIT * sizeof(conditioned); i > 0; i--)
|
||||
{
|
||||
if ((value & (1 << (i - 1))) == 0)
|
||||
if ((conditioned & (1 << (i - 1))) == 0)
|
||||
num_leading_bits++;
|
||||
else
|
||||
break;
|
||||
|
@ -27,17 +27,17 @@ uword count_leading_bits(sword value)
|
|||
return num_leading_bits;
|
||||
}
|
||||
|
||||
shword saturating_word_to_hword(sword value)
|
||||
shword saturate_word_to_hword(const sword value)
|
||||
{
|
||||
if (value > VALUE_SHWORD_MAX)
|
||||
if (value > static_cast<sword>(VALUE_SHWORD_MAX))
|
||||
return VALUE_SHWORD_MAX;
|
||||
else if (value < VALUE_SHWORD_MIN)
|
||||
else if (value < static_cast<sword>(VALUE_SHWORD_MIN))
|
||||
return VALUE_SHWORD_MIN;
|
||||
else
|
||||
return static_cast<shword>(value);
|
||||
}
|
||||
|
||||
sword saturating_dword_to_word(sdword value)
|
||||
sword saturate_dword_to_word(const sdword value)
|
||||
{
|
||||
if (value > VALUE_SWORD_MAX)
|
||||
return VALUE_SWORD_MAX;
|
||||
|
|
|
@ -14,15 +14,15 @@ ubyte get_float_exponent(const f32 value);
|
|||
|
||||
/// Counts leading bits (1's) from a 32-bit value.
|
||||
/// Example: in 0b1110001..., the answer is 3.
|
||||
uword count_leading_bits(sword value); // Adapted from the old PCSX2 code and Stackoverflow (see inside body). Thanks everyone!
|
||||
int count_leading_bits(const sword value);
|
||||
|
||||
/// Saturates/clamps values to the next smallest size, if above the maximum value allowed.
|
||||
/// Saturates values to the next smallest size, if above the maximum value allowed.
|
||||
/// Eg: for 0x02345678 to hword, this becomes 0x7FFF;
|
||||
shword saturating_word_to_hword(sword value);
|
||||
sword saturating_dword_to_word(sdword value);
|
||||
shword saturate_word_to_hword(const sword value);
|
||||
sword saturate_dword_to_word(const sdword value);
|
||||
|
||||
/// Provided x and y, returns a bool for the condition that addition it will not overflow, and for subtraction it will not underflow.
|
||||
/// User must select the appropriate bit size (ie 32, 64).
|
||||
/// Thanks to http://stackoverflow.com/questions/199333/how-to-detect-integer-overflow-in-c-c
|
||||
bool test_over_or_underflow_32(sword x, sword y);
|
||||
bool test_over_or_underflow_64(sdword x, sdword y);
|
||||
bool test_over_or_underflow_32(const sword x, const sword y);
|
||||
bool test_over_or_underflow_64(const sdword x, const sdword y);
|
||||
|
|
Loading…
Reference in a new issue