Integrate disassembler tests.

This commit is contained in:
Maxim Poliakovski 2020-02-12 22:58:24 +01:00
parent 513658b45f
commit 24652de392
5 changed files with 338 additions and 3 deletions

View File

@ -26,6 +26,7 @@ add_custom_command(
TARGET testppc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcinttests.csv"
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcdisasmtest.csv"
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
install (TARGETS dingusppc DESTINATION ${EXECUTABLE_OUTPUT_PATH})

View File

@ -13,6 +13,8 @@ typedef struct PPCDisasmContext {
std::string disassemble_single(PPCDisasmContext *ctx);
int test_ppc_disasm(void);
/** sign-extend an integer. */
#define SIGNEXT(x, sb) ((x) | (((x) & (1 << (sb))) ? ~((1 << (sb))-1) : 0))

View File

@ -0,0 +1,223 @@
# Test data for PowerPC disassembler supplied as comma-separated values
# Data format:
# instruction address (hex), instruction code (hex), expected disassembly: opcode, [operands...]
# (lines starting with "#" will be treated as comments and ignored)
# unconditional branches
0xFFF03008,0x48000355,bl,0xFFF0335C
0xFFF03000,0x4280035C,b,0xFFF0335C
# conditional branches with simplified mnemonics, primary opcode 0x10
0xFFF0011C,0x409E2EE4,bne,cr7,0xFFF03000
0xFFF00100,0x40A60098,bne+,cr1,0xFFF00198
0xFFF00100,0x41820018,beq,0xFFF00118
0xFFF03004,0x41200054,bdnzt+,lt,0xFFF03058
0xFFF03004,0x40000054,bdnzf,lt,0xFFF03058
0xFFF03000,0x4106FFF4,bdnzt,4*cr1+eq,0xFFF02FF4
# indexed load/store instructions, primary opcode 0x1F
0xFFF00100,0x7D49F02E,lwzx,r10,r9,r30
0xFFF00100,0x7FAB806E,lwzux,r29,r11,r16
0xFFF00100,0x7C0820AE,lbzx,r0,r8,r4
0xFFF00100,0x7F47E8EE,lbzux,r26,r7,r29
0xFFF00100,0x7C01612E,stwx,r0,r1,r12
0xFFF00100,0x7FC3996E,stwux,r30,r3,r19
0xFFF00100,0x7D2C09AE,stbx,r9,r12,r1
0xFFF00100,0x7C8531EE,stbux,r4,r5,r6
0xFFF00100,0x7C94DA2E,lhzx,r4,r20,r27
0xFFF00100,0x7C833A6E,lhzux,r4,r3,r7
0xFFF00100,0x7D8F62AE,lhax,r12,r15,r12
0xFFF00100,0x7C98DAEE,lhaux,r4,r24,r27
0xFFF00100,0x7C0C0B2E,sthx,r0,r12,r1
0xFFF00100,0x7C032B6E,sthux,r0,r3,r5
0xFFF00100,0x7C43242E,lfsx,fp2,r3,r4
0xFFF00100,0x7C43246E,lfsux,fp2,r3,r4
0xFFF00100,0x7D491CAE,lfdx,fp10,r9,r3
0xFFF00100,0x7C4324EE,lfdux,fp2,r3,r4
0xFFF00100,0x7C43252E,stfsx,fp2,r3,r4
0xFFF00100,0x7C43256E,stfsux,fp2,r3,r4
0xFFF00100,0x7C4325AE,stfdx,fp2,r3,r4
0xFFF00100,0x7C4325EE,stfdux,fp2,r3,r4
# arithmetic instructions with immediate operand
0xFFF00100,0x1F00A81A,mulli,r24,r0,-0x57E6
0xFFF00100,0x1D8A4CCC,mulli,r12,r10,0x4CCC
0xFFF00100,0x207CFEE0,subfic,r3,r28,-0x120
0xFFF00100,0x20894E75,subfic,r4,r9,0x4E75
0xFFF00100,0x38BE0000,addi,r5,r30,0x0
0xFFF00100,0x3A2EFFF0,addi,r17,r14,-0x10
0xFFF00100,0x307F005E,addic,r3,r31,0x5E
0xFFF00100,0x30C4FFFF,addic,r6,r4,-0x1
0xFFF00100,0x34803012,addic.,r4,r0,0x3012
0xFFF00100,0x3E1F4A47,addis,r16,r31,0x4A47
0xFFF00100,0x3F3CFFF6,addis,r25,r28,-0xA
# subtracts and friends, primary opcode 0x1F
0xFFF00100,0x7C03E810,subfc,r0,r3,r29
0xFFF00100,0x7CE03011,subfc.,r7,r0,r6
0xFFF00100,0x7CC47C10,subfco,r6,r4,r15
0xFFF00100,0x7CC46C11,subfco.,r6,r4,r13
0xFFF00100,0x7D800850,subf,r12,r0,r1
0xFFF00100,0x7C966851,subf.,r4,r22,r13
0xFFF00100,0x7C7B8C50,subfo,r3,r27,r17
0xFFF00100,0x7D283C51,subfo.,r9,r8,r7
0xFFF00100,0x7CE400D0,neg,r7,r4
0xFFF00100,0x7CC900D1,neg.,r6,r9
0xFFF00100,0x7C6B04D0,nego,r3,r11
0xFFF00100,0x7FC004D1,nego.,r30,r0
0xFFF00100,0x7D266110,subfe,r9,r6,r12
0xFFF00100,0x7C693111,subfe.,r3,r9,r6
0xFFF00100,0x7C642D10,subfeo,r3,r4,r5
0xFFF00100,0x7C843511,subfeo.,r4,r4,r6
0xFFF00100,0x7D6B0190,subfze,r11,r11
0xFFF00100,0x7C430191,subfze.,r2,r3
0xFFF00100,0x7C640590,subfzeo,r3,r4
0xFFF00100,0x7C850591,subfzeo.,r4,r5
0xFFF00100,0x7C4301D0,subfme,r2,r3
0xFFF00100,0x7C4301D1,subfme.,r2,r3
0xFFF00100,0x7D2A1A10,doz,r9,r10,r3
0xFFF00100,0x7C642A11,doz.,r3,r4,r5
0xFFF00100,0x7C851E10,dozo,r4,r5,r3
0xFFF00100,0x7CA41E11,dozo.,r5,r4,r3
0xFFF00100,0x7C1E02D0,abs,r0,r30
0xFFF00100,0x7C3E02D1,abs.,r1,r30
0xFFF00100,0x7FC306D0,abso,r30,r3
0xFFF00100,0x7FC706D1,abso.,r30,r7
0xFFF00100,0x7CE703D0,nabs,r7,r7
0xFFF00100,0x7D0703D1,nabs.,r8,r7
0xFFF00100,0x7D0907D0,nabso,r8,r9
0xFFF00100,0x7D0A07D1,nabso.,r8,r10
# additions, primary opcode 0x1F
0xFFF00100,0x7C830014,addc,r4,r3,r0
0xFFF00100,0x7FB8F015,addc.,r29,r24,r30
0xFFF00100,0x7CDB0414,addco,r6,r27,r0
0xFFF00100,0x7C880415,addco.,r4,r8,r0
0xFFF00100,0x7D6BC914,adde,r11,r11,r25
0xFFF00100,0x7D296115,adde.,r9,r9,r12
0xFFF00100,0x7C842514,addeo,r4,r4,r4
0xFFF00100,0x7C843515,addeo.,r4,r4,r6
0xFFF00100,0x7CE80194,addze,r7,r8
0xFFF00100,0x7C800195,addze.,r4,r0
# FIXME addzeo
# FIXME addzeo.
# FIXME addme
# FIXME addme.
# FIXME addmeo
# FIXME addmeo.
0xFFF00100,0x7F03EA14,add,r24,r3,r29
0xFFF00100,0x7ED6E215,add.,r22,r22,r28
0xFFF00100,0x7D040614,addo,r8,r4,r0
0xFFF00100,0x7DE40615,addo.,r15,r4,r0
# integer multiplications & divisions, primary opcode 0x1F
0xFFF00100,0x7C8C5016,mulhwu,r4,r12,r10
0xFFF00100,0x7CA72017,mulhwu.,r5,r7,r4
0xFFF00100,0x7CA72096,mulhw,r5,r7,r4
0xFFF00100,0x7CA72097,mulhw.,r5,r7,r4
0xFFF00100,0x7C9000D6,mul,r4,r16,r0
0xFFF00100,0x7CA428D7,mul.,r5,r4,r5
# FIXME mulo
# FIXME mulo.
0xFFF00100,0x7D0039D6,mullw,r8,r0,r7
0xFFF00100,0x7C1DF1D7,mullw.,r0,r29,r30
0xFFF00100,0x7CE725D6,mullwo,r7,r7,r4
0xFFF00100,0x7CE725D7,mullwo.,r7,r7,r4
0xFFF00100,0x7FEB2296,div,r31,r11,r4
0xFFF00100,0x7C064297,div.,r0,r6,r8
# FIXME divo
# FIXME divo.
0xFFF00100,0x7CA03AD6,divs,r5,r0,r7
0xFFF00100,0x7C642AD7,divs.,r3,r4,r5
# FIXME divso
# FIXME divso.
0xFFF00100,0x7F7C1B96,divwu,r27,r28,r3
0xFFF00100,0x7C7B1B97,divwu.,r3,r27,r3
0xFFF00100,0x7CE62796,divwuo,r7,r6,r4
0xFFF00100,0x7CE62797,divwuo.,r7,r6,r4
0xFFF00100,0x7C042BD6,divw,r0,r4,r5
0xFFF00100,0x7C042BD7,divw.,r0,r4,r5
0xFFF00100,0x7CA627D6,divwo,r5,r6,r4
0xFFF00100,0x7CA627D7,divwo.,r5,r6,r4
# move to condition register, primary opcode 0x1F
0xFFF00100,0x7D818120,mtcrf,0x18,r12
0xFFF00100,0x7D838120,mtcrf,0x38,r12
0xFFF00100,0x7D080120,mtcrf,0x80,r8
0xFFF00100,0x7E007120,mtcrf,0x07,r16
# logical instructions, primary opcode 0x1F
0xFFF00100,0x7FC32838,and,r3,r30,r5
0xFFF00100,0x7C672039,and.,r7,r3,r4
0xFFF00100,0x7D281878,andc,r8,r9,r3
0xFFF00100,0x7DCE0079,andc.,r14,r14,r0
0xFFF00100,0x7C8328F8,nor,r3,r4,r5
0xFFF00100,0x7D4948F9,nor.,r9,r10,r9
0xFFF00100,0x7ED53A38,eqv,r21,r22,r7
0xFFF00100,0x7C622239,eqv.,r2,r3,r4
0xFFF00100,0x7D645278,xor,r4,r11,r10
0xFFF00100,0x7C600279,xor.,r0,r3,r0
0xFFF00100,0x7C841B38,orc,r4,r4,r3
0xFFF00100,0x7C841B39,orc.,r4,r4,r3
0xFFF00100,0x7DE42378,or,r4,r15,r4
0xFFF00100,0x7C632379,or.,r3,r3,r4
0xFFF00100,0x7C6023B8,nand,r0,r3,r4
0xFFF00100,0x7F8B63B9,nand.,r11,r28,r12
# trap instructions
0xFFF00100,0x7F800008,tw,28,r0,r0
# integer load and stores
0xFFF00100,0x80BF0808,lwz,r5,0x808(r31)
0xFFF00100,0x80A2FFB8,lwz,r5,-0x48(r2)
0xFFF00100,0x80002F3C,lwz,r0,0x2F3C
0xFFF00100,0x8506003C,lwzu,r8,0x3C(r6)
0xFFF00100,0x8403FFF8,lwzu,r0,-0x8(r3)
0xFFF00100,0x88FD00FA,lbz,r7,0xFA(r29)
0xFFF00100,0x889EFFF4,lbz,r4,-0xC(r30)
0xFFF00100,0x8D480001,lbzu,r10,0x1(r8)
0xFFF00100,0x8FC3FFFF,lbzu,r30,-0x1(r3)
0xFFF00100,0x90600AFC,stw,r3,0xAFC
0xFFF00100,0x9000F620,stw,r0,-0x9E0
0xFFF00100,0x9146696E,stw,r10,0x696E(r6)
0xFFF00100,0x9317FFF0,stw,r24,-0x10(r23)
0xFFF00100,0x94050020,stwu,r0,0x20(r5)
0xFFF00100,0x9421FFA0,stwu,r1,-0x60(r1)
0xFFF00100,0x981F00FA,stb,r0,0xFA(r31)
0xFFF00100,0x98829882,stb,r4,-0x677E(r2)
0xFFF00100,0x9EFC000A,stbu,r23,0xA(r28)
0xFFF00100,0x9FAEFFFC,stbu,r29,-0x4(r14)
0xFFF00100,0xA22E6010,lhz,r17,0x6010(r14)
0xFFF00100,0xA0C6FFF8,lhz,r6,-0x8(r6)
0xFFF00100,0xA43C6010,lhzu,r1,0x6010(r28)
0xFFF00100,0xA7BFFFFE,lhzu,r29,-0x2(r31)
0xFFF00100,0xA820265F,lha,r1,0x265F
0xFFF00100,0xA8B5201F,lha,r5,0x201F(r21)
0xFFF00100,0xAAFEFE82,lha,r23,-0x17E(r30)
0xFFF00100,0xAC08003C,lhau,r0,0x3C(r8)
0xFFF00100,0xAC90FFFE,lhau,r4,-0x2(r16)
0xFFF00100,0xB3E40012,sth,r31,0x12(r4)
0xFFF00100,0xB02EFFFB,sth,r1,-0x5(r14)
0xFFF00100,0xB4B81EF4,sthu,r5,0x1EF4(r24)
0xFFF00100,0xB774FFFE,sthu,r27,-0x2(r20)
0xFFF00100,0xBB61006C,lmw,r27,0x6C(r1)
0xFFF00100,0xBB41FFE8,lmw,r26,-0x18(r1)
0xFFF00100,0xBC410008,stmw,r2,0x8(r1)
0xFFF00100,0xBFC1FFF8,stmw,r30,-0x8(r1)
# various simplified (extended) mnemonics
0xFFF00100,0x60000000,nop
0xFFF00100,0x7C7C1B78,mr,r28,r3
0xFFF00100,0x7C7C1B78,mr,r28,r3
0xFFF00100,0x7DAA6B79,mr.,r10,r13
0xFFF00100,0x38000000,li,r0,0x0
0xFFF00100,0x3860FFCE,li,r3,-0x32
# invalid opcodes/instruction forms
0xFFF00100,0x7D49F02F,dc.l,0x7D49F02F
0xFFF00100,0x7F800009,dc.l,0x7F800009
0xFFF00100,0x7C6B0CD0,dc.l,0x7C6B0CD0
0xFFF00100,0x7C642D90,dc.l,0x7C642D90
# POWER/PPC601 specific instructions
#0xFFF00100,0x7E3EE43A,maskir,r30,r17,r28
Can't render this file because it contains an unexpected character in line 4 and column 24.

View File

@ -5,6 +5,7 @@
#include <vector>
#include <string>
#include "../ppcemu.h"
#include "../ppcdisasm.h"
using namespace std;
@ -59,7 +60,7 @@ void xer_update_test()
}
/** testing vehicle */
void read_test_data()
static void read_test_data()
{
string line, token;
int i, lineno;
@ -165,7 +166,9 @@ int main()
cout << "... completed." << endl;
cout << "--> Tested instructions: " << dec << ntested << endl;
cout << "--> Failed: " << dec << nfailed << endl;
cout << "--> Failed: " << dec << nfailed << endl << endl;
return 0;
cout << "Running PPC disassembler tests..." << endl << endl;
return test_ppc_disasm();
}

106
cpu/ppc/test/testdisasm.cpp Normal file
View File

@ -0,0 +1,106 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <string>
#include "../ppcdisasm.h"
using namespace std;
/** testing vehicle */
static vector<PPCDisasmContext> read_test_data()
{
string line, token;
int i, lineno;
PPCDisasmContext ctx;
vector<PPCDisasmContext> tstvec;
ifstream tfstream("ppcdisasmtest.csv");
if (!tfstream.is_open()) {
cout << "Could not open tests CSV file. Exiting..." << endl;
return tstvec;
}
lineno = 0;
while(getline(tfstream, line)) {
lineno++;
if (line.empty() || !line.rfind("#", 0))
continue; // skip empty/comment lines
istringstream lnstream(line);
vector<string> tokens;
while(getline(lnstream, token, ',' )) {
//cout << "Token: " << token << endl;
tokens.push_back(token);
}
if (tokens.size() < 3) {
cout << "Too few values in line " << lineno << ". Skipping..." << endl;
continue;
}
ctx = {0};
ctx.instr_addr = stoul(tokens[0], NULL, 16);
ctx.instr_code = stoul(tokens[1], NULL, 16);
/* build disassembly string out of comma-separated parts */
ostringstream idisasm;
/* put instruction mnemonic padded with trailing spaces */
idisasm << tokens[2];
if (tokens.size() > 3) // don't pad operand-less instructions
idisasm << setw(8 - tokens[2].length()) << "";
/* now add comma-separated operands */
for (i = 3; i < tokens.size(); i++) {
if (i > 3)
idisasm << ", ";
idisasm << tokens[i];
}
ctx.instr_str = idisasm.str();
//cout << idisasm.str() << endl;
tstvec.push_back(ctx);
}
return tstvec;
}
int test_ppc_disasm()
{
int i, nfailed;
PPCDisasmContext ctx;
vector<PPCDisasmContext> testdata = read_test_data();
cout << "Imported " << testdata.size() << " test instructions." << endl;
nfailed = 0;
for (i = 0; i < testdata.size(); i++) {
ctx = {0};
ctx.instr_addr = testdata[i].instr_addr;
ctx.instr_code = testdata[i].instr_code;
ctx.simplified = true;
std::string disas = disassemble_single(&ctx);
if (disas != testdata[i].instr_str) {
cout << "Mismatch found, expected={" << testdata[i].instr_str <<
"}, got={" << disas << "}" << endl;
nfailed++;
}
}
cout << "Tested " << testdata.size() << " instructions. Failed: " <<
nfailed << "." << endl;
return 0;
}