// Condition Register XOR static bool crxor(PPCEmuAssembler& a, Instruction instr) { getTwoCRB(a, instr.crbA, a.eax, instr.crbB, a.ecx); a.xor_(a.eax, a.ecx); setCRB(a, instr.crbD, a.eax, a.ecx, a.edx); return true; }
// Condition Register XOR static void crxor(ThreadState *state, Instruction instr) { uint32_t a, b, d; a = getCRB(state, instr.crbA); b = getCRB(state, instr.crbB); d = a ^ b; setCRB(state, instr.crbD, d); }
// Condition Register NAND static void crnand(ThreadState *state, Instruction instr) { uint32_t a, b, d; a = getCRB(state, instr.crbA); b = getCRB(state, instr.crbB); d = ~(a & b); setCRB(state, instr.crbD, d); }
static void generateTests(InstructionData *data) { std::vector<size_t> indexCur, indexMax; std::vector<bool> flagSet; hwtest::TestFile testFile; auto complete = false; auto completeIndices = false; for (auto i = 0; i < data->read.size(); ++i) { auto &field = data->read[i]; indexCur.push_back(0); switch (field) { case Field::rA: case Field::rB: case Field::rS: indexMax.push_back(gValuesGPR.size()); break; case Field::frA: case Field::frB: case Field::frC: case Field::frS: indexMax.push_back(gValuesFPR.size()); break; case Field::crbA: case Field::crbB: indexMax.push_back(gValuesCRB.size()); break; case Field::simm: indexMax.push_back(gValuesSIMM.size()); break; case Field::sh: indexMax.push_back(gValuesSH.size()); break; case Field::mb: indexMax.push_back(gValuesMB.size()); break; case Field::me: indexMax.push_back(gValuesME.size()); break; case Field::uimm: indexMax.push_back(gValuesUIMM.size()); break; case Field::XERC: indexMax.push_back(gValuesXERC.size()); break; case Field::XERSO: indexMax.push_back(gValuesXERSO.size()); break; default: assert(false); } } for (auto i = 0; i < data->flags.size(); ++i) { flagSet.push_back(false); } while (!complete) { uint32_t gpr = 0, fpr = 0, crf = 0, crb = 0; hwtest::TestData test; memset(&test, 0, sizeof(hwtest::TestData)); test.instr = gInstructionTable.encode(data->id); for (auto i = 0; i < data->read.size(); ++i) { auto index = indexCur[i]; // Generate read field values switch (data->read[i]) { case Field::rA: test.instr.rA = gpr + hwtest::GPR_BASE; test.input.gpr[gpr++] = gValuesGPR[index]; break; case Field::rB: test.instr.rB = gpr + hwtest::GPR_BASE; test.input.gpr[gpr++] = gValuesGPR[index]; break; case Field::rS: test.instr.rS = gpr + hwtest::GPR_BASE; test.input.gpr[gpr++] = gValuesGPR[index]; break; case Field::frA: test.instr.frA = fpr + hwtest::FPR_BASE; test.input.fr[fpr++] = gValuesFPR[index]; break; case Field::frB: test.instr.frB = fpr + hwtest::FPR_BASE; test.input.fr[fpr++] = gValuesFPR[index]; break; case Field::frC: test.instr.frC = fpr + hwtest::FPR_BASE; test.input.fr[fpr++] = gValuesFPR[index]; break; case Field::frS: test.instr.frS = fpr + hwtest::FPR_BASE; test.input.fr[fpr++] = gValuesFPR[index]; break; case Field::crbA: test.instr.crbA = (crb++) + hwtest::CRB_BASE; setCRB(test.input, test.instr.crbA, gValuesCRB[index]); break; case Field::crbB: test.instr.crbB = (crb++) + hwtest::CRB_BASE; setCRB(test.input, test.instr.crbB, gValuesCRB[index]); break; case Field::simm: test.instr.simm = gValuesSIMM[index]; break; case Field::sh: test.instr.sh = gValuesSH[index]; break; case Field::mb: test.instr.mb = gValuesMB[index]; break; case Field::me: test.instr.me = gValuesME[index]; break; case Field::uimm: test.instr.uimm = gValuesUIMM[index]; break; case Field::XERC: test.input.xer.ca = gValuesXERC[index]; break; case Field::XERSO: test.input.xer.so = gValuesXERSO[index]; break; default: assert(false); } } // Generate write field values for (auto field : data->write) { switch (field) { case Field::rA: test.instr.rA = gpr + hwtest::GPR_BASE; gpr++; break; case Field::rD: test.instr.rD = gpr + hwtest::GPR_BASE; gpr++; break; case Field::frD: test.instr.frD = fpr + hwtest::FPR_BASE; fpr++; break; case Field::crfD: test.instr.crfD = crf + hwtest::CRF_BASE; crf++; break; case Field::crbD: test.instr.crbD = crb + hwtest::CRB_BASE; crb++; break; case Field::XERC: case Field::XERSO: case Field::FCRISI: case Field::FCRZDZ: case Field::FCRIDI: case Field::FCRSNAN: break; default: assert(false); } } testFile.tests.emplace_back(test); // Increase indices for (auto i = 0; i < indexCur.size(); ++i) { indexCur[i]++; if (indexCur[i] < indexMax[i]) { break; } else if (indexCur[i] == indexMax[i]) { indexCur[i] = 0; if (i == indexCur.size() - 1) { completeIndices = true; } } } if (completeIndices) { if (flagSet.size() == 0) { complete = true; break; } completeIndices = false; // Do next flag! for (auto i = 0; i < flagSet.size(); ++i) { if (!flagSet[i]) { flagSet[i] = true; break; } else { flagSet[i] = false; if (i == flagSet.size() - 1) { complete = true; break; } } } } } // Save tests to file auto filename = std::string("tests/cpu/input/") + data->name; std::ofstream out { filename, std::ofstream::out | std::ofstream::binary }; cereal::BinaryOutputArchive archive(out); archive(testFile); }