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 594 void 595 printk(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 605 char * 606 print_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 646 int 647 main(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