1161537Smarcel/**************************************************************************** 2161537Smarcel* 3161537Smarcel* Realmode X86 Emulator Library 4161537Smarcel* 5161537Smarcel* Copyright (C) 1996-1999 SciTech Software, Inc. 6161537Smarcel* Copyright (C) David Mosberger-Tang 7161537Smarcel* Copyright (C) 1999 Egbert Eich 8161537Smarcel* 9161537Smarcel* ======================================================================== 10161537Smarcel* 11161537Smarcel* Permission to use, copy, modify, distribute, and sell this software and 12161537Smarcel* its documentation for any purpose is hereby granted without fee, 13161537Smarcel* provided that the above copyright notice appear in all copies and that 14161537Smarcel* both that copyright notice and this permission notice appear in 15161537Smarcel* supporting documentation, and that the name of the authors not be used 16161537Smarcel* in advertising or publicity pertaining to distribution of the software 17161537Smarcel* without specific, written prior permission. The authors makes no 18161537Smarcel* representations about the suitability of this software for any purpose. 19161537Smarcel* It is provided "as is" without express or implied warranty. 20161537Smarcel* 21161537Smarcel* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22161537Smarcel* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23161537Smarcel* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24161537Smarcel* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25161537Smarcel* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26161537Smarcel* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27161537Smarcel* PERFORMANCE OF THIS SOFTWARE. 28161537Smarcel* 29161537Smarcel* ======================================================================== 30161537Smarcel* 31161537Smarcel* Language: Watcom C 10.6 or later 32161537Smarcel* Environment: 32-bit DOS 33161537Smarcel* Developer: Kendall Bennett 34161537Smarcel* 35161537Smarcel* Description: Program to validate the x86 emulator library for 36161537Smarcel* correctness. We run the emulator primitive operations 37161537Smarcel* functions against the real x86 CPU, and compare the result 38161537Smarcel* and flags to ensure correctness. 39161537Smarcel* 40161537Smarcel* We use inline assembler to compile and build this program. 41161537Smarcel* 42161537Smarcel****************************************************************************/ 43161537Smarcel 44161537Smarcel#include <stdio.h> 45161537Smarcel#include <stdlib.h> 46161537Smarcel#include <string.h> 47161537Smarcel#include <stdarg.h> 48161537Smarcel#include "x86emu.h" 49161537Smarcel#include "x86emu/prim_asm.h" 50161537Smarcel 51161537Smarcel/*-------------------------- Implementation -------------------------------*/ 52161537Smarcel 53161537Smarcel#define true 1 54161537Smarcel#define false 0 55161537Smarcel 56161537Smarcel#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF) 57161537Smarcel 58161537Smarcel#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \ 59161537Smarcel{ \ 60161537Smarcel parm_type d,s; \ 61161537Smarcel res_type r,r_asm; \ 62161537Smarcel ulong flags,inflags; \ 63161537Smarcel int f,failed = false; \ 64161537Smarcel char buf1[80],buf2[80]; \ 65161537Smarcel for (d = 0; d < dmax; d += dincr) { \ 66161537Smarcel for (s = 0; s < smax; s += sincr) { \ 67161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 68161537Smarcel for (f = 0; f < 2; f++) { 69161537Smarcel 70161537Smarcel#define VAL_TEST_BINARY(name) \ 71161537Smarcel r_asm = name##_asm(&flags,d,s); \ 72161537Smarcel r = name(d,s); \ 73161537Smarcel if (r != r_asm || M.x86.R_EFLG != flags) \ 74161537Smarcel failed = true; \ 75161537Smarcel if (failed || trace) { 76161537Smarcel 77161537Smarcel#define VAL_TEST_BINARY_VOID(name) \ 78161537Smarcel name##_asm(&flags,d,s); \ 79161537Smarcel name(d,s); \ 80161537Smarcel r = r_asm = 0; \ 81161537Smarcel if (M.x86.R_EFLG != flags) \ 82161537Smarcel failed = true; \ 83161537Smarcel if (failed || trace) { 84161537Smarcel 85161537Smarcel#define VAL_FAIL_BYTE_BYTE_BINARY(name) \ 86161537Smarcel if (failed) \ 87161537Smarcel printk("fail\n"); \ 88161537Smarcel printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 89161537Smarcel r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 90161537Smarcel printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 91161537Smarcel r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); 92161537Smarcel 93161537Smarcel#define VAL_FAIL_WORD_WORD_BINARY(name) \ 94161537Smarcel if (failed) \ 95161537Smarcel printk("fail\n"); \ 96161537Smarcel printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 97161537Smarcel r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 98161537Smarcel printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 99161537Smarcel r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); 100161537Smarcel 101161537Smarcel#define VAL_FAIL_LONG_LONG_BINARY(name) \ 102161537Smarcel if (failed) \ 103161537Smarcel printk("fail\n"); \ 104161537Smarcel printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 105161537Smarcel r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 106161537Smarcel printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 107161537Smarcel r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); 108161537Smarcel 109161537Smarcel#define VAL_END_BINARY() \ 110161537Smarcel } \ 111161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 112161537Smarcel if (failed) \ 113161537Smarcel break; \ 114161537Smarcel } \ 115161537Smarcel if (failed) \ 116161537Smarcel break; \ 117161537Smarcel } \ 118161537Smarcel if (failed) \ 119161537Smarcel break; \ 120161537Smarcel } \ 121161537Smarcel if (!failed) \ 122161537Smarcel printk("passed\n"); \ 123161537Smarcel} 124161537Smarcel 125161537Smarcel#define VAL_BYTE_BYTE_BINARY(name) \ 126161537Smarcel printk("Validating %s ... ", #name); \ 127161537Smarcel VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ 128161537Smarcel VAL_TEST_BINARY(name) \ 129161537Smarcel VAL_FAIL_BYTE_BYTE_BINARY(name) \ 130161537Smarcel VAL_END_BINARY() 131161537Smarcel 132161537Smarcel#define VAL_WORD_WORD_BINARY(name) \ 133161537Smarcel printk("Validating %s ... ", #name); \ 134161537Smarcel VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ 135161537Smarcel VAL_TEST_BINARY(name) \ 136161537Smarcel VAL_FAIL_WORD_WORD_BINARY(name) \ 137161537Smarcel VAL_END_BINARY() 138161537Smarcel 139161537Smarcel#define VAL_LONG_LONG_BINARY(name) \ 140161537Smarcel printk("Validating %s ... ", #name); \ 141161537Smarcel VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ 142161537Smarcel VAL_TEST_BINARY(name) \ 143161537Smarcel VAL_FAIL_LONG_LONG_BINARY(name) \ 144161537Smarcel VAL_END_BINARY() 145161537Smarcel 146161537Smarcel#define VAL_VOID_BYTE_BINARY(name) \ 147161537Smarcel printk("Validating %s ... ", #name); \ 148161537Smarcel VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ 149161537Smarcel VAL_TEST_BINARY_VOID(name) \ 150161537Smarcel VAL_FAIL_BYTE_BYTE_BINARY(name) \ 151161537Smarcel VAL_END_BINARY() 152161537Smarcel 153161537Smarcel#define VAL_VOID_WORD_BINARY(name) \ 154161537Smarcel printk("Validating %s ... ", #name); \ 155161537Smarcel VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ 156161537Smarcel VAL_TEST_BINARY_VOID(name) \ 157161537Smarcel VAL_FAIL_WORD_WORD_BINARY(name) \ 158161537Smarcel VAL_END_BINARY() 159161537Smarcel 160161537Smarcel#define VAL_VOID_LONG_BINARY(name) \ 161161537Smarcel printk("Validating %s ... ", #name); \ 162161537Smarcel VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ 163161537Smarcel VAL_TEST_BINARY_VOID(name) \ 164161537Smarcel VAL_FAIL_LONG_LONG_BINARY(name) \ 165161537Smarcel VAL_END_BINARY() 166161537Smarcel 167161537Smarcel#define VAL_BYTE_ROTATE(name) \ 168161537Smarcel printk("Validating %s ... ", #name); \ 169161537Smarcel VAL_START_BINARY(u8,u8,0xFF,8,1,1) \ 170161537Smarcel VAL_TEST_BINARY(name) \ 171161537Smarcel VAL_FAIL_BYTE_BYTE_BINARY(name) \ 172161537Smarcel VAL_END_BINARY() 173161537Smarcel 174161537Smarcel#define VAL_WORD_ROTATE(name) \ 175161537Smarcel printk("Validating %s ... ", #name); \ 176161537Smarcel VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \ 177161537Smarcel VAL_TEST_BINARY(name) \ 178161537Smarcel VAL_FAIL_WORD_WORD_BINARY(name) \ 179161537Smarcel VAL_END_BINARY() 180161537Smarcel 181161537Smarcel#define VAL_LONG_ROTATE(name) \ 182161537Smarcel printk("Validating %s ... ", #name); \ 183161537Smarcel VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \ 184161537Smarcel VAL_TEST_BINARY(name) \ 185161537Smarcel VAL_FAIL_LONG_LONG_BINARY(name) \ 186161537Smarcel VAL_END_BINARY() 187161537Smarcel 188161537Smarcel#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\ 189161537Smarcel{ \ 190161537Smarcel parm_type d,s; \ 191161537Smarcel res_type r,r_asm; \ 192161537Smarcel u8 shift; \ 193161537Smarcel u32 flags,inflags; \ 194161537Smarcel int f,failed = false; \ 195161537Smarcel char buf1[80],buf2[80]; \ 196161537Smarcel for (d = 0; d < dmax; d += dincr) { \ 197161537Smarcel for (s = 0; s < smax; s += sincr) { \ 198161537Smarcel for (shift = 0; shift < maxshift; shift += 1) { \ 199161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 200161537Smarcel for (f = 0; f < 2; f++) { 201161537Smarcel 202161537Smarcel#define VAL_TEST_TERNARY(name) \ 203161537Smarcel r_asm = name##_asm(&flags,d,s,shift); \ 204161537Smarcel r = name(d,s,shift); \ 205161537Smarcel if (r != r_asm || M.x86.R_EFLG != flags) \ 206161537Smarcel failed = true; \ 207161537Smarcel if (failed || trace) { 208161537Smarcel 209161537Smarcel#define VAL_FAIL_WORD_WORD_TERNARY(name) \ 210161537Smarcel if (failed) \ 211161537Smarcel printk("fail\n"); \ 212161537Smarcel printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ 213161537Smarcel r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 214161537Smarcel printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ 215161537Smarcel r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); 216161537Smarcel 217161537Smarcel#define VAL_FAIL_LONG_LONG_TERNARY(name) \ 218161537Smarcel if (failed) \ 219161537Smarcel printk("fail\n"); \ 220161537Smarcel printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ 221161537Smarcel r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 222161537Smarcel printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ 223161537Smarcel r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); 224161537Smarcel 225161537Smarcel#define VAL_END_TERNARY() \ 226161537Smarcel } \ 227161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 228161537Smarcel if (failed) \ 229161537Smarcel break; \ 230161537Smarcel } \ 231161537Smarcel if (failed) \ 232161537Smarcel break; \ 233161537Smarcel } \ 234161537Smarcel if (failed) \ 235161537Smarcel break; \ 236161537Smarcel } \ 237161537Smarcel if (failed) \ 238161537Smarcel break; \ 239161537Smarcel } \ 240161537Smarcel if (!failed) \ 241161537Smarcel printk("passed\n"); \ 242161537Smarcel} 243161537Smarcel 244161537Smarcel#define VAL_WORD_ROTATE_DBL(name) \ 245161537Smarcel printk("Validating %s ... ", #name); \ 246161537Smarcel VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \ 247161537Smarcel VAL_TEST_TERNARY(name) \ 248161537Smarcel VAL_FAIL_WORD_WORD_TERNARY(name) \ 249161537Smarcel VAL_END_TERNARY() 250161537Smarcel 251161537Smarcel#define VAL_LONG_ROTATE_DBL(name) \ 252161537Smarcel printk("Validating %s ... ", #name); \ 253161537Smarcel VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \ 254161537Smarcel VAL_TEST_TERNARY(name) \ 255161537Smarcel VAL_FAIL_LONG_LONG_TERNARY(name) \ 256161537Smarcel VAL_END_TERNARY() 257161537Smarcel 258161537Smarcel#define VAL_START_UNARY(parm_type,max,incr) \ 259161537Smarcel{ \ 260161537Smarcel parm_type d,r,r_asm; \ 261161537Smarcel u32 flags,inflags; \ 262161537Smarcel int f,failed = false; \ 263161537Smarcel char buf1[80],buf2[80]; \ 264161537Smarcel for (d = 0; d < max; d += incr) { \ 265161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 266161537Smarcel for (f = 0; f < 2; f++) { 267161537Smarcel 268161537Smarcel#define VAL_TEST_UNARY(name) \ 269161537Smarcel r_asm = name##_asm(&flags,d); \ 270161537Smarcel r = name(d); \ 271161537Smarcel if (r != r_asm || M.x86.R_EFLG != flags) { \ 272161537Smarcel failed = true; 273161537Smarcel 274161537Smarcel#define VAL_FAIL_BYTE_UNARY(name) \ 275161537Smarcel printk("fail\n"); \ 276161537Smarcel printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ 277161537Smarcel r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 278161537Smarcel printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ 279161537Smarcel r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); 280161537Smarcel 281161537Smarcel#define VAL_FAIL_WORD_UNARY(name) \ 282161537Smarcel printk("fail\n"); \ 283161537Smarcel printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ 284161537Smarcel r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 285161537Smarcel printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ 286161537Smarcel r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); 287161537Smarcel 288161537Smarcel#define VAL_FAIL_LONG_UNARY(name) \ 289161537Smarcel printk("fail\n"); \ 290161537Smarcel printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ 291161537Smarcel r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 292161537Smarcel printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ 293161537Smarcel r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); 294161537Smarcel 295161537Smarcel#define VAL_END_UNARY() \ 296161537Smarcel } \ 297161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \ 298161537Smarcel if (failed) \ 299161537Smarcel break; \ 300161537Smarcel } \ 301161537Smarcel if (failed) \ 302161537Smarcel break; \ 303161537Smarcel } \ 304161537Smarcel if (!failed) \ 305161537Smarcel printk("passed\n"); \ 306161537Smarcel} 307161537Smarcel 308161537Smarcel#define VAL_BYTE_UNARY(name) \ 309161537Smarcel printk("Validating %s ... ", #name); \ 310161537Smarcel VAL_START_UNARY(u8,0xFF,0x1) \ 311161537Smarcel VAL_TEST_UNARY(name) \ 312161537Smarcel VAL_FAIL_BYTE_UNARY(name) \ 313161537Smarcel VAL_END_UNARY() 314161537Smarcel 315161537Smarcel#define VAL_WORD_UNARY(name) \ 316161537Smarcel printk("Validating %s ... ", #name); \ 317161537Smarcel VAL_START_UNARY(u16,0xFF00,0x100) \ 318161537Smarcel VAL_TEST_UNARY(name) \ 319161537Smarcel VAL_FAIL_WORD_UNARY(name) \ 320161537Smarcel VAL_END_UNARY() 321161537Smarcel 322161537Smarcel#define VAL_WORD_BYTE_UNARY(name) \ 323161537Smarcel printk("Validating %s ... ", #name); \ 324161537Smarcel VAL_START_UNARY(u16,0xFF,0x1) \ 325161537Smarcel VAL_TEST_UNARY(name) \ 326161537Smarcel VAL_FAIL_WORD_UNARY(name) \ 327161537Smarcel VAL_END_UNARY() 328161537Smarcel 329161537Smarcel#define VAL_LONG_UNARY(name) \ 330161537Smarcel printk("Validating %s ... ", #name); \ 331161537Smarcel VAL_START_UNARY(u32,0xFF000000,0x1000000) \ 332161537Smarcel VAL_TEST_UNARY(name) \ 333161537Smarcel VAL_FAIL_LONG_UNARY(name) \ 334161537Smarcel VAL_END_UNARY() 335161537Smarcel 336161537Smarcel#define VAL_BYTE_MUL(name) \ 337161537Smarcel printk("Validating %s ... ", #name); \ 338161537Smarcel{ \ 339161537Smarcel u8 d,s; \ 340161537Smarcel u16 r,r_asm; \ 341161537Smarcel u32 flags,inflags; \ 342161537Smarcel int f,failed = false; \ 343161537Smarcel char buf1[80],buf2[80]; \ 344161537Smarcel for (d = 0; d < 0xFF; d += 1) { \ 345161537Smarcel for (s = 0; s < 0xFF; s += 1) { \ 346161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 347161537Smarcel for (f = 0; f < 2; f++) { \ 348161537Smarcel name##_asm(&flags,&r_asm,d,s); \ 349161537Smarcel M.x86.R_AL = d; \ 350161537Smarcel name(s); \ 351161537Smarcel r = M.x86.R_AX; \ 352161537Smarcel if (r != r_asm || M.x86.R_EFLG != flags) \ 353161537Smarcel failed = true; \ 354161537Smarcel if (failed || trace) { \ 355161537Smarcel if (failed) \ 356161537Smarcel printk("fail\n"); \ 357161537Smarcel printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 358161537Smarcel r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 359161537Smarcel printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 360161537Smarcel r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 361161537Smarcel } \ 362161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 363161537Smarcel if (failed) \ 364161537Smarcel break; \ 365161537Smarcel } \ 366161537Smarcel if (failed) \ 367161537Smarcel break; \ 368161537Smarcel } \ 369161537Smarcel if (failed) \ 370161537Smarcel break; \ 371161537Smarcel } \ 372161537Smarcel if (!failed) \ 373161537Smarcel printk("passed\n"); \ 374161537Smarcel} 375161537Smarcel 376161537Smarcel#define VAL_WORD_MUL(name) \ 377161537Smarcel printk("Validating %s ... ", #name); \ 378161537Smarcel{ \ 379161537Smarcel u16 d,s; \ 380161537Smarcel u16 r_lo,r_asm_lo; \ 381161537Smarcel u16 r_hi,r_asm_hi; \ 382161537Smarcel u32 flags,inflags; \ 383161537Smarcel int f,failed = false; \ 384161537Smarcel char buf1[80],buf2[80]; \ 385161537Smarcel for (d = 0; d < 0xFF00; d += 0x100) { \ 386161537Smarcel for (s = 0; s < 0xFF00; s += 0x100) { \ 387161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 388161537Smarcel for (f = 0; f < 2; f++) { \ 389161537Smarcel name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ 390161537Smarcel M.x86.R_AX = d; \ 391161537Smarcel name(s); \ 392161537Smarcel r_lo = M.x86.R_AX; \ 393161537Smarcel r_hi = M.x86.R_DX; \ 394161537Smarcel if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ 395161537Smarcel failed = true; \ 396161537Smarcel if (failed || trace) { \ 397161537Smarcel if (failed) \ 398161537Smarcel printk("fail\n"); \ 399161537Smarcel printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 400161537Smarcel r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 401161537Smarcel printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 402161537Smarcel r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 403161537Smarcel } \ 404161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 405161537Smarcel if (failed) \ 406161537Smarcel break; \ 407161537Smarcel } \ 408161537Smarcel if (failed) \ 409161537Smarcel break; \ 410161537Smarcel } \ 411161537Smarcel if (failed) \ 412161537Smarcel break; \ 413161537Smarcel } \ 414161537Smarcel if (!failed) \ 415161537Smarcel printk("passed\n"); \ 416161537Smarcel} 417161537Smarcel 418161537Smarcel#define VAL_LONG_MUL(name) \ 419161537Smarcel printk("Validating %s ... ", #name); \ 420161537Smarcel{ \ 421161537Smarcel u32 d,s; \ 422161537Smarcel u32 r_lo,r_asm_lo; \ 423161537Smarcel u32 r_hi,r_asm_hi; \ 424161537Smarcel u32 flags,inflags; \ 425161537Smarcel int f,failed = false; \ 426161537Smarcel char buf1[80],buf2[80]; \ 427161537Smarcel for (d = 0; d < 0xFF000000; d += 0x1000000) { \ 428161537Smarcel for (s = 0; s < 0xFF000000; s += 0x1000000) { \ 429161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 430161537Smarcel for (f = 0; f < 2; f++) { \ 431161537Smarcel name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ 432161537Smarcel M.x86.R_EAX = d; \ 433161537Smarcel name(s); \ 434161537Smarcel r_lo = M.x86.R_EAX; \ 435161537Smarcel r_hi = M.x86.R_EDX; \ 436161537Smarcel if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ 437161537Smarcel failed = true; \ 438161537Smarcel if (failed || trace) { \ 439161537Smarcel if (failed) \ 440161537Smarcel printk("fail\n"); \ 441161537Smarcel printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 442161537Smarcel r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 443161537Smarcel printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 444161537Smarcel r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 445161537Smarcel } \ 446161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 447161537Smarcel if (failed) \ 448161537Smarcel break; \ 449161537Smarcel } \ 450161537Smarcel if (failed) \ 451161537Smarcel break; \ 452161537Smarcel } \ 453161537Smarcel if (failed) \ 454161537Smarcel break; \ 455161537Smarcel } \ 456161537Smarcel if (!failed) \ 457161537Smarcel printk("passed\n"); \ 458161537Smarcel} 459161537Smarcel 460161537Smarcel#define VAL_BYTE_DIV(name) \ 461161537Smarcel printk("Validating %s ... ", #name); \ 462161537Smarcel{ \ 463161537Smarcel u16 d,s; \ 464161537Smarcel u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \ 465161537Smarcel u32 flags,inflags; \ 466161537Smarcel int f,failed = false; \ 467161537Smarcel char buf1[80],buf2[80]; \ 468161537Smarcel for (d = 0; d < 0xFF00; d += 0x100) { \ 469161537Smarcel for (s = 1; s < 0xFF; s += 1) { \ 470161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 471161537Smarcel for (f = 0; f < 2; f++) { \ 472161537Smarcel M.x86.intr = 0; \ 473161537Smarcel M.x86.R_AX = d; \ 474161537Smarcel name(s); \ 475161537Smarcel r_quot = M.x86.R_AL; \ 476161537Smarcel r_rem = M.x86.R_AH; \ 477161537Smarcel if (M.x86.intr & INTR_SYNCH) \ 478161537Smarcel continue; \ 479161537Smarcel name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \ 480161537Smarcel if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ 481161537Smarcel failed = true; \ 482161537Smarcel if (failed || trace) { \ 483161537Smarcel if (failed) \ 484161537Smarcel printk("fail\n"); \ 485161537Smarcel printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ 486161537Smarcel r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 487161537Smarcel printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ 488161537Smarcel r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 489161537Smarcel } \ 490161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 491161537Smarcel if (failed) \ 492161537Smarcel break; \ 493161537Smarcel } \ 494161537Smarcel if (failed) \ 495161537Smarcel break; \ 496161537Smarcel } \ 497161537Smarcel if (failed) \ 498161537Smarcel break; \ 499161537Smarcel } \ 500161537Smarcel if (!failed) \ 501161537Smarcel printk("passed\n"); \ 502161537Smarcel} 503161537Smarcel 504161537Smarcel#define VAL_WORD_DIV(name) \ 505161537Smarcel printk("Validating %s ... ", #name); \ 506161537Smarcel{ \ 507161537Smarcel u32 d,s; \ 508161537Smarcel u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \ 509161537Smarcel u32 flags,inflags; \ 510161537Smarcel int f,failed = false; \ 511161537Smarcel char buf1[80],buf2[80]; \ 512161537Smarcel for (d = 0; d < 0xFF000000; d += 0x1000000) { \ 513161537Smarcel for (s = 0x100; s < 0xFF00; s += 0x100) { \ 514161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 515161537Smarcel for (f = 0; f < 2; f++) { \ 516161537Smarcel M.x86.intr = 0; \ 517161537Smarcel M.x86.R_AX = d & 0xFFFF; \ 518161537Smarcel M.x86.R_DX = d >> 16; \ 519161537Smarcel name(s); \ 520161537Smarcel r_quot = M.x86.R_AX; \ 521161537Smarcel r_rem = M.x86.R_DX; \ 522161537Smarcel if (M.x86.intr & INTR_SYNCH) \ 523161537Smarcel continue; \ 524161537Smarcel name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\ 525161537Smarcel if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ 526161537Smarcel failed = true; \ 527161537Smarcel if (failed || trace) { \ 528161537Smarcel if (failed) \ 529161537Smarcel printk("fail\n"); \ 530161537Smarcel printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ 531161537Smarcel r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 532161537Smarcel printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ 533161537Smarcel r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 534161537Smarcel } \ 535161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 536161537Smarcel if (failed) \ 537161537Smarcel break; \ 538161537Smarcel } \ 539161537Smarcel if (failed) \ 540161537Smarcel break; \ 541161537Smarcel } \ 542161537Smarcel if (failed) \ 543161537Smarcel break; \ 544161537Smarcel } \ 545161537Smarcel if (!failed) \ 546161537Smarcel printk("passed\n"); \ 547161537Smarcel} 548161537Smarcel 549161537Smarcel#define VAL_LONG_DIV(name) \ 550161537Smarcel printk("Validating %s ... ", #name); \ 551161537Smarcel{ \ 552161537Smarcel u32 d,s; \ 553161537Smarcel u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \ 554161537Smarcel u32 flags,inflags; \ 555161537Smarcel int f,failed = false; \ 556161537Smarcel char buf1[80],buf2[80]; \ 557161537Smarcel for (d = 0; d < 0xFF000000; d += 0x1000000) { \ 558161537Smarcel for (s = 0x100; s < 0xFF00; s += 0x100) { \ 559161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags; \ 560161537Smarcel for (f = 0; f < 2; f++) { \ 561161537Smarcel M.x86.intr = 0; \ 562161537Smarcel M.x86.R_EAX = d; \ 563161537Smarcel M.x86.R_EDX = 0; \ 564161537Smarcel name(s); \ 565161537Smarcel r_quot = M.x86.R_EAX; \ 566161537Smarcel r_rem = M.x86.R_EDX; \ 567161537Smarcel if (M.x86.intr & INTR_SYNCH) \ 568161537Smarcel continue; \ 569161537Smarcel name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \ 570161537Smarcel if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ 571161537Smarcel failed = true; \ 572161537Smarcel if (failed || trace) { \ 573161537Smarcel if (failed) \ 574161537Smarcel printk("fail\n"); \ 575161537Smarcel printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ 576161537Smarcel r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 577161537Smarcel printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ 578161537Smarcel r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 579161537Smarcel } \ 580161537Smarcel M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 581161537Smarcel if (failed) \ 582161537Smarcel break; \ 583161537Smarcel } \ 584161537Smarcel if (failed) \ 585161537Smarcel break; \ 586161537Smarcel } \ 587161537Smarcel if (failed) \ 588161537Smarcel break; \ 589161537Smarcel } \ 590161537Smarcel if (!failed) \ 591161537Smarcel printk("passed\n"); \ 592161537Smarcel} 593161537Smarcel 594161537Smarcelvoid 595161537Smarcelprintk(const char *fmt, ...) 596161537Smarcel{ 597161537Smarcel va_list argptr; 598161537Smarcel 599161537Smarcel va_start(argptr, fmt); 600161537Smarcel vfprintf(stdout, fmt, argptr); 601161537Smarcel fflush(stdout); 602161537Smarcel va_end(argptr); 603161537Smarcel} 604161537Smarcel 605161537Smarcelchar * 606161537Smarcelprint_flags(char *buf, ulong flags) 607161537Smarcel{ 608161537Smarcel char *separator = ""; 609161537Smarcel 610161537Smarcel buf[0] = 0; 611161537Smarcel if (flags & F_CF) { 612161537Smarcel strcat(buf, separator); 613161537Smarcel strcat(buf, "CF"); 614161537Smarcel separator = ","; 615161537Smarcel } 616161537Smarcel if (flags & F_PF) { 617161537Smarcel strcat(buf, separator); 618161537Smarcel strcat(buf, "PF"); 619161537Smarcel separator = ","; 620161537Smarcel } 621161537Smarcel if (flags & F_AF) { 622161537Smarcel strcat(buf, separator); 623161537Smarcel strcat(buf, "AF"); 624161537Smarcel separator = ","; 625161537Smarcel } 626161537Smarcel if (flags & F_ZF) { 627161537Smarcel strcat(buf, separator); 628161537Smarcel strcat(buf, "ZF"); 629161537Smarcel separator = ","; 630161537Smarcel } 631161537Smarcel if (flags & F_SF) { 632161537Smarcel strcat(buf, separator); 633161537Smarcel strcat(buf, "SF"); 634161537Smarcel separator = ","; 635161537Smarcel } 636161537Smarcel if (flags & F_OF) { 637161537Smarcel strcat(buf, separator); 638161537Smarcel strcat(buf, "OF"); 639161537Smarcel separator = ","; 640161537Smarcel } 641161537Smarcel if (separator[0] == 0) 642161537Smarcel strcpy(buf, "None"); 643161537Smarcel return buf; 644161537Smarcel} 645161537Smarcel 646161537Smarcelint 647161537Smarcelmain(int argc) 648161537Smarcel{ 649161537Smarcel ulong def_flags; 650161537Smarcel int trace = false; 651161537Smarcel 652161537Smarcel if (argc > 1) 653161537Smarcel trace = true; 654161537Smarcel memset(&M, 0, sizeof(M)); 655161537Smarcel def_flags = get_flags_asm() & ~ALL_FLAGS; 656161537Smarcel 657161537Smarcel VAL_WORD_UNARY(aaa_word); 658161537Smarcel VAL_WORD_UNARY(aas_word); 659161537Smarcel 660161537Smarcel VAL_WORD_UNARY(aad_word); 661161537Smarcel VAL_WORD_UNARY(aam_word); 662161537Smarcel 663161537Smarcel VAL_BYTE_BYTE_BINARY(adc_byte); 664161537Smarcel VAL_WORD_WORD_BINARY(adc_word); 665161537Smarcel VAL_LONG_LONG_BINARY(adc_long); 666161537Smarcel 667161537Smarcel VAL_BYTE_BYTE_BINARY(add_byte); 668161537Smarcel VAL_WORD_WORD_BINARY(add_word); 669161537Smarcel VAL_LONG_LONG_BINARY(add_long); 670161537Smarcel 671161537Smarcel VAL_BYTE_BYTE_BINARY(and_byte); 672161537Smarcel VAL_WORD_WORD_BINARY(and_word); 673161537Smarcel VAL_LONG_LONG_BINARY(and_long); 674161537Smarcel 675161537Smarcel VAL_BYTE_BYTE_BINARY(cmp_byte); 676161537Smarcel VAL_WORD_WORD_BINARY(cmp_word); 677161537Smarcel VAL_LONG_LONG_BINARY(cmp_long); 678161537Smarcel 679161537Smarcel VAL_BYTE_UNARY(daa_byte); 680161537Smarcel VAL_BYTE_UNARY(das_byte); /* Fails for 0x9A (out of range anyway) */ 681161537Smarcel 682161537Smarcel VAL_BYTE_UNARY(dec_byte); 683161537Smarcel VAL_WORD_UNARY(dec_word); 684161537Smarcel VAL_LONG_UNARY(dec_long); 685161537Smarcel 686161537Smarcel VAL_BYTE_UNARY(inc_byte); 687161537Smarcel VAL_WORD_UNARY(inc_word); 688161537Smarcel VAL_LONG_UNARY(inc_long); 689161537Smarcel 690161537Smarcel VAL_BYTE_BYTE_BINARY(or_byte); 691161537Smarcel VAL_WORD_WORD_BINARY(or_word); 692161537Smarcel VAL_LONG_LONG_BINARY(or_long); 693161537Smarcel 694161537Smarcel VAL_BYTE_UNARY(neg_byte); 695161537Smarcel VAL_WORD_UNARY(neg_word); 696161537Smarcel VAL_LONG_UNARY(neg_long); 697161537Smarcel 698161537Smarcel VAL_BYTE_UNARY(not_byte); 699161537Smarcel VAL_WORD_UNARY(not_word); 700161537Smarcel VAL_LONG_UNARY(not_long); 701161537Smarcel 702161537Smarcel VAL_BYTE_ROTATE(rcl_byte); 703161537Smarcel VAL_WORD_ROTATE(rcl_word); 704161537Smarcel VAL_LONG_ROTATE(rcl_long); 705161537Smarcel 706161537Smarcel VAL_BYTE_ROTATE(rcr_byte); 707161537Smarcel VAL_WORD_ROTATE(rcr_word); 708161537Smarcel VAL_LONG_ROTATE(rcr_long); 709161537Smarcel 710161537Smarcel VAL_BYTE_ROTATE(rol_byte); 711161537Smarcel VAL_WORD_ROTATE(rol_word); 712161537Smarcel VAL_LONG_ROTATE(rol_long); 713161537Smarcel 714161537Smarcel VAL_BYTE_ROTATE(ror_byte); 715161537Smarcel VAL_WORD_ROTATE(ror_word); 716161537Smarcel VAL_LONG_ROTATE(ror_long); 717161537Smarcel 718161537Smarcel VAL_BYTE_ROTATE(shl_byte); 719161537Smarcel VAL_WORD_ROTATE(shl_word); 720161537Smarcel VAL_LONG_ROTATE(shl_long); 721161537Smarcel 722161537Smarcel VAL_BYTE_ROTATE(shr_byte); 723161537Smarcel VAL_WORD_ROTATE(shr_word); 724161537Smarcel VAL_LONG_ROTATE(shr_long); 725161537Smarcel 726161537Smarcel VAL_BYTE_ROTATE(sar_byte); 727161537Smarcel VAL_WORD_ROTATE(sar_word); 728161537Smarcel VAL_LONG_ROTATE(sar_long); 729161537Smarcel 730161537Smarcel VAL_WORD_ROTATE_DBL(shld_word); 731161537Smarcel VAL_LONG_ROTATE_DBL(shld_long); 732161537Smarcel 733161537Smarcel VAL_WORD_ROTATE_DBL(shrd_word); 734161537Smarcel VAL_LONG_ROTATE_DBL(shrd_long); 735161537Smarcel 736161537Smarcel VAL_BYTE_BYTE_BINARY(sbb_byte); 737161537Smarcel VAL_WORD_WORD_BINARY(sbb_word); 738161537Smarcel VAL_LONG_LONG_BINARY(sbb_long); 739161537Smarcel 740161537Smarcel VAL_BYTE_BYTE_BINARY(sub_byte); 741161537Smarcel VAL_WORD_WORD_BINARY(sub_word); 742161537Smarcel VAL_LONG_LONG_BINARY(sub_long); 743161537Smarcel 744161537Smarcel VAL_BYTE_BYTE_BINARY(xor_byte); 745161537Smarcel VAL_WORD_WORD_BINARY(xor_word); 746161537Smarcel VAL_LONG_LONG_BINARY(xor_long); 747161537Smarcel 748161537Smarcel VAL_VOID_BYTE_BINARY(test_byte); 749161537Smarcel VAL_VOID_WORD_BINARY(test_word); 750161537Smarcel VAL_VOID_LONG_BINARY(test_long); 751161537Smarcel 752161537Smarcel VAL_BYTE_MUL(imul_byte); 753161537Smarcel VAL_WORD_MUL(imul_word); 754161537Smarcel VAL_LONG_MUL(imul_long); 755161537Smarcel 756161537Smarcel VAL_BYTE_MUL(mul_byte); 757161537Smarcel VAL_WORD_MUL(mul_word); 758161537Smarcel VAL_LONG_MUL(mul_long); 759161537Smarcel 760161537Smarcel VAL_BYTE_DIV(idiv_byte); 761161537Smarcel VAL_WORD_DIV(idiv_word); 762161537Smarcel VAL_LONG_DIV(idiv_long); 763161537Smarcel 764161537Smarcel VAL_BYTE_DIV(div_byte); 765161537Smarcel VAL_WORD_DIV(div_word); 766161537Smarcel VAL_LONG_DIV(div_long); 767161537Smarcel 768161537Smarcel return 0; 769161537Smarcel} 770161537Smarcel