diff --git a/cpu/ppc/test/genppctests.py b/cpu/ppc/test/genppctests.py index 55d2955..502697d 100644 --- a/cpu/ppc/test/genppctests.py +++ b/cpu/ppc/test/genppctests.py @@ -99,6 +99,90 @@ def gen_ppc_opcode(opc_str, imm): return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x39A << 1) elif opc_str == "EXTSH.": return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x39A << 1) + 1 + elif opc_str == "FABS": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x108 << 1) + elif opc_str == "FABS.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x108 << 1) + 1 + elif opc_str == "FADD": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + elif opc_str == "FADD.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + 1 + elif opc_str == "FADDS": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + elif opc_str == "FADDS.": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + 1 + elif opc_str == "FCMPO": + return (0x3B << 26) + (3 << 16) + (4 << 11) + (0x20 << 1) + elif opc_str == "FCMPU": + return (0x3B << 26) + (3 << 16) + (4 << 11) + elif opc_str == "FCTIW": + return (0x3B << 26) + (3 << 16) + (4 << 11) + (0xE << 1) + elif opc_str == "FCTIW.": + return (0x3B << 26) + (3 << 16) + (4 << 11) + (0xE << 1) + 1 + elif opc_str == "FCTIWZ": + return (0x3B << 26) + (3 << 16) + (4 << 11) + (0xF << 1) + elif opc_str == "FCTIWZ.": + return (0x3B << 26) + (3 << 16) + (4 << 11) + (0xF << 1) + 1 + elif opc_str == "FDIV": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1) + elif opc_str == "FDIV.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x12 << 1) + 1 + elif opc_str == "FMADD": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1) + elif opc_str == "FMADD.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1) + 1 + elif opc_str == "FMADDS": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1) + elif opc_str == "FMADDS.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1D << 1) + 1 + elif opc_str == "FMUL": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1) + elif opc_str == "FMUL.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1) + 1 + elif opc_str == "FMULS": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1) + elif opc_str == "FMULS.": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x19 << 1) + 1 + elif opc_str == "FNABS": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x88 << 1) + elif opc_str == "FNABS.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x88 << 1) + 1 + elif opc_str == "FNEG": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x28 << 1) + elif opc_str == "FMULS.": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 6) + (0x28 << 1) + 1 + elif opc_str == "FMSUB": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + elif opc_str == "FMSUB.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1 + elif opc_str == "FMSUBS": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + elif opc_str == "FMSUBS.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1 + elif opc_str == "FNMADD": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1) + elif opc_str == "FNMADD.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1) + 1 + elif opc_str == "FNMADDS": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1) + elif opc_str == "FNMADDS.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1F << 1) + 1 + elif opc_str == "FNMSUB": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + elif opc_str == "FNMSUB.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1 + elif opc_str == "FNMSUBS": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + elif opc_str == "FNMSUBS.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (4 << 6) + (0x1C << 1) + 1 + elif opc_str == "FSUB": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + elif opc_str == "FSUB.": + return (0x3F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + 1 + elif opc_str == "FSUBS": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + elif opc_str == "FSUBS.": + return (0x3B << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x15 << 1) + 1 elif opc_str == "MULHW": return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x4B << 1) elif opc_str == "MULHW.": @@ -263,50 +347,98 @@ def extract_rot_params(line): return (sh, mb, me) -with open("ppcinttest.txt", "r") as in_file: - with open("ppcinttests.csv", "w") as out_file: - lineno = 0 - for line in in_file: - lineno += 1 +if __name__ == "__main__": + with open("ppcinttest.txt", "r") as in_file: + with open("ppcinttests.csv", "w") as out_file: + lineno = 0 + for line in in_file: + lineno += 1 - line = line.strip() - opcode = (line[0:8]).rstrip().upper() - out_file.write(opcode + ",") + line = line.strip() + opcode = (line[0:8]).rstrip().upper() + out_file.write(opcode + ",") - if opcode.startswith("RLWI"): - sh, mb, me = extract_rot_params(line) - out_file.write("0x{:X}".format(gen_rot_opcode(opcode, sh, mb, me))) - else: - imm = extract_imm(line) - out_file.write("0x{:X}".format(gen_ppc_opcode(opcode, imm))) - - pos = 12 - - while pos < len(line): - reg_id = line[pos:pos+4] - if reg_id.startswith("rD"): - out_file.write(",rD=" + line[pos+3:pos+13]) - pos += 16 - elif reg_id.startswith("rA"): - out_file.write(",rA=" + line[pos+3:pos+13]) - pos += 16 - elif reg_id.startswith("rB") or reg_id.startswith("rS"): - out_file.write(",rB=" + line[pos+3:pos+13]) - pos += 16 - elif reg_id.startswith("XER:"): - out_file.write(",XER=" + line[pos+5:pos+15]) - pos += 18 - elif reg_id.startswith("CR:"): - out_file.write(",CR=" + line[pos+4:pos+14]) - pos += 17 - elif reg_id.startswith("imm"): - pos += 17 # ignore immediate operands - elif reg_id.startswith("SH"): - pos += 16 - elif reg_id.startswith("MB") or reg_id.startswith("ME"): - pos += 16 + if opcode.startswith("RLWI"): + sh, mb, me = extract_rot_params(line) + out_file.write("0x{:X}".format(gen_rot_opcode(opcode, sh, mb, me))) else: - out_file.write("Unknown reg ID" + reg_id) - break + imm = extract_imm(line) + out_file.write("0x{:X}".format(gen_ppc_opcode(opcode, imm))) - out_file.write("\n") + pos = 12 + + while pos < len(line): + reg_id = line[pos:pos+4] + if reg_id.startswith("rD"): + out_file.write(",rD=" + line[pos+3:pos+13]) + pos += 16 + elif reg_id.startswith("rA"): + out_file.write(",rA=" + line[pos+3:pos+13]) + pos += 16 + elif reg_id.startswith("rB") or reg_id.startswith("rS"): + out_file.write(",rB=" + line[pos+3:pos+13]) + pos += 16 + elif reg_id.startswith("XER:"): + out_file.write(",XER=" + line[pos+5:pos+15]) + pos += 18 + elif reg_id.startswith("CR:"): + out_file.write(",CR=" + line[pos+4:pos+14]) + pos += 17 + elif reg_id.startswith("imm"): + pos += 17 # ignore immediate operands + elif reg_id.startswith("SH"): + pos += 16 + elif reg_id.startswith("MB") or reg_id.startswith("ME"): + pos += 16 + else: + out_file.write("Unknown reg ID" + reg_id) + break + + out_file.write("\n") + + with open("ppcfloattest.txt", "r") as in_file: + with open("ppcfloattests.csv", "w") as out_file: + lineno = 0 + for line in in_file: + lineno += 1 + + line = line.strip() + opcode = (line[0:8]).rstrip().upper() + out_file.write(opcode + ",") + + if opcode.startswith("RLWI"): + sh, mb, me = extract_rot_params(line) + out_file.write("0x{:X}".format(gen_rot_opcode(opcode, sh, mb, me))) + else: + imm = extract_imm(line) + out_file.write("0x{:X}".format(gen_ppc_opcode(opcode, imm))) + + pos = 12 + + while pos < len(line): + reg_id = line[pos:pos+4] + if reg_id.startswith("frD"): + out_file.write(",frD=" + line[pos+4:pos+14]) + pos += 16 + elif reg_id.startswith("frA"): + out_file.write(",frA=" + line[pos+4:pos+14]) + pos += 16 + elif reg_id.startswith("frB"): + out_file.write(",frB=" + line[pos+4:pos+14]) + pos += 16 + elif reg_id.startswith("frC"): + out_file.write(",frC=" + line[pos+4:pos+14]) + pos += 16 + elif reg_id.startswith("FPSCR:"): + out_file.write(",FPSCR=" + line[pos+7:pos+17]) + pos += 19 + elif reg_id.startswith("CR:"): + out_file.write(",CR=" + line[pos+4:pos+14]) + pos += 17 + elif reg_id.startswith("imm"): + pos += 17 # ignore immediate operands + else: + out_file.write("Unknown reg ID" + reg_id) + break + + out_file.write("\n") \ No newline at end of file diff --git a/cpu/ppc/test/ppcfloattest.txt b/cpu/ppc/test/ppcfloattest.txt new file mode 100644 index 0000000..05fad1b --- /dev/null +++ b/cpu/ppc/test/ppcfloattest.txt @@ -0,0 +1,4 @@ +FADD (RTN) :: frD 0x0000000000000000 | frA 0.000000e+00 | frB 0.000000e+00 | FPSCR: 0x00002000 | CR: 0x20000000 +FADD (RTZ) :: frD 0x0000000000000000 | frA 0.000000e+00 | frB 0.000000e+00 | FPSCR: 0x00002001 | CR: 0x40000002 +FADD (RTPI) :: frD 0x0000000000000000 | frA 0.000000e+00 | frB 0.000000e+00 | FPSCR: 0x00002002 | CR: 0x40000002 +FADD (RTNI) :: frD 0x0000000000000000 | frA 0.000000e+00 | frB 0.000000e+00 | FPSCR: 0x00002003 | CR: 0x40000002 diff --git a/cpu/ppc/test/ppcfloattests.csv b/cpu/ppc/test/ppcfloattests.csv new file mode 100644 index 0000000..09a3aba --- /dev/null +++ b/cpu/ppc/test/ppcfloattests.csv @@ -0,0 +1 @@ +FADD,0xFC64282A,round=RTN,frD=0x0000000000000000,frA=0.000000e+00,frB=0.000000e+00,FPSCR=0x00002000,CR=0x20000000 \ No newline at end of file diff --git a/cpu/ppc/test/ppctests.cpp b/cpu/ppc/test/ppctests.cpp index 0f3b512..2e4eda3 100644 --- a/cpu/ppc/test/ppctests.cpp +++ b/cpu/ppc/test/ppctests.cpp @@ -117,6 +117,7 @@ static void read_test_data() { ppc_state.gpr[3] = src1; ppc_state.gpr[4] = src2; + ppc_state.spr[SPR::XER] = 0; ppc_state.cr = 0; @@ -141,6 +142,127 @@ static void read_test_data() { } } +static void read_test_float_data() { + string line, token; + int i, lineno; + + uint32_t opcode, dest, src1, src2, check_xer, check_cr, check_fpscr; + uint64_t dest_64, src1_64, src2_64; + float sfp_dest, sfp_src1, sfp_src2, sfp_src3; + double dfp_dest, dfp_src1, dfp_src2, dfp_src3; + string rounding_mode; + + ifstream tf2stream("ppcfloattests.csv"); + if (!tf2stream.is_open()) { + cout << "Could not open tests CSV file. Exiting..." << endl; + return; + } + + lineno = 0; + + while (getline(tf2stream, line)) { + lineno++; + + if (line.empty() || !line.rfind("#", 0)) + continue; /* skip empty/comment lines */ + + istringstream lnstream(line); + + vector tokens; + + while (getline(lnstream, token, ',')) { + tokens.push_back(token); + } + + if (tokens.size() < 5) { + cout << "Too few values in line " << lineno << ". Skipping..." << endl; + continue; + } + + opcode = stoul(tokens[1], NULL, 16); + + dest = 0; + src1 = 0; + src2 = 0; + check_xer = 0; + check_cr = 0; + check_fpscr = 0; + sfp_dest = 0.0; + sfp_src1 = 0.0; + sfp_src2 = 0.0; + sfp_src3 = 0.0; + dfp_dest = 0.0; + dfp_src1 = 0.0; + dfp_src2 = 0.0; + dfp_src3 = 0.0; + + for (i = 2; i < tokens.size(); i++) { + if (tokens[i].rfind("frD=", 0) == 0) { + dfp_dest = stoul(tokens[i].substr(4), NULL, 16); + } else if (tokens[i].rfind("frA=", 0) == 0) { + dfp_src1 = stoul(tokens[i].substr(4), NULL, 16); + } else if (tokens[i].rfind("frB=", 0) == 0) { + dfp_src2 = stoul(tokens[i].substr(4), NULL, 16); + } else if (tokens[i].rfind("frC=", 0) == 0) { + dfp_src3 = stoul(tokens[i].substr(4), NULL, 16); + } else if (tokens[i].rfind("round=", 0) == 0) { + rounding_mode = tokens[i].substr(6, 3); + ppc_state.fpscr &= 0xFFFFFFFC; + if (rounding_mode.compare("RTN") == 0) { + ppc_state.fpscr |= 0x0; + } else if (rounding_mode.compare("RTZ") == 0) { + ppc_state.fpscr |= 0x1; + } else if (rounding_mode.compare("RPI") == 0) { + ppc_state.fpscr |= 0x2; + } else if (rounding_mode.compare("RNI") == 0) { + ppc_state.fpscr |= 0x3; + } else { + cout << "ILLEGAL ROUNDING METHOD: " << tokens[i] << " in line " << lineno + << ". Exiting..." << endl; + exit(0); + } + } else if (tokens[i].rfind("FPSCR=", 0) == 0) { + check_cr = stoul(tokens[i].substr(6), NULL, 16); + } else if (tokens[i].rfind("CR=", 0) == 0) { + check_cr = stoul(tokens[i].substr(3), NULL, 16); + } else { + cout << "Unknown parameter " << tokens[i] << " in line " << lineno << ". Exiting..." + << endl; + exit(0); + } + } + + ppc_state.gpr[3] = src1; + ppc_state.gpr[4] = src2; + + ppc_state.fpr[3].dbl64_r = dfp_src1; + ppc_state.fpr[4].dbl64_r = dfp_src2; + ppc_state.fpr[5].dbl64_r = dfp_src3; + + ppc_state.spr[SPR::XER] = 0; + ppc_state.cr = 0; + + ppc_cur_instruction = opcode; + + ppc_main_opcode(); + + ntested++; + + if ((tokens[0].rfind("FCMP") && (ppc_state.gpr[3] != dest)) || (ppc_state.fpscr != check_fpscr) || + (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 << ", FPSCR=0x" << hex << check_xer << ", CR=0x" + << hex << check_cr << endl; + cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", FPSCR=0x" << hex + << ppc_state.fpscr << ", CR=0x" << hex << ppc_state.cr << endl; + cout << "Test file line #: " << dec << lineno << endl << endl; + + nfailed++; + } + } +} + int main() { initialize_ppc_opcode_tables(); //kludge @@ -157,6 +279,10 @@ int main() { read_test_data(); + cout << endl << "Testing floating point instructions:" << endl; + + read_test_float_data(); + cout << "... completed." << endl; cout << "--> Tested instructions: " << dec << ntested << endl; cout << "--> Failed: " << dec << nfailed << endl << endl;