2020-05-12 18:55:45 +00:00
|
|
|
#include "../ppcdisasm.h"
|
|
|
|
#include "../ppcemu.h"
|
2020-01-31 03:10:53 +00:00
|
|
|
#include <fstream>
|
|
|
|
#include <iomanip>
|
2020-05-12 18:55:45 +00:00
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
2020-01-31 03:10:53 +00:00
|
|
|
#include <string>
|
2020-05-12 18:55:45 +00:00
|
|
|
#include <vector>
|
2020-01-31 03:10:53 +00:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
int ntested; /* number of tested instructions */
|
|
|
|
int nfailed; /* number of failed instructions */
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
void xer_ov_test(string mnem, uint32_t opcode) {
|
|
|
|
ppc_state.gpr[3] = 2;
|
|
|
|
ppc_state.gpr[4] = 2;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::XER] = 0xFFFFFFFF;
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_cur_instruction = opcode;
|
2020-02-10 18:34:03 +00:00
|
|
|
ppc_main_opcode();
|
2020-03-05 04:29:04 +00:00
|
|
|
if (ppc_state.spr[SPR::XER] & 0x40000000UL) {
|
2020-05-12 18:55:45 +00:00
|
|
|
cout << "Invalid " << mnem << " emulation! XER[OV] should not be set." << endl;
|
2020-02-10 18:34:03 +00:00
|
|
|
nfailed++;
|
|
|
|
}
|
|
|
|
ntested++;
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
void xer_update_test() {
|
|
|
|
xer_ov_test("ADDCO", 0x7C632414);
|
|
|
|
xer_ov_test("ADDCO.", 0x7C632415);
|
|
|
|
xer_ov_test("ADDO", 0x7C632614);
|
|
|
|
xer_ov_test("ADDO.", 0x7C632615);
|
|
|
|
xer_ov_test("ADDEO", 0x7C632514);
|
|
|
|
xer_ov_test("ADDEO.", 0x7C632515);
|
|
|
|
xer_ov_test("ADDMEO", 0x7C6305D4);
|
|
|
|
xer_ov_test("ADDMEO.", 0x7C6305D5);
|
|
|
|
xer_ov_test("ADDZEO", 0x7C630594);
|
|
|
|
xer_ov_test("ADDZEO.", 0x7C630595);
|
|
|
|
xer_ov_test("DIVWO", 0x7C6327D6);
|
|
|
|
xer_ov_test("DIVWO.", 0x7C6327D7);
|
|
|
|
xer_ov_test("DIVWUO", 0x7C632796);
|
|
|
|
xer_ov_test("DIVWUO.", 0x7C632797);
|
|
|
|
xer_ov_test("MULLWO", 0x7C6325D6);
|
|
|
|
xer_ov_test("MULLWO.", 0x7C6325D7);
|
|
|
|
xer_ov_test("NEGO", 0x7C6304D0);
|
|
|
|
xer_ov_test("NEGO.", 0x7C6304D1);
|
|
|
|
xer_ov_test("SUBFO", 0x7C632450);
|
|
|
|
xer_ov_test("SUBFO.", 0x7C632451);
|
|
|
|
xer_ov_test("SUBFCO", 0x7C632410);
|
|
|
|
xer_ov_test("SUBFCO.", 0x7C632411);
|
|
|
|
xer_ov_test("SUBFEO", 0x7C632510);
|
|
|
|
xer_ov_test("SUBFEO.", 0x7C632511);
|
|
|
|
xer_ov_test("SUBFMEO", 0x7C6305D0);
|
2020-02-10 18:34:03 +00:00
|
|
|
xer_ov_test("SUBFMEO.", 0x7C6305D1);
|
2020-05-12 18:55:45 +00:00
|
|
|
xer_ov_test("SUBFZEO", 0x7C630590);
|
2020-02-10 18:34:03 +00:00
|
|
|
xer_ov_test("SUBFZEO.", 0x7C630591);
|
|
|
|
}
|
|
|
|
|
2020-01-31 03:10:53 +00:00
|
|
|
/** testing vehicle */
|
2020-05-12 18:55:45 +00:00
|
|
|
static void read_test_data() {
|
|
|
|
string line, token;
|
|
|
|
int i, lineno;
|
2020-01-31 03:10:53 +00:00
|
|
|
uint32_t opcode, dest, src1, src2, check_xer, check_cr;
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ifstream tfstream("ppcinttests.csv");
|
2020-01-31 03:10:53 +00:00
|
|
|
if (!tfstream.is_open()) {
|
|
|
|
cout << "Could not open tests CSV file. Exiting..." << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lineno = 0;
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
while (getline(tfstream, line)) {
|
2020-01-31 03:10:53 +00:00
|
|
|
lineno++;
|
|
|
|
|
|
|
|
if (line.empty() || !line.rfind("#", 0))
|
|
|
|
continue; /* skip empty/comment lines */
|
|
|
|
|
|
|
|
istringstream lnstream(line);
|
|
|
|
|
|
|
|
vector<string> tokens;
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
while (getline(lnstream, token, ',')) {
|
2020-01-31 03:10:53 +00:00
|
|
|
tokens.push_back(token);
|
|
|
|
}
|
|
|
|
|
2020-01-31 17:04:50 +00:00
|
|
|
if (tokens.size() < 5) {
|
2020-01-31 03:10:53 +00:00
|
|
|
cout << "Too few values in line " << lineno << ". Skipping..." << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-01-31 20:53:02 +00:00
|
|
|
opcode = stoul(tokens[1], NULL, 16);
|
2020-01-31 03:10:53 +00:00
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
dest = 0;
|
|
|
|
src1 = 0;
|
|
|
|
src2 = 0;
|
2020-01-31 03:10:53 +00:00
|
|
|
check_xer = 0;
|
|
|
|
check_cr = 0;
|
|
|
|
|
|
|
|
for (i = 2; i < tokens.size(); i++) {
|
|
|
|
if (tokens[i].rfind("rD=", 0) == 0) {
|
2020-01-31 20:53:02 +00:00
|
|
|
dest = stoul(tokens[i].substr(3), NULL, 16);
|
2020-01-31 03:10:53 +00:00
|
|
|
} else if (tokens[i].rfind("rA=", 0) == 0) {
|
2020-01-31 20:53:02 +00:00
|
|
|
src1 = stoul(tokens[i].substr(3), NULL, 16);
|
2020-01-31 03:10:53 +00:00
|
|
|
} else if (tokens[i].rfind("rB=", 0) == 0) {
|
2020-01-31 20:53:02 +00:00
|
|
|
src2 = stoul(tokens[i].substr(3), NULL, 16);
|
2020-01-31 03:10:53 +00:00
|
|
|
} else if (tokens[i].rfind("XER=", 0) == 0) {
|
2020-01-31 20:53:02 +00:00
|
|
|
check_xer = stoul(tokens[i].substr(4), NULL, 16);
|
2020-01-31 03:10:53 +00:00
|
|
|
} else if (tokens[i].rfind("CR=", 0) == 0) {
|
2020-01-31 20:53:02 +00:00
|
|
|
check_cr = stoul(tokens[i].substr(3), NULL, 16);
|
2020-01-31 03:10:53 +00:00
|
|
|
} else {
|
2020-05-12 18:55:45 +00:00
|
|
|
cout << "Unknown parameter " << tokens[i] << " in line " << lineno << ". Exiting..."
|
|
|
|
<< endl;
|
2020-01-31 03:10:53 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_state.gpr[3] = src1;
|
|
|
|
ppc_state.gpr[4] = src2;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::XER] = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_state.cr = 0;
|
2020-01-31 03:10:53 +00:00
|
|
|
|
|
|
|
ppc_cur_instruction = opcode;
|
|
|
|
|
|
|
|
ppc_main_opcode();
|
|
|
|
|
|
|
|
ntested++;
|
|
|
|
|
2020-03-05 04:29:04 +00:00
|
|
|
if ((tokens[0].rfind("CMP") && (ppc_state.gpr[3] != dest)) ||
|
2020-05-12 18:55:45 +00:00
|
|
|
(ppc_state.spr[SPR::XER] != check_xer) || (ppc_state.cr != check_cr)) {
|
|
|
|
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1 << ", src2=0x"
|
|
|
|
<< hex << src2 << endl;
|
|
|
|
cout << "expected: dest=0x" << hex << dest << ", XER=0x" << hex << check_xer
|
|
|
|
<< ", CR=0x" << hex << check_cr << endl;
|
|
|
|
cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", XER=0x" << hex
|
|
|
|
<< ppc_state.spr[SPR::XER] << ", CR=0x" << hex << ppc_state.cr << endl;
|
2020-02-03 19:36:22 +00:00
|
|
|
cout << "Test file line #: " << dec << lineno << endl << endl;
|
2020-01-31 03:10:53 +00:00
|
|
|
|
|
|
|
nfailed++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
int main() {
|
2020-10-17 21:30:37 +00:00
|
|
|
initialize_ppc_opcode_tables(); //kludge
|
|
|
|
|
2020-01-31 03:10:53 +00:00
|
|
|
cout << "Running DingusPPC emulator tests..." << endl << endl;
|
|
|
|
|
2020-02-10 18:34:03 +00:00
|
|
|
ntested = 0;
|
2020-01-31 03:10:53 +00:00
|
|
|
nfailed = 0;
|
|
|
|
|
2020-02-10 18:34:03 +00:00
|
|
|
cout << "Testing XER[OV] updating..." << endl << endl;
|
|
|
|
|
|
|
|
xer_update_test();
|
|
|
|
|
|
|
|
cout << endl << "Testing integer instructions:" << endl;
|
|
|
|
|
2020-01-31 03:10:53 +00:00
|
|
|
read_test_data();
|
|
|
|
|
|
|
|
cout << "... completed." << endl;
|
|
|
|
cout << "--> Tested instructions: " << dec << ntested << endl;
|
2020-02-12 21:58:24 +00:00
|
|
|
cout << "--> Failed: " << dec << nfailed << endl << endl;
|
2020-01-31 03:10:53 +00:00
|
|
|
|
2020-02-12 21:58:24 +00:00
|
|
|
cout << "Running PPC disassembler tests..." << endl << endl;
|
|
|
|
|
|
|
|
return test_ppc_disasm();
|
2020-01-31 03:10:53 +00:00
|
|
|
}
|