]> git.ipfire.org Git - ipfire-2.x.git/blame - src/hwinfo/src/x86emu/validate.c
Signierten GPG-Schluessel importiert.
[ipfire-2.x.git] / src / hwinfo / src / x86emu / validate.c
CommitLineData
93afd047
MT
1/****************************************************************************
2*
3* Realmode X86 Emulator Library
4*
5* Copyright (C) 1996-1999 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
8*
9* ========================================================================
10*
11* Permission to use, copy, modify, distribute, and sell this software and
12* its documentation for any purpose is hereby granted without fee,
13* provided that the above copyright notice appear in all copies and that
14* both that copyright notice and this permission notice appear in
15* supporting documentation, and that the name of the authors not be used
16* in advertising or publicity pertaining to distribution of the software
17* without specific, written prior permission. The authors makes no
18* representations about the suitability of this software for any purpose.
19* It is provided "as is" without express or implied warranty.
20*
21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27* PERFORMANCE OF THIS SOFTWARE.
28*
29* ========================================================================
30*
31* Language: Watcom C 10.6 or later
32* Environment: 32-bit DOS
33* Developer: Kendall Bennett
34*
35* Description: Program to validate the x86 emulator library for
36* correctness. We run the emulator primitive operations
37* functions against the real x86 CPU, and compare the result
38* and flags to ensure correctness.
39*
40* We use inline assembler to compile and build this program.
41*
42****************************************************************************/
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <stdarg.h>
48#include "x86emu.h"
49#include "x86emu/prim_asm.h"
50
51/*-------------------------- Implementation -------------------------------*/
52
53#define true 1
54#define false 0
55
56#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF)
57
58#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \
59{ \
60 parm_type d,s; \
61 res_type r,r_asm; \
62 ulong flags,inflags; \
63 int f,failed = false; \
64 char buf1[80],buf2[80]; \
65 for (d = 0; d < dmax; d += dincr) { \
66 for (s = 0; s < smax; s += sincr) { \
67 M.x86.R_EFLG = inflags = flags = def_flags; \
68 for (f = 0; f < 2; f++) {
69
70#define VAL_TEST_BINARY(name) \
71 r_asm = name##_asm(&flags,d,s); \
72 r = name(d,s); \
73 if (r != r_asm || M.x86.R_EFLG != flags) \
74 failed = true; \
75 if (failed || trace) {
76
77#define VAL_TEST_BINARY_VOID(name) \
78 name##_asm(&flags,d,s); \
79 name(d,s); \
80 r = r_asm = 0; \
81 if (M.x86.R_EFLG != flags) \
82 failed = true; \
83 if (failed || trace) {
84
85#define VAL_FAIL_BYTE_BYTE_BINARY(name) \
86 if (failed) \
87 printk("fail\n"); \
88 printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
89 r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
90 printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
91 r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
92
93#define VAL_FAIL_WORD_WORD_BINARY(name) \
94 if (failed) \
95 printk("fail\n"); \
96 printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
97 r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
98 printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
99 r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
100
101#define VAL_FAIL_LONG_LONG_BINARY(name) \
102 if (failed) \
103 printk("fail\n"); \
104 printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
105 r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
106 printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
107 r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
108
109#define VAL_END_BINARY() \
110 } \
111 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
112 if (failed) \
113 break; \
114 } \
115 if (failed) \
116 break; \
117 } \
118 if (failed) \
119 break; \
120 } \
121 if (!failed) \
122 printk("passed\n"); \
123}
124
125#define VAL_BYTE_BYTE_BINARY(name) \
126 printk("Validating %s ... ", #name); \
127 VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
128 VAL_TEST_BINARY(name) \
129 VAL_FAIL_BYTE_BYTE_BINARY(name) \
130 VAL_END_BINARY()
131
132#define VAL_WORD_WORD_BINARY(name) \
133 printk("Validating %s ... ", #name); \
134 VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
135 VAL_TEST_BINARY(name) \
136 VAL_FAIL_WORD_WORD_BINARY(name) \
137 VAL_END_BINARY()
138
139#define VAL_LONG_LONG_BINARY(name) \
140 printk("Validating %s ... ", #name); \
141 VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
142 VAL_TEST_BINARY(name) \
143 VAL_FAIL_LONG_LONG_BINARY(name) \
144 VAL_END_BINARY()
145
146#define VAL_VOID_BYTE_BINARY(name) \
147 printk("Validating %s ... ", #name); \
148 VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
149 VAL_TEST_BINARY_VOID(name) \
150 VAL_FAIL_BYTE_BYTE_BINARY(name) \
151 VAL_END_BINARY()
152
153#define VAL_VOID_WORD_BINARY(name) \
154 printk("Validating %s ... ", #name); \
155 VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
156 VAL_TEST_BINARY_VOID(name) \
157 VAL_FAIL_WORD_WORD_BINARY(name) \
158 VAL_END_BINARY()
159
160#define VAL_VOID_LONG_BINARY(name) \
161 printk("Validating %s ... ", #name); \
162 VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
163 VAL_TEST_BINARY_VOID(name) \
164 VAL_FAIL_LONG_LONG_BINARY(name) \
165 VAL_END_BINARY()
166
167#define VAL_BYTE_ROTATE(name) \
168 printk("Validating %s ... ", #name); \
169 VAL_START_BINARY(u8,u8,0xFF,8,1,1) \
170 VAL_TEST_BINARY(name) \
171 VAL_FAIL_BYTE_BYTE_BINARY(name) \
172 VAL_END_BINARY()
173
174#define VAL_WORD_ROTATE(name) \
175 printk("Validating %s ... ", #name); \
176 VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \
177 VAL_TEST_BINARY(name) \
178 VAL_FAIL_WORD_WORD_BINARY(name) \
179 VAL_END_BINARY()
180
181#define VAL_LONG_ROTATE(name) \
182 printk("Validating %s ... ", #name); \
183 VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \
184 VAL_TEST_BINARY(name) \
185 VAL_FAIL_LONG_LONG_BINARY(name) \
186 VAL_END_BINARY()
187
188#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\
189{ \
190 parm_type d,s; \
191 res_type r,r_asm; \
192 u8 shift; \
193 u32 flags,inflags; \
194 int f,failed = false; \
195 char buf1[80],buf2[80]; \
196 for (d = 0; d < dmax; d += dincr) { \
197 for (s = 0; s < smax; s += sincr) { \
198 for (shift = 0; shift < maxshift; shift += 1) { \
199 M.x86.R_EFLG = inflags = flags = def_flags; \
200 for (f = 0; f < 2; f++) {
201
202#define VAL_TEST_TERNARY(name) \
203 r_asm = name##_asm(&flags,d,s,shift); \
204 r = name(d,s,shift); \
205 if (r != r_asm || M.x86.R_EFLG != flags) \
206 failed = true; \
207 if (failed || trace) {
208
209#define VAL_FAIL_WORD_WORD_TERNARY(name) \
210 if (failed) \
211 printk("fail\n"); \
212 printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
213 r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
214 printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
215 r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
216
217#define VAL_FAIL_LONG_LONG_TERNARY(name) \
218 if (failed) \
219 printk("fail\n"); \
220 printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
221 r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
222 printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
223 r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
224
225#define VAL_END_TERNARY() \
226 } \
227 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
228 if (failed) \
229 break; \
230 } \
231 if (failed) \
232 break; \
233 } \
234 if (failed) \
235 break; \
236 } \
237 if (failed) \
238 break; \
239 } \
240 if (!failed) \
241 printk("passed\n"); \
242}
243
244#define VAL_WORD_ROTATE_DBL(name) \
245 printk("Validating %s ... ", #name); \
246 VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \
247 VAL_TEST_TERNARY(name) \
248 VAL_FAIL_WORD_WORD_TERNARY(name) \
249 VAL_END_TERNARY()
250
251#define VAL_LONG_ROTATE_DBL(name) \
252 printk("Validating %s ... ", #name); \
253 VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \
254 VAL_TEST_TERNARY(name) \
255 VAL_FAIL_LONG_LONG_TERNARY(name) \
256 VAL_END_TERNARY()
257
258#define VAL_START_UNARY(parm_type,max,incr) \
259{ \
260 parm_type d,r,r_asm; \
261 u32 flags,inflags; \
262 int f,failed = false; \
263 char buf1[80],buf2[80]; \
264 for (d = 0; d < max; d += incr) { \
265 M.x86.R_EFLG = inflags = flags = def_flags; \
266 for (f = 0; f < 2; f++) {
267
268#define VAL_TEST_UNARY(name) \
269 r_asm = name##_asm(&flags,d); \
270 r = name(d); \
271 if (r != r_asm || M.x86.R_EFLG != flags) { \
272 failed = true;
273
274#define VAL_FAIL_BYTE_UNARY(name) \
275 printk("fail\n"); \
276 printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
277 r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
278 printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
279 r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
280
281#define VAL_FAIL_WORD_UNARY(name) \
282 printk("fail\n"); \
283 printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
284 r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
285 printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
286 r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
287
288#define VAL_FAIL_LONG_UNARY(name) \
289 printk("fail\n"); \
290 printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
291 r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
292 printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
293 r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
294
295#define VAL_END_UNARY() \
296 } \
297 M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \
298 if (failed) \
299 break; \
300 } \
301 if (failed) \
302 break; \
303 } \
304 if (!failed) \
305 printk("passed\n"); \
306}
307
308#define VAL_BYTE_UNARY(name) \
309 printk("Validating %s ... ", #name); \
310 VAL_START_UNARY(u8,0xFF,0x1) \
311 VAL_TEST_UNARY(name) \
312 VAL_FAIL_BYTE_UNARY(name) \
313 VAL_END_UNARY()
314
315#define VAL_WORD_UNARY(name) \
316 printk("Validating %s ... ", #name); \
317 VAL_START_UNARY(u16,0xFF00,0x100) \
318 VAL_TEST_UNARY(name) \
319 VAL_FAIL_WORD_UNARY(name) \
320 VAL_END_UNARY()
321
322#define VAL_WORD_BYTE_UNARY(name) \
323 printk("Validating %s ... ", #name); \
324 VAL_START_UNARY(u16,0xFF,0x1) \
325 VAL_TEST_UNARY(name) \
326 VAL_FAIL_WORD_UNARY(name) \
327 VAL_END_UNARY()
328
329#define VAL_LONG_UNARY(name) \
330 printk("Validating %s ... ", #name); \
331 VAL_START_UNARY(u32,0xFF000000,0x1000000) \
332 VAL_TEST_UNARY(name) \
333 VAL_FAIL_LONG_UNARY(name) \
334 VAL_END_UNARY()
335
336#define VAL_BYTE_MUL(name) \
337 printk("Validating %s ... ", #name); \
338{ \
339 u8 d,s; \
340 u16 r,r_asm; \
341 u32 flags,inflags; \
342 int f,failed = false; \
343 char buf1[80],buf2[80]; \
344 for (d = 0; d < 0xFF; d += 1) { \
345 for (s = 0; s < 0xFF; s += 1) { \
346 M.x86.R_EFLG = inflags = flags = def_flags; \
347 for (f = 0; f < 2; f++) { \
348 name##_asm(&flags,&r_asm,d,s); \
349 M.x86.R_AL = d; \
350 name(s); \
351 r = M.x86.R_AX; \
352 if (r != r_asm || M.x86.R_EFLG != flags) \
353 failed = true; \
354 if (failed || trace) { \
355 if (failed) \
356 printk("fail\n"); \
357 printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
358 r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
359 printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
360 r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
361 } \
362 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
363 if (failed) \
364 break; \
365 } \
366 if (failed) \
367 break; \
368 } \
369 if (failed) \
370 break; \
371 } \
372 if (!failed) \
373 printk("passed\n"); \
374}
375
376#define VAL_WORD_MUL(name) \
377 printk("Validating %s ... ", #name); \
378{ \
379 u16 d,s; \
380 u16 r_lo,r_asm_lo; \
381 u16 r_hi,r_asm_hi; \
382 u32 flags,inflags; \
383 int f,failed = false; \
384 char buf1[80],buf2[80]; \
385 for (d = 0; d < 0xFF00; d += 0x100) { \
386 for (s = 0; s < 0xFF00; s += 0x100) { \
387 M.x86.R_EFLG = inflags = flags = def_flags; \
388 for (f = 0; f < 2; f++) { \
389 name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
390 M.x86.R_AX = d; \
391 name(s); \
392 r_lo = M.x86.R_AX; \
393 r_hi = M.x86.R_DX; \
394 if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
395 failed = true; \
396 if (failed || trace) { \
397 if (failed) \
398 printk("fail\n"); \
399 printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
400 r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
401 printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
402 r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
403 } \
404 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
405 if (failed) \
406 break; \
407 } \
408 if (failed) \
409 break; \
410 } \
411 if (failed) \
412 break; \
413 } \
414 if (!failed) \
415 printk("passed\n"); \
416}
417
418#define VAL_LONG_MUL(name) \
419 printk("Validating %s ... ", #name); \
420{ \
421 u32 d,s; \
422 u32 r_lo,r_asm_lo; \
423 u32 r_hi,r_asm_hi; \
424 u32 flags,inflags; \
425 int f,failed = false; \
426 char buf1[80],buf2[80]; \
427 for (d = 0; d < 0xFF000000; d += 0x1000000) { \
428 for (s = 0; s < 0xFF000000; s += 0x1000000) { \
429 M.x86.R_EFLG = inflags = flags = def_flags; \
430 for (f = 0; f < 2; f++) { \
431 name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
432 M.x86.R_EAX = d; \
433 name(s); \
434 r_lo = M.x86.R_EAX; \
435 r_hi = M.x86.R_EDX; \
436 if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
437 failed = true; \
438 if (failed || trace) { \
439 if (failed) \
440 printk("fail\n"); \
441 printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
442 r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
443 printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
444 r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
445 } \
446 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
447 if (failed) \
448 break; \
449 } \
450 if (failed) \
451 break; \
452 } \
453 if (failed) \
454 break; \
455 } \
456 if (!failed) \
457 printk("passed\n"); \
458}
459
460#define VAL_BYTE_DIV(name) \
461 printk("Validating %s ... ", #name); \
462{ \
463 u16 d,s; \
464 u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \
465 u32 flags,inflags; \
466 int f,failed = false; \
467 char buf1[80],buf2[80]; \
468 for (d = 0; d < 0xFF00; d += 0x100) { \
469 for (s = 1; s < 0xFF; s += 1) { \
470 M.x86.R_EFLG = inflags = flags = def_flags; \
471 for (f = 0; f < 2; f++) { \
472 M.x86.intr = 0; \
473 M.x86.R_AX = d; \
474 name(s); \
475 r_quot = M.x86.R_AL; \
476 r_rem = M.x86.R_AH; \
477 if (M.x86.intr & INTR_SYNCH) \
478 continue; \
479 name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \
480 if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
481 failed = true; \
482 if (failed || trace) { \
483 if (failed) \
484 printk("fail\n"); \
485 printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
486 r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
487 printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
488 r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
489 } \
490 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
491 if (failed) \
492 break; \
493 } \
494 if (failed) \
495 break; \
496 } \
497 if (failed) \
498 break; \
499 } \
500 if (!failed) \
501 printk("passed\n"); \
502}
503
504#define VAL_WORD_DIV(name) \
505 printk("Validating %s ... ", #name); \
506{ \
507 u32 d,s; \
508 u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \
509 u32 flags,inflags; \
510 int f,failed = false; \
511 char buf1[80],buf2[80]; \
512 for (d = 0; d < 0xFF000000; d += 0x1000000) { \
513 for (s = 0x100; s < 0xFF00; s += 0x100) { \
514 M.x86.R_EFLG = inflags = flags = def_flags; \
515 for (f = 0; f < 2; f++) { \
516 M.x86.intr = 0; \
517 M.x86.R_AX = d & 0xFFFF; \
518 M.x86.R_DX = d >> 16; \
519 name(s); \
520 r_quot = M.x86.R_AX; \
521 r_rem = M.x86.R_DX; \
522 if (M.x86.intr & INTR_SYNCH) \
523 continue; \
524 name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\
525 if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
526 failed = true; \
527 if (failed || trace) { \
528 if (failed) \
529 printk("fail\n"); \
530 printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
531 r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
532 printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
533 r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
534 } \
535 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
536 if (failed) \
537 break; \
538 } \
539 if (failed) \
540 break; \
541 } \
542 if (failed) \
543 break; \
544 } \
545 if (!failed) \
546 printk("passed\n"); \
547}
548
549#define VAL_LONG_DIV(name) \
550 printk("Validating %s ... ", #name); \
551{ \
552 u32 d,s; \
553 u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \
554 u32 flags,inflags; \
555 int f,failed = false; \
556 char buf1[80],buf2[80]; \
557 for (d = 0; d < 0xFF000000; d += 0x1000000) { \
558 for (s = 0x100; s < 0xFF00; s += 0x100) { \
559 M.x86.R_EFLG = inflags = flags = def_flags; \
560 for (f = 0; f < 2; f++) { \
561 M.x86.intr = 0; \
562 M.x86.R_EAX = d; \
563 M.x86.R_EDX = 0; \
564 name(s); \
565 r_quot = M.x86.R_EAX; \
566 r_rem = M.x86.R_EDX; \
567 if (M.x86.intr & INTR_SYNCH) \
568 continue; \
569 name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \
570 if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
571 failed = true; \
572 if (failed || trace) { \
573 if (failed) \
574 printk("fail\n"); \
575 printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
576 r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
577 printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
578 r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
579 } \
580 M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
581 if (failed) \
582 break; \
583 } \
584 if (failed) \
585 break; \
586 } \
587 if (failed) \
588 break; \
589 } \
590 if (!failed) \
591 printk("passed\n"); \
592}
593
594void printk(const char *fmt, ...)
595{
596 va_list argptr;
597 va_start(argptr, fmt);
598 vfprintf(stdout, fmt, argptr);
599 fflush(stdout);
600 va_end(argptr);
601}
602
603char * print_flags(char *buf,ulong flags)
604{
605 char *separator = "";
606
607 buf[0] = 0;
608 if (flags & F_CF) {
609 strcat(buf,separator);
610 strcat(buf,"CF");
611 separator = ",";
612 }
613 if (flags & F_PF) {
614 strcat(buf,separator);
615 strcat(buf,"PF");
616 separator = ",";
617 }
618 if (flags & F_AF) {
619 strcat(buf,separator);
620 strcat(buf,"AF");
621 separator = ",";
622 }
623 if (flags & F_ZF) {
624 strcat(buf,separator);
625 strcat(buf,"ZF");
626 separator = ",";
627 }
628 if (flags & F_SF) {
629 strcat(buf,separator);
630 strcat(buf,"SF");
631 separator = ",";
632 }
633 if (flags & F_OF) {
634 strcat(buf,separator);
635 strcat(buf,"OF");
636 separator = ",";
637 }
638 if (separator[0] == 0)
639 strcpy(buf,"None");
640 return buf;
641}
642
643int main(int argc)
644{
645 ulong def_flags;
646 int trace = false;
647
648 if (argc > 1)
649 trace = true;
650 memset(&M, 0, sizeof(M));
651 def_flags = get_flags_asm() & ~ALL_FLAGS;
652
653 VAL_WORD_UNARY(aaa_word);
654 VAL_WORD_UNARY(aas_word);
655
656 VAL_WORD_UNARY(aad_word);
657 VAL_WORD_UNARY(aam_word);
658
659 VAL_BYTE_BYTE_BINARY(adc_byte);
660 VAL_WORD_WORD_BINARY(adc_word);
661 VAL_LONG_LONG_BINARY(adc_long);
662
663 VAL_BYTE_BYTE_BINARY(add_byte);
664 VAL_WORD_WORD_BINARY(add_word);
665 VAL_LONG_LONG_BINARY(add_long);
666
667 VAL_BYTE_BYTE_BINARY(and_byte);
668 VAL_WORD_WORD_BINARY(and_word);
669 VAL_LONG_LONG_BINARY(and_long);
670
671 VAL_BYTE_BYTE_BINARY(cmp_byte);
672 VAL_WORD_WORD_BINARY(cmp_word);
673 VAL_LONG_LONG_BINARY(cmp_long);
674
675 VAL_BYTE_UNARY(daa_byte);
676 VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway)
677
678 VAL_BYTE_UNARY(dec_byte);
679 VAL_WORD_UNARY(dec_word);
680 VAL_LONG_UNARY(dec_long);
681
682 VAL_BYTE_UNARY(inc_byte);
683 VAL_WORD_UNARY(inc_word);
684 VAL_LONG_UNARY(inc_long);
685
686 VAL_BYTE_BYTE_BINARY(or_byte);
687 VAL_WORD_WORD_BINARY(or_word);
688 VAL_LONG_LONG_BINARY(or_long);
689
690 VAL_BYTE_UNARY(neg_byte);
691 VAL_WORD_UNARY(neg_word);
692 VAL_LONG_UNARY(neg_long);
693
694 VAL_BYTE_UNARY(not_byte);
695 VAL_WORD_UNARY(not_word);
696 VAL_LONG_UNARY(not_long);
697
698 VAL_BYTE_ROTATE(rcl_byte);
699 VAL_WORD_ROTATE(rcl_word);
700 VAL_LONG_ROTATE(rcl_long);
701
702 VAL_BYTE_ROTATE(rcr_byte);
703 VAL_WORD_ROTATE(rcr_word);
704 VAL_LONG_ROTATE(rcr_long);
705
706 VAL_BYTE_ROTATE(rol_byte);
707 VAL_WORD_ROTATE(rol_word);
708 VAL_LONG_ROTATE(rol_long);
709
710 VAL_BYTE_ROTATE(ror_byte);
711 VAL_WORD_ROTATE(ror_word);
712 VAL_LONG_ROTATE(ror_long);
713
714 VAL_BYTE_ROTATE(shl_byte);
715 VAL_WORD_ROTATE(shl_word);
716 VAL_LONG_ROTATE(shl_long);
717
718 VAL_BYTE_ROTATE(shr_byte);
719 VAL_WORD_ROTATE(shr_word);
720 VAL_LONG_ROTATE(shr_long);
721
722 VAL_BYTE_ROTATE(sar_byte);
723 VAL_WORD_ROTATE(sar_word);
724 VAL_LONG_ROTATE(sar_long);
725
726 VAL_WORD_ROTATE_DBL(shld_word);
727 VAL_LONG_ROTATE_DBL(shld_long);
728
729 VAL_WORD_ROTATE_DBL(shrd_word);
730 VAL_LONG_ROTATE_DBL(shrd_long);
731
732 VAL_BYTE_BYTE_BINARY(sbb_byte);
733 VAL_WORD_WORD_BINARY(sbb_word);
734 VAL_LONG_LONG_BINARY(sbb_long);
735
736 VAL_BYTE_BYTE_BINARY(sub_byte);
737 VAL_WORD_WORD_BINARY(sub_word);
738 VAL_LONG_LONG_BINARY(sub_long);
739
740 VAL_BYTE_BYTE_BINARY(xor_byte);
741 VAL_WORD_WORD_BINARY(xor_word);
742 VAL_LONG_LONG_BINARY(xor_long);
743
744 VAL_VOID_BYTE_BINARY(test_byte);
745 VAL_VOID_WORD_BINARY(test_word);
746 VAL_VOID_LONG_BINARY(test_long);
747
748 VAL_BYTE_MUL(imul_byte);
749 VAL_WORD_MUL(imul_word);
750 VAL_LONG_MUL(imul_long);
751
752 VAL_BYTE_MUL(mul_byte);
753 VAL_WORD_MUL(mul_word);
754 VAL_LONG_MUL(mul_long);
755
756 VAL_BYTE_DIV(idiv_byte);
757 VAL_WORD_DIV(idiv_word);
758 VAL_LONG_DIV(idiv_long);
759
760 VAL_BYTE_DIV(div_byte);
761 VAL_WORD_DIV(div_word);
762 VAL_LONG_DIV(div_long);
763
764 return 0;
765}