Some instruction encoding combinations are not documented in the Cray manuals. These were asserted upon previously. This causes crashes if those instructions are encountered. Obviously not ideal for "production" code. The new behavior replaces these by the exceptions that can be supressed.
862 lines
28 KiB
C++
862 lines
28 KiB
C++
// Cray-1S CPU simulator class
|
|
|
|
// !!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!
|
|
// !!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!
|
|
//
|
|
// To be true to the documentation, octal numbers are extensively used in this file.
|
|
// Watch out for the leading 0-s!
|
|
//
|
|
// !!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!
|
|
// !!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!
|
|
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0040(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0040);
|
|
// Si exp
|
|
if (IsXMode()) {
|
|
CInt_t Value = CInt_t(jkm);
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << HexPrinter(Value);
|
|
}
|
|
if (aDoExecute) {
|
|
RefSiTarget = Value;
|
|
}
|
|
return 2;
|
|
}
|
|
else {
|
|
CInt_t Value = CInt_t(mn);
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << HexPrinter(Value);
|
|
}
|
|
if (aDoExecute) {
|
|
CRAY_UNDOCUMENTED_FLOW_THROUGH(jk == 000);
|
|
RefSiTarget = Value;
|
|
}
|
|
return 3;
|
|
}
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0041(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0041);
|
|
// Si -exp
|
|
if (IsXMode()) {
|
|
CInt_t Value = ~CInt_t(jkm);
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << HexPrinter(Value);
|
|
}
|
|
if (aDoExecute) {
|
|
RefSiTarget = Value;
|
|
}
|
|
return 2;
|
|
}
|
|
else {
|
|
CInt_t Value = ~CInt_t(mn);
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << HexPrinter(Value);
|
|
}
|
|
if (aDoExecute) {
|
|
CRAY_UNDOCUMENTED_FLOW_THROUGH(jk == 000);
|
|
RefSiTarget = Value;
|
|
}
|
|
return 3;
|
|
}
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0042(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0042);
|
|
// Si <exp
|
|
|
|
if (!aDoExecute) {
|
|
switch (jk) {
|
|
case 077:
|
|
aDisassembly << RefSiTarget << " 1";
|
|
break;
|
|
case 000:
|
|
aDisassembly << RefSiTarget << " -1";
|
|
break;
|
|
default:
|
|
aDisassembly << RefSiTarget << " <" << 64 - jk;
|
|
aExplanation << "form " << 64 - jk << " ones from right";
|
|
break;
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = (0xffffffffffffffffULL) >> (jk);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0043(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0043);
|
|
// Si >exp
|
|
|
|
if (!aDoExecute) {
|
|
switch (jk) {
|
|
case 000:
|
|
aDisassembly << RefSiTarget << " 0";
|
|
break;
|
|
default:
|
|
aDisassembly << RefSiTarget << " >" << jk;
|
|
aExplanation << "form " << jk << " ones from left";
|
|
break;
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
if (jk == 0) {
|
|
RefSi = 0;
|
|
}
|
|
else {
|
|
RefSi = (0xffffffffffffffffULL) << (64 - jk);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0044(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0044);
|
|
// Si Sj&Sk
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "&" << RefSk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = RefSj & RefSk;
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0045(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0045);
|
|
// Si #Sk&Sj
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " #" << RefSk << "&" << RefSj;
|
|
aExplanation << RefSiTarget << " not(" << RefSk << ") and (" << RefSj << ")";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = RefSj & ~RefSk;
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0046(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0046);
|
|
// Si Sj\Sk (xor)
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "\\" << RefSk;
|
|
aExplanation << RefSiTarget << " " << RefSj << " xor " << RefSk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = RefSj ^ RefSk;
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0047(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0047);
|
|
// Si #Sj\Sk (xnor)
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " #" << RefSj << "\\" << RefSk;
|
|
aExplanation << RefSiTarget << " not(" << RefSj << ") xor " << RefSk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = ~RefSj ^ RefSk;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0050(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0050);
|
|
// Si Sj!Si&Sk (scalar merge)
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "!" << RefSi << "&" << RefSk;
|
|
aExplanation << RefSiTarget << " bit-wise " << RefSk << "==1 ? " << RefSj << ":" << RefSi;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = (RefSj & RefSk) | (RefSi & ~RefSk);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0051(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0051);
|
|
// Si Sj!Sk (or)
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "!" << RefSk;
|
|
aExplanation << RefSiTarget << " " << RefSj << " or " << RefSk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = RefSj | RefSk;
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0052(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0052);
|
|
// S0 Si < exp
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << "S0 " << RefSi << " < " << jk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefS0 = ShiftLeft(RefSi, CAddr_t(jk));
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0053(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0053);
|
|
// S0 Si > exp
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << "S0 " << RefSi << " > " << 64 - jk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefS0 = ShiftRight(RefSi, CAddr_t(64 - jk)); // It should be unsigned already, but just to be extra sure in case someone changes CInt_t to signed
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0054(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0054);
|
|
// Si Si < exp
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSi << " < " << jk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = ShiftLeft(RefSi, CAddr_t(jk));
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0055(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0055);
|
|
// Si Si > exp
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSi << " > " << 64 - jk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = ShiftRight(RefSi, CAddr_t(64 - jk)); // It should be unsigned already, but just to be extra sure in case someone changes CInt_t to signed
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0056(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0056);
|
|
// Si Si,Sj < Ak
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSi << "," << RefSj << " < " << RefAk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = DoubleShiftLeft(RefSi, RefSj, RefAk);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0057(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0057);
|
|
// Si Sj,Si > Ak
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "," << RefSi << " > " << RefAk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = DoubleShiftRight(RefSj, RefSi, RefAk);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0060(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0060);
|
|
// Si Sj+Sk
|
|
|
|
if (!aDoExecute) {
|
|
if (j == 0) {
|
|
aDisassembly << RefSiTarget << " " << RefSk;
|
|
}
|
|
else {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "+" << RefSk;
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = CInt_t(RefSj) + CInt_t(RefSk);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0061(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0061); // Si Sj-Sk
|
|
|
|
if (!aDoExecute) {
|
|
if (j == 0) {
|
|
aDisassembly << RefSiTarget << " -" << RefSk;
|
|
}
|
|
else {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "-" << RefSk;
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = CInt_t(RefSj) - CInt_t(RefSk);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0062(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0062); // Si Sj+FSk
|
|
|
|
if (!aDoExecute) {
|
|
if (j == 0) {
|
|
aDisassembly << RefSiTarget << " F" << RefSk;
|
|
aExplanation << "Normalize " << RefSk;
|
|
}
|
|
else {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "+F" << RefSk;
|
|
aExplanation << "floating point addition";
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
CFloat_t J = CFloat_t(RefSj);
|
|
CFloat_t K = CFloat_t(RefSk);
|
|
CFloat_t I = J + K;
|
|
// double dI = J.ToDouble() + K.ToDouble();
|
|
// if (!TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " + " << DoublePrinter(K) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " + " << DoublePrinter(K) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " + " << DoublePrinter(K) << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0063(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0063); // Si Sj-FSk
|
|
|
|
if (!aDoExecute) {
|
|
if (j == 0) {
|
|
aDisassembly << RefSiTarget << " -F" << RefSk;
|
|
aExplanation << "floating point subtraction";
|
|
}
|
|
else {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "-F" << RefSk;
|
|
aExplanation << "floating point subtraction";
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
CFloat_t J = CFloat_t(RefSj);
|
|
CFloat_t K = CFloat_t(RefSk);
|
|
CFloat_t I = J - K;
|
|
// double dI = J.ToDouble() - K.ToDouble();
|
|
// if (!TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " - " << DoublePrinter(K) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " - " << DoublePrinter(K) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " - " << DoublePrinter(K) << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0064(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0064); // Si Sj*FSk
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "*F" << RefSk;
|
|
aExplanation << "floating point multiplication";
|
|
}
|
|
if (aDoExecute) {
|
|
CFloat_t J = CFloat_t(RefSj);
|
|
CFloat_t K = CFloat_t(RefSk);
|
|
CFloat_t I = J * K;
|
|
// {
|
|
// bool IntegerMult = (J.RawExp() == 0 && K.RawExp() == 0);
|
|
// if (IntegerMult) {
|
|
// uint64_t FractA = J.UFract();
|
|
// uint64_t FractB = K.UFract();
|
|
// if ((FractA & 0xffffffull) != 0 || (FractB & 0xffffffull) != 0) {
|
|
// DumpHistory();
|
|
// }
|
|
// }
|
|
// }
|
|
// double dI = J.ToDouble() * K.ToDouble();
|
|
// if ((J.Exp() != -CFloat_t::ExpOfs || K.Exp() != -CFloat_t::ExpOfs) && !TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " H* " << DoublePrinter(K) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " H* " << DoublePrinter(K) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " F* " << DoublePrinter(K) << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0065(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0065); // Si Sj*HSk
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "*H" << RefSk;
|
|
aExplanation << "Half-precision floating point multiplication";
|
|
}
|
|
if (aDoExecute) {
|
|
CHalfFloat_t J = CHalfFloat_t(RefSj);
|
|
CHalfFloat_t K = CHalfFloat_t(RefSk);
|
|
CHalfFloat_t I = HalfPrecisionMult(J, K);
|
|
// double dI = J.ToDouble() * K.ToDouble();
|
|
// if ((J.Exp() != -CFloat_t::ExpOfs || K.Exp() != -CFloat_t::ExpOfs) && !TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " H* " << DoublePrinter(K) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " H* " << DoublePrinter(K) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " H* " << DoublePrinter(K) << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0066(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0066); // Si Sj*RSk
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "*R" << RefSk;
|
|
aExplanation << "Rounded floating point multiplication";
|
|
}
|
|
if (aDoExecute) {
|
|
CFloat_t J = CFloat_t(RefSj);
|
|
CFloat_t K = CFloat_t(RefSk);
|
|
CFloat_t I = RoundedMult(J, K);
|
|
// double dI = J.ToDouble() * K.ToDouble();
|
|
// if ((J.Exp() != -CFloat_t::ExpOfs || K.Exp() != -CFloat_t::ExpOfs) && !TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " R* " << DoublePrinter(K) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " R* " << DoublePrinter(K) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " R* " << DoublePrinter(K) << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0067(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0067); // Si Sj*ISk
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << "*I" << RefSk;
|
|
aExplanation << "Reciprocial iteration: " << RefSiTarget << " = 2-" << RefSj << "*" << RefSk;
|
|
}
|
|
if (aDoExecute) {
|
|
CFloat_t J = CFloat_t(RefSj);
|
|
CFloat_t K = CFloat_t(RefSk);
|
|
CFloat_t I = ReciprocIterate(J, K);
|
|
// double dI = 2.0 - J.ToDouble() * K.ToDouble();
|
|
// if (!TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " (RI) " << DoublePrinter(K) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << " " << HexPrinter(K.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " (RI) " << DoublePrinter(K) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << DoublePrinter(I) << " = " << DoublePrinter(J) << " (RI) " << DoublePrinter(K) << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0070(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0070); // Si /HSj
|
|
switch (k) {
|
|
case 0:
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " /H" << RefSj;
|
|
aExplanation << "Reciproc";
|
|
}
|
|
if (aDoExecute) {
|
|
CFloat_t J = CFloat_t(RefSj);
|
|
CFloat_t I = ReciprocApprox(J);
|
|
// double dI = 1.0 / J.ToDouble();
|
|
// if (!TestResult(dI, I, mLogger)) {
|
|
// mLogger << setloglevel(LogLevel_Always) << "Binary input values: " << HexPrinter(J.Value) << std::endl;
|
|
// mLogger << setloglevel(LogLevel_Always) << "Floating point values: " << DoublePrinter(I) << " = 1/" << DoublePrinter(J) << std::endl;
|
|
// std::cout << "Binary input values: " << HexPrinter(J.Value) << std::endl;
|
|
// std::cout << "Floating point values: " << DoublePrinter(I) << " = 1/" << DoublePrinter(J) << std::endl;
|
|
// //CRAY_ASSERT(false);
|
|
// }
|
|
mLogger << setloglevel(LogLevel_SideEffects) << SideEffectIndent << "Floating point values: " << I.ToDouble() << " = 1/" << J.ToDouble() << std::endl;
|
|
RefSi = CInt_t(I);
|
|
}
|
|
return 1;
|
|
case 6: // Si Sj * BT
|
|
if (IsSV1()) {
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSj << " * BT";
|
|
aExplanation << "Transmit the bit-matrix product of (Sj ) and transpose of (BMM) to Si. *********** UNIMPLEMENTED FOR NOW ***********";
|
|
}
|
|
if (aDoExecute) {
|
|
CRAY_UNDOCUMENTED_FLOW_THROUGH(mState.Mode.IsSv1BitMatrixLoaded());
|
|
CInt_t Result = 0;
|
|
for (int i = 0; i < mState.VL; ++i) {
|
|
Result ^= RefSj & RefBM[i];
|
|
}
|
|
RefSiTarget = Result;
|
|
}
|
|
}
|
|
else {
|
|
CRAY_UNKNOWN
|
|
}
|
|
return 1;
|
|
default:
|
|
CRAY_UNKNOWN
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0071(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0071);
|
|
switch (j) {
|
|
|
|
case 0: // Si Ak
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefAk;
|
|
aExplanation << "Assign with no sign-extension";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = CInt_t(CAddr_t(RefAk));
|
|
}
|
|
return 1;
|
|
case 1: // Si +Ak
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " +" << RefAk;
|
|
aExplanation << "Assign with sign-extension";
|
|
}
|
|
if (aDoExecute) {
|
|
if (IsXMode()) {
|
|
RefSi = uint64_t(SignExtendLongLong(CXmpAddr_t(RefAk)));
|
|
}
|
|
else {
|
|
RefSi = uint64_t(SignExtendLongLong(CAddr_t(RefAk)));
|
|
}
|
|
}
|
|
return 1;
|
|
case 2: // Si +FAk
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " +F" << RefAk;
|
|
aExplanation << "Assign as unnormalized float";
|
|
}
|
|
if (aDoExecute) {
|
|
int32_t Ak = SignExtend(RefAk);
|
|
CInt_t Result = 040060ULL << 48;
|
|
if (Ak < 0) Result |= CFloat_t::FractSignMask;
|
|
Result |= abs(Ak);
|
|
RefSiTarget = Result;
|
|
}
|
|
return 1;
|
|
case 3: // Si 0.6
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " 0.6";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = 0400606000000000000000ULL;
|
|
}
|
|
return 1;
|
|
case 4: // Si 0.4
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " 0.4";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = 0400004000000000000000ULL;
|
|
}
|
|
return 1;
|
|
case 5: // Si 1.0
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " 1.";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = 0400014000000000000000ULL;
|
|
}
|
|
return 1;
|
|
case 6: // Si 2.0
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " 2.";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = 0400024000000000000000ULL;
|
|
}
|
|
return 1;
|
|
case 7: // Si 4.0
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " 4.";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = 0400034000000000000000ULL;
|
|
}
|
|
return 1;
|
|
default: CRAY_UNKNOWN
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0072(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0072);
|
|
switch (k) {
|
|
case 0: // Si RT
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " RT";
|
|
aExplanation << "Read the real-time-clock";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = mMainframe.GetRealTimeClock();
|
|
aBreakBurst = true;
|
|
}
|
|
return 1;
|
|
case 2: // Si SM
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " SM";
|
|
aExplanation << "Read the semaphores";
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Cluster > 0) {
|
|
uint64_t RetVal = 0;
|
|
auto &Cluster = mMainframe.GetCluster(mState.Cluster - 1);
|
|
for (int i = 0; i < 32; ++i) {
|
|
if (Cluster.SM[i].load()) RetVal |= (1ULL << 31);
|
|
RetVal <<= 1;
|
|
}
|
|
RefSi = RetVal;
|
|
aBreakBurst = true;
|
|
}
|
|
}
|
|
return 1;
|
|
case 3: // Si STj
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSTj;
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Cluster > 0) {
|
|
RefSi = RefSTj;
|
|
aBreakBurst = true;
|
|
}
|
|
}
|
|
return 1;
|
|
default: CRAY_UNKNOWN
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0073(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0073);
|
|
switch (k) {
|
|
case 0: // Si VM
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " VM";
|
|
aExplanation << "Read the vector-mask register";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = RefVM;
|
|
}
|
|
return 1;
|
|
case 1: // multiple
|
|
switch (j) {
|
|
case 0: // Si SR0
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefSRj;
|
|
aExplanation << "See HR-0097 5-60 for bit-definitions of SR0 registers";
|
|
}
|
|
if (aDoExecute) {
|
|
if (j != 0) {
|
|
// We don't know what SRj registers are...
|
|
CRAY_UNIMPLEMENTED;
|
|
}
|
|
else {
|
|
RefSi = GetSR(0);
|
|
aBreakBurst = true;
|
|
}
|
|
}
|
|
return 1;
|
|
case 1: // Read perf counter to Si
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " PFPTR++";
|
|
aExplanation << "Read (high or low order bits of) performance counter into " << RefSiTarget << " than increment performance counter pointer";
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Mode.IsMonitorMode()) {
|
|
//CRAY_UNIMPLEMENTED;
|
|
RefSi = CInt_t(0);
|
|
}
|
|
}
|
|
return 1;
|
|
case 2: // Increment perf counter
|
|
if (!aDoExecute) {
|
|
if (IsXmp()) {
|
|
aDisassembly << "PFC++";
|
|
aExplanation << "Increment the current performance counter (low or high-part) pointed by PFPTR";
|
|
}
|
|
else {
|
|
aDisassembly << "PFC++ - low";
|
|
aExplanation << "Increment the current performance counter (low-part) pointed by PFPTR";
|
|
|
|
}
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Mode.IsMonitorMode()) {
|
|
//CRAY_UNIMPLEMENTED;
|
|
}
|
|
}
|
|
return 1;
|
|
case 3: // Clear all maintanace modes
|
|
if (!aDoExecute) {
|
|
aDisassembly << "CLM " << RefSiTarget << " -1";
|
|
aExplanation << "Clear all maintenance modes. Loads " << RefSiTarget << " with -1 as a side-effect";
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Mode.IsMonitorMode()) {
|
|
//CRAY_UNIMPLEMENTED;
|
|
}
|
|
}
|
|
return 1;
|
|
case 4: // SIM-TO-HOST COMMUNICATION CHANNEL.
|
|
if (!aDoExecute) {
|
|
aDisassembly << "HOST_WR " << RefSi << " -1";
|
|
aExplanation << "Sends " << RefSi << " to host";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSiTarget = mMainframe.SimToHost(RefSi);
|
|
}
|
|
case 5: // Gets defined in C90
|
|
CRAY_UNKNOWN;
|
|
case 6: // Increment perf counter (higher)
|
|
if (!IsXmp()) {
|
|
if (!aDoExecute) {
|
|
aDisassembly << "PFC++ - high";
|
|
aExplanation << "Increment the current performance counter (high-part) pointed by PFPTR";
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Mode.IsMonitorMode()) {
|
|
//CRAY_UNIMPLEMENTED;
|
|
}
|
|
}
|
|
}
|
|
else CRAY_UNKNOWN
|
|
return 1;
|
|
case 7: // HOST-TO-SIM COMMUNICATION CHANNEL.
|
|
if (!aDoExecute) {
|
|
aDisassembly << "HOST_WR " << RefSiTarget << " -1";
|
|
aExplanation << "Sends " << RefSiTarget << " to host";
|
|
}
|
|
if (aDoExecute) {
|
|
RefSiTarget = mMainframe.HostToSim();
|
|
}
|
|
default: CRAY_UNKNOWN
|
|
}
|
|
return 1;
|
|
case 2: // SM Si
|
|
if (!aDoExecute) {
|
|
aDisassembly << "SM " << RefSi;
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Cluster > 0) {
|
|
uint64_t NewVal = RefSi;
|
|
auto &Cluster = mMainframe.GetCluster(mState.Cluster - 1);
|
|
for (int i = 0; i < 32; ++i) {
|
|
Cluster.SM[i].store(GetBit(NewVal, 63 - i) != 0);
|
|
}
|
|
aBreakBurst = true;
|
|
}
|
|
}
|
|
return 1;
|
|
case 3: // STj Si
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSTjTarget << " " << RefSi;
|
|
}
|
|
if (aDoExecute) {
|
|
if (mState.Cluster > 0) {
|
|
RefSTj = RefSi;
|
|
aBreakBurst = true;
|
|
}
|
|
}
|
|
return 1;
|
|
case 5: // Multiple
|
|
if (i == 0 && j == 1) { // SPECIAL SIM OPERATION TO TERMINATE SIMULATOR
|
|
throw TerminateInstError_x();
|
|
}
|
|
else {
|
|
CRAY_UNKNOWN
|
|
}
|
|
default: CRAY_UNKNOWN
|
|
}
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0074(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0074);
|
|
// Si Tjk
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefTjk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = RefTjk;
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0075(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0075);
|
|
// Tjk Si
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefTjkTarget << " " << RefSi;
|
|
}
|
|
if (aDoExecute) {
|
|
RefTjk = RefSi;
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0076(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0076);
|
|
// Si Vj,Ak
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefSiTarget << " " << RefVj << "," << RefAk;
|
|
}
|
|
if (aDoExecute) {
|
|
RefSi = mState.V[j][CAddr_t(RefAk) % cVecSize];
|
|
}
|
|
return 1;
|
|
}
|
|
template <bool aDoExecute> size_t SoftCpu_c::Decode0077(uint64_t aParcels, size_t aMaxParcelCnt, std::ostream &aDisassembly, std::ostream &aExplanation, bool &aBreakBurst) {
|
|
EXTRACT_FIELDS(aParcels);
|
|
CRAY_ASSERT(gh == 0077);
|
|
// Vi,Ak Sj
|
|
|
|
if (!aDoExecute) {
|
|
aDisassembly << RefViTarget << "," << RefAk << " " << RefSj;
|
|
}
|
|
if (aDoExecute) {
|
|
mState.V[i][CAddr_t(RefAk) % cVecSize] = RefSj;
|
|
RefVi.LogState();
|
|
mState.VectorNotUsed = false;
|
|
}
|
|
return 1;
|
|
}
|