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
595printk(const char *fmt, ...)
596{
597    va_list argptr;
598
599    va_start(argptr, fmt);
600    vfprintf(stdout, fmt, argptr);
601    fflush(stdout);
602    va_end(argptr);
603}
604
605char *
606print_flags(char *buf, ulong flags)
607{
608    char *separator = "";
609
610    buf[0] = 0;
611    if (flags & F_CF) {
612        strcat(buf, separator);
613        strcat(buf, "CF");
614        separator = ",";
615    }
616    if (flags & F_PF) {
617        strcat(buf, separator);
618        strcat(buf, "PF");
619        separator = ",";
620    }
621    if (flags & F_AF) {
622        strcat(buf, separator);
623        strcat(buf, "AF");
624        separator = ",";
625    }
626    if (flags & F_ZF) {
627        strcat(buf, separator);
628        strcat(buf, "ZF");
629        separator = ",";
630    }
631    if (flags & F_SF) {
632        strcat(buf, separator);
633        strcat(buf, "SF");
634        separator = ",";
635    }
636    if (flags & F_OF) {
637        strcat(buf, separator);
638        strcat(buf, "OF");
639        separator = ",";
640    }
641    if (separator[0] == 0)
642        strcpy(buf, "None");
643    return buf;
644}
645
646int
647main(int argc)
648{
649    ulong def_flags;
650    int trace = false;
651
652    if (argc > 1)
653        trace = true;
654    memset(&M, 0, sizeof(M));
655    def_flags = get_flags_asm() & ~ALL_FLAGS;
656
657    VAL_WORD_UNARY(aaa_word);
658    VAL_WORD_UNARY(aas_word);
659
660    VAL_WORD_UNARY(aad_word);
661    VAL_WORD_UNARY(aam_word);
662
663    VAL_BYTE_BYTE_BINARY(adc_byte);
664    VAL_WORD_WORD_BINARY(adc_word);
665    VAL_LONG_LONG_BINARY(adc_long);
666
667    VAL_BYTE_BYTE_BINARY(add_byte);
668    VAL_WORD_WORD_BINARY(add_word);
669    VAL_LONG_LONG_BINARY(add_long);
670
671    VAL_BYTE_BYTE_BINARY(and_byte);
672    VAL_WORD_WORD_BINARY(and_word);
673    VAL_LONG_LONG_BINARY(and_long);
674
675    VAL_BYTE_BYTE_BINARY(cmp_byte);
676    VAL_WORD_WORD_BINARY(cmp_word);
677    VAL_LONG_LONG_BINARY(cmp_long);
678
679    VAL_BYTE_UNARY(daa_byte);
680    VAL_BYTE_UNARY(das_byte);   /* Fails for 0x9A (out of range anyway) */
681
682    VAL_BYTE_UNARY(dec_byte);
683    VAL_WORD_UNARY(dec_word);
684    VAL_LONG_UNARY(dec_long);
685
686    VAL_BYTE_UNARY(inc_byte);
687    VAL_WORD_UNARY(inc_word);
688    VAL_LONG_UNARY(inc_long);
689
690    VAL_BYTE_BYTE_BINARY(or_byte);
691    VAL_WORD_WORD_BINARY(or_word);
692    VAL_LONG_LONG_BINARY(or_long);
693
694    VAL_BYTE_UNARY(neg_byte);
695    VAL_WORD_UNARY(neg_word);
696    VAL_LONG_UNARY(neg_long);
697
698    VAL_BYTE_UNARY(not_byte);
699    VAL_WORD_UNARY(not_word);
700    VAL_LONG_UNARY(not_long);
701
702    VAL_BYTE_ROTATE(rcl_byte);
703    VAL_WORD_ROTATE(rcl_word);
704    VAL_LONG_ROTATE(rcl_long);
705
706    VAL_BYTE_ROTATE(rcr_byte);
707    VAL_WORD_ROTATE(rcr_word);
708    VAL_LONG_ROTATE(rcr_long);
709
710    VAL_BYTE_ROTATE(rol_byte);
711    VAL_WORD_ROTATE(rol_word);
712    VAL_LONG_ROTATE(rol_long);
713
714    VAL_BYTE_ROTATE(ror_byte);
715    VAL_WORD_ROTATE(ror_word);
716    VAL_LONG_ROTATE(ror_long);
717
718    VAL_BYTE_ROTATE(shl_byte);
719    VAL_WORD_ROTATE(shl_word);
720    VAL_LONG_ROTATE(shl_long);
721
722    VAL_BYTE_ROTATE(shr_byte);
723    VAL_WORD_ROTATE(shr_word);
724    VAL_LONG_ROTATE(shr_long);
725
726    VAL_BYTE_ROTATE(sar_byte);
727    VAL_WORD_ROTATE(sar_word);
728    VAL_LONG_ROTATE(sar_long);
729
730    VAL_WORD_ROTATE_DBL(shld_word);
731    VAL_LONG_ROTATE_DBL(shld_long);
732
733    VAL_WORD_ROTATE_DBL(shrd_word);
734    VAL_LONG_ROTATE_DBL(shrd_long);
735
736    VAL_BYTE_BYTE_BINARY(sbb_byte);
737    VAL_WORD_WORD_BINARY(sbb_word);
738    VAL_LONG_LONG_BINARY(sbb_long);
739
740    VAL_BYTE_BYTE_BINARY(sub_byte);
741    VAL_WORD_WORD_BINARY(sub_word);
742    VAL_LONG_LONG_BINARY(sub_long);
743
744    VAL_BYTE_BYTE_BINARY(xor_byte);
745    VAL_WORD_WORD_BINARY(xor_word);
746    VAL_LONG_LONG_BINARY(xor_long);
747
748    VAL_VOID_BYTE_BINARY(test_byte);
749    VAL_VOID_WORD_BINARY(test_word);
750    VAL_VOID_LONG_BINARY(test_long);
751
752    VAL_BYTE_MUL(imul_byte);
753    VAL_WORD_MUL(imul_word);
754    VAL_LONG_MUL(imul_long);
755
756    VAL_BYTE_MUL(mul_byte);
757    VAL_WORD_MUL(mul_word);
758    VAL_LONG_MUL(mul_long);
759
760    VAL_BYTE_DIV(idiv_byte);
761    VAL_WORD_DIV(idiv_word);
762    VAL_LONG_DIV(idiv_long);
763
764    VAL_BYTE_DIV(div_byte);
765    VAL_WORD_DIV(div_word);
766    VAL_LONG_DIV(div_long);
767
768    return 0;
769}
770