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