Integrate disassembler tests.
This commit is contained in:
parent
513658b45f
commit
24652de392
|
@ -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})
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue