1 #include <cinttypes>
2 #include <cstdio>
3 #include <iomanip>
4 #include <memory>
5 #include <teakra/disassembler.h>
6 #include "../core_timing.h"
7 #include "../interpreter.h"
8 #include "../memory_interface.h"
9 #include "../shared_memory.h"
10 #include "../test.h"
11
Flag16ToString(u16 value,const char * symbols)12 std::string Flag16ToString(u16 value, const char* symbols) {
13 std::string result = symbols;
14 for (int i = 0; i < 16; ++i) {
15 if ((value >> i & 1) == 0)
16 result[15 - i] = '-';
17 }
18 return result;
19 }
20
main(int argc,char ** argv)21 int main(int argc, char** argv) {
22 if (argc < 2) {
23 std::fprintf(stderr, "A filename argument must be provided. Exiting...\n");
24 return -1;
25 }
26
27 std::unique_ptr<std::FILE, decltype(&std::fclose)> file{std::fopen(argv[1], "rb"), std::fclose};
28 if (!file) {
29 std::fprintf(stderr, "Unable to open file %s. Exiting...\n", argv[1]);
30 return -2;
31 }
32
33 Teakra::CoreTiming core_timing;
34 Teakra::SharedMemory shared_memory;
35 Teakra::MemoryInterfaceUnit miu;
36 Teakra::MemoryInterface memory_interface{shared_memory, miu};
37 Teakra::RegisterState regs;
38 Teakra::Interpreter interpreter(core_timing, regs, memory_interface);
39
40 int i = 0;
41 int passed = 0;
42 int total = 0;
43 int skipped = 0;
44 while (true) {
45 TestCase test_case;
46 if (std::fread(&test_case, sizeof(test_case), 1, file.get()) == 0) {
47 break;
48 }
49 regs.Reset();
50 regs.a = test_case.before.a;
51 regs.b = test_case.before.b;
52 regs.p = test_case.before.p;
53 regs.r = test_case.before.r;
54 regs.x = test_case.before.x;
55 regs.y = test_case.before.y;
56 regs.stepi0 = test_case.before.stepi0;
57 regs.stepj0 = test_case.before.stepj0;
58 regs.mixp = test_case.before.mixp;
59 regs.sv = test_case.before.sv;
60 regs.repc = test_case.before.repc;
61 regs.Lc() = test_case.before.lc;
62 regs.Set<Teakra::cfgi>(test_case.before.cfgi);
63 regs.Set<Teakra::cfgj>(test_case.before.cfgj);
64 regs.Set<Teakra::stt0>(test_case.before.stt0);
65 regs.Set<Teakra::stt1>(test_case.before.stt1);
66 regs.Set<Teakra::stt2>(test_case.before.stt2);
67 regs.Set<Teakra::mod0>(test_case.before.mod0);
68 regs.Set<Teakra::mod1>(test_case.before.mod1);
69 regs.Set<Teakra::mod2>(test_case.before.mod2);
70 regs.Set<Teakra::ar0>(test_case.before.ar[0]);
71 regs.Set<Teakra::ar1>(test_case.before.ar[1]);
72 regs.Set<Teakra::arp0>(test_case.before.arp[0]);
73 regs.Set<Teakra::arp1>(test_case.before.arp[1]);
74 regs.Set<Teakra::arp2>(test_case.before.arp[2]);
75 regs.Set<Teakra::arp3>(test_case.before.arp[3]);
76
77 for (u16 offset = 0; offset < TestSpaceSize; ++offset) {
78 memory_interface.DataWrite(TestSpaceX + offset, test_case.before.test_space_x[offset]);
79 memory_interface.DataWrite(TestSpaceY + offset, test_case.before.test_space_y[offset]);
80 }
81
82 memory_interface.ProgramWrite(0, test_case.opcode);
83 memory_interface.ProgramWrite(1, test_case.expand);
84
85 bool pass = true;
86 bool skip = false;
87 try {
88 interpreter.Run(1);
89 auto Check40 = [&](const char* name, u64 expected, u64 actual) {
90 if (expected != actual) {
91 std::printf("Mismatch: %s: %010" PRIx64 " != %010" PRIx64 "\n", name,
92 expected & 0xFF'FFFF'FFFF, actual & 0xFF'FFFF'FFFF);
93 pass = false;
94 }
95 };
96
97 auto Check32 = [&](const char* name, u32 expected, u32 actual) {
98 if (expected != actual) {
99 std::printf("Mismatch: %s: %08X != %08X\n", name, expected, actual);
100 pass = false;
101 }
102 };
103
104 auto Check = [&](const char* name, u16 expected, u16 actual) {
105 if (expected != actual) {
106 std::printf("Mismatch: %s: %04X != %04X\n", name, expected, actual);
107 pass = false;
108 }
109 };
110
111 auto CheckAddress = [&](const char* name, u16 address, u16 expected, u16 actual) {
112 if (expected != actual) {
113 std::printf("Mismatch: %s%04X: %04X != %04X\n", name, address, expected,
114 actual);
115 pass = false;
116 }
117 };
118
119 auto CheckFlag = [&](const char* name, u16 expected, u16 actual, const char* symbols) {
120 if (expected != actual) {
121 std::printf("Mismatch: %s: %s != %s\n", name,
122 Flag16ToString(expected, symbols).c_str(),
123 Flag16ToString(actual, symbols).c_str());
124 pass = false;
125 }
126 };
127
128 Check40("a0", SignExtend<40>(test_case.after.a[0]), regs.a[0]);
129 Check40("a1", SignExtend<40>(test_case.after.a[1]), regs.a[1]);
130 Check40("b0", SignExtend<40>(test_case.after.b[0]), regs.b[0]);
131 Check40("b1", SignExtend<40>(test_case.after.b[1]), regs.b[1]);
132 Check32("p0", test_case.after.p[0], regs.p[0]);
133 Check32("p1", test_case.after.p[1], regs.p[1]);
134 Check("r0", test_case.after.r[0], regs.r[0]);
135 Check("r1", test_case.after.r[1], regs.r[1]);
136 Check("r2", test_case.after.r[2], regs.r[2]);
137 Check("r3", test_case.after.r[3], regs.r[3]);
138 Check("r4", test_case.after.r[4], regs.r[4]);
139 Check("r5", test_case.after.r[5], regs.r[5]);
140 Check("r6", test_case.after.r[6], regs.r[6]);
141 Check("r7", test_case.after.r[7], regs.r[7]);
142 Check("x0", test_case.after.x[0], regs.x[0]);
143 Check("x1", test_case.after.x[1], regs.x[1]);
144 Check("y0", test_case.after.y[0], regs.y[0]);
145 Check("y1", test_case.after.y[1], regs.y[1]);
146 Check("stepi0", test_case.after.stepi0, regs.stepi0);
147 Check("stepj0", test_case.after.stepj0, regs.stepj0);
148 Check("mixp", test_case.after.mixp, regs.mixp);
149 Check("sv", test_case.after.sv, regs.sv);
150 Check("repc", test_case.after.repc, regs.repc);
151 Check("lc", test_case.after.lc, regs.Lc());
152 CheckFlag("cfgi", test_case.after.cfgi, regs.Get<Teakra::cfgi>(), "mmmmmmmmmsssssss");
153 CheckFlag("cfgj", test_case.after.cfgj, regs.Get<Teakra::cfgj>(), "mmmmmmmmmsssssss");
154 CheckFlag("stt0", test_case.after.stt0, regs.Get<Teakra::stt0>(), "####C###ZMNVCELL");
155 CheckFlag("stt1", test_case.after.stt1, regs.Get<Teakra::stt1>(), "QP#########R####");
156 CheckFlag("stt2", test_case.after.stt2, regs.Get<Teakra::stt2>(), "LBBB####mm##V21I");
157 CheckFlag("mod0", test_case.after.mod0, regs.Get<Teakra::mod0>(), "#QQ#PPooSYY###SS");
158 CheckFlag("mod1", test_case.after.mod1, regs.Get<Teakra::mod1>(), "???B####pppppppp");
159 CheckFlag("mod2", test_case.after.mod2, regs.Get<Teakra::mod2>(), "7654321m7654321M");
160 CheckFlag("ar0", test_case.after.ar[0], regs.Get<Teakra::ar0>(), "RRRRRRoosssoosss");
161 CheckFlag("ar1", test_case.after.ar[1], regs.Get<Teakra::ar1>(), "RRRRRRoosssoosss");
162 CheckFlag("arp0", test_case.after.arp[0], regs.Get<Teakra::arp0>(), "#RR#RRjjjjjiiiii");
163 CheckFlag("arp1", test_case.after.arp[1], regs.Get<Teakra::arp1>(), "#RR#RRjjjjjiiiii");
164 CheckFlag("arp2", test_case.after.arp[2], regs.Get<Teakra::arp2>(), "#RR#RRjjjjjiiiii");
165 CheckFlag("arp3", test_case.after.arp[3], regs.Get<Teakra::arp3>(), "#RR#RRjjjjjiiiii");
166
167 for (u16 offset = 0; offset < TestSpaceSize; ++offset) {
168 CheckAddress("memory_", (TestSpaceX + offset), test_case.after.test_space_x[offset],
169 memory_interface.DataRead(TestSpaceX + offset));
170 CheckAddress("memory_", (TestSpaceY + offset), test_case.after.test_space_y[offset],
171 memory_interface.DataRead(TestSpaceY + offset));
172 }
173 ++total;
174 } catch (const Teakra::UnimplementedException&) {
175 std::printf("Skipped one unimplemented case\n");
176 pass = false;
177 skip = true;
178 ++skipped;
179 }
180
181 if (pass) {
182 ++passed;
183 } else {
184 Teakra::Disassembler::ArArpSettings ar_arp;
185 ar_arp.ar = test_case.before.ar;
186 ar_arp.arp = test_case.before.arp;
187 std::printf(
188 "Test case %d: %04X %04X %s\n", i, test_case.opcode, test_case.expand,
189 Teakra::Disassembler::Do(test_case.opcode, test_case.expand, ar_arp).c_str());
190 if (!skip) {
191 std::printf("before:\n");
192 std::printf("a0 = %010" PRIx64 "; a1 = %010" PRIx64 "\n",
193 test_case.before.a[0] & 0xFF'FFFF'FFFF,
194 test_case.before.a[1] & 0xFF'FFFF'FFFF);
195 std::printf("b0 = %010" PRIx64 "; b1 = %010" PRIx64 "\n",
196 test_case.before.b[0] & 0xFF'FFFF'FFFF,
197 test_case.before.b[1] & 0xFF'FFFF'FFFF);
198 std::printf("p0 = %08X; p1 = %08X\n", test_case.before.p[0], test_case.before.p[1]);
199 std::printf("x0 = %04X; x1 = %04X\n", test_case.before.x[0], test_case.before.x[1]);
200 std::printf("y0 = %04X; y1 = %04X\n", test_case.before.y[0], test_case.before.y[1]);
201 std::printf("r0 = %04X; r1 = %04X; r2 = %04X; r3 = %04X\n", test_case.before.r[0],
202 test_case.before.r[1], test_case.before.r[2], test_case.before.r[3]);
203 std::printf("r4 = %04X; r5 = %04X; r6 = %04X; r7 = %04X\n", test_case.before.r[4],
204 test_case.before.r[5], test_case.before.r[6], test_case.before.r[7]);
205 std::printf("stepi0 = %04X\n", test_case.before.stepi0);
206 std::printf("stepj0 = %04X\n", test_case.before.stepj0);
207 std::printf("mixp = %04X\n", test_case.before.mixp);
208 std::printf("sv = %04X\n", test_case.before.sv);
209 std::printf("repc = %04X\n", test_case.before.repc);
210 std::printf("lc = %04X\n", test_case.before.lc);
211 std::printf("cfgi = %s\n",
212 Flag16ToString(test_case.before.cfgi, "mmmmmmmmmsssssss").c_str());
213 std::printf("cfgj = %s\n",
214 Flag16ToString(test_case.before.cfgj, "mmmmmmmmmsssssss").c_str());
215 std::printf("stt0 = %s\n",
216 Flag16ToString(test_case.before.stt0, "####C###ZMNVCELL").c_str());
217 std::printf("stt1 = %s\n",
218 Flag16ToString(test_case.before.stt1, "QP#########R####").c_str());
219 std::printf("stt2 = %s\n",
220 Flag16ToString(test_case.before.stt2, "LBBB####mm##V21I").c_str());
221 std::printf("mod0 = %s\n",
222 Flag16ToString(test_case.before.mod0, "#QQ#PPooSYY###SS").c_str());
223 std::printf("mod1 = %s\n",
224 Flag16ToString(test_case.before.mod1, "jicB####pppppppp").c_str());
225 std::printf("mod2 = %s\n",
226 Flag16ToString(test_case.before.mod2, "7654321m7654321M").c_str());
227 std::printf("ar0 = %s\n",
228 Flag16ToString(test_case.before.ar[0], "RRRRRRoosssoosss").c_str());
229 std::printf("ar1 = %s\n",
230 Flag16ToString(test_case.before.ar[1], "RRRRRRoosssoosss").c_str());
231 std::printf("arp0 = %s\n",
232 Flag16ToString(test_case.before.arp[0], "#RR#RRiiiiijjjjj").c_str());
233 std::printf("arp1 = %s\n",
234 Flag16ToString(test_case.before.arp[1], "#RR#RRiiiiijjjjj").c_str());
235 std::printf("arp2 = %s\n",
236 Flag16ToString(test_case.before.arp[2], "#RR#RRiiiiijjjjj").c_str());
237 std::printf("arp3 = %s\n",
238 Flag16ToString(test_case.before.arp[3], "#RR#RRiiiiijjjjj").c_str());
239 std::printf("FAILED\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
240 }
241 }
242
243 ++i;
244 }
245
246 std::printf("%d / %d passed, %d skipped\n", passed, total, skipped);
247
248 if (passed < total) {
249 return 1;
250 }
251
252 return 0;
253 }
254