1706f2543Smrg/**************************************************************************** 2706f2543Smrg* 3706f2543Smrg* Realmode X86 Emulator Library 4706f2543Smrg* 5706f2543Smrg* Copyright (C) 1996-1999 SciTech Software, Inc. 6706f2543Smrg* Copyright (C) David Mosberger-Tang 7706f2543Smrg* Copyright (C) 1999 Egbert Eich 8706f2543Smrg* 9706f2543Smrg* ======================================================================== 10706f2543Smrg* 11706f2543Smrg* Permission to use, copy, modify, distribute, and sell this software and 12706f2543Smrg* its documentation for any purpose is hereby granted without fee, 13706f2543Smrg* provided that the above copyright notice appear in all copies and that 14706f2543Smrg* both that copyright notice and this permission notice appear in 15706f2543Smrg* supporting documentation, and that the name of the authors not be used 16706f2543Smrg* in advertising or publicity pertaining to distribution of the software 17706f2543Smrg* without specific, written prior permission. The authors makes no 18706f2543Smrg* representations about the suitability of this software for any purpose. 19706f2543Smrg* It is provided "as is" without express or implied warranty. 20706f2543Smrg* 21706f2543Smrg* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22706f2543Smrg* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23706f2543Smrg* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24706f2543Smrg* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25706f2543Smrg* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26706f2543Smrg* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27706f2543Smrg* PERFORMANCE OF THIS SOFTWARE. 28706f2543Smrg* 29706f2543Smrg* ======================================================================== 30706f2543Smrg* 31706f2543Smrg* Language: Watcom C 10.6 or later 32706f2543Smrg* Environment: 32-bit DOS 33706f2543Smrg* Developer: Kendall Bennett 34706f2543Smrg* 35706f2543Smrg* Description: Program to validate the x86 emulator library for 36706f2543Smrg* correctness. We run the emulator primitive operations 37706f2543Smrg* functions against the real x86 CPU, and compare the result 38706f2543Smrg* and flags to ensure correctness. 39706f2543Smrg* 40706f2543Smrg* We use inline assembler to compile and build this program. 41706f2543Smrg* 42706f2543Smrg****************************************************************************/ 43706f2543Smrg 44706f2543Smrg#include <stdio.h> 45706f2543Smrg#include <stdlib.h> 46706f2543Smrg#include <string.h> 47706f2543Smrg#include <stdarg.h> 48706f2543Smrg#include "x86emu.h" 49706f2543Smrg#include "x86emu/prim_asm.h" 50706f2543Smrg 51706f2543Smrg/*-------------------------- Implementation -------------------------------*/ 52706f2543Smrg 53706f2543Smrg#define true 1 54706f2543Smrg#define false 0 55706f2543Smrg 56706f2543Smrg#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF) 57706f2543Smrg 58706f2543Smrg#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \ 59706f2543Smrg{ \ 60706f2543Smrg parm_type d,s; \ 61706f2543Smrg res_type r,r_asm; \ 62706f2543Smrg ulong flags,inflags; \ 63706f2543Smrg int f,failed = false; \ 64706f2543Smrg char buf1[80],buf2[80]; \ 65706f2543Smrg for (d = 0; d < dmax; d += dincr) { \ 66706f2543Smrg for (s = 0; s < smax; s += sincr) { \ 67706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 68706f2543Smrg for (f = 0; f < 2; f++) { 69706f2543Smrg 70706f2543Smrg#define VAL_TEST_BINARY(name) \ 71706f2543Smrg r_asm = name##_asm(&flags,d,s); \ 72706f2543Smrg r = name(d,s); \ 73706f2543Smrg if (r != r_asm || M.x86.R_EFLG != flags) \ 74706f2543Smrg failed = true; \ 75706f2543Smrg if (failed || trace) { 76706f2543Smrg 77706f2543Smrg#define VAL_TEST_BINARY_VOID(name) \ 78706f2543Smrg name##_asm(&flags,d,s); \ 79706f2543Smrg name(d,s); \ 80706f2543Smrg r = r_asm = 0; \ 81706f2543Smrg if (M.x86.R_EFLG != flags) \ 82706f2543Smrg failed = true; \ 83706f2543Smrg if (failed || trace) { 84706f2543Smrg 85706f2543Smrg#define VAL_FAIL_BYTE_BYTE_BINARY(name) \ 86706f2543Smrg if (failed) \ 87706f2543Smrg printk("fail\n"); \ 88706f2543Smrg printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 89706f2543Smrg r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 90706f2543Smrg printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 91706f2543Smrg r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); 92706f2543Smrg 93706f2543Smrg#define VAL_FAIL_WORD_WORD_BINARY(name) \ 94706f2543Smrg if (failed) \ 95706f2543Smrg printk("fail\n"); \ 96706f2543Smrg printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 97706f2543Smrg r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 98706f2543Smrg printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 99706f2543Smrg r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); 100706f2543Smrg 101706f2543Smrg#define VAL_FAIL_LONG_LONG_BINARY(name) \ 102706f2543Smrg if (failed) \ 103706f2543Smrg printk("fail\n"); \ 104706f2543Smrg printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 105706f2543Smrg r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 106706f2543Smrg printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 107706f2543Smrg r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); 108706f2543Smrg 109706f2543Smrg#define VAL_END_BINARY() \ 110706f2543Smrg } \ 111706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 112706f2543Smrg if (failed) \ 113706f2543Smrg break; \ 114706f2543Smrg } \ 115706f2543Smrg if (failed) \ 116706f2543Smrg break; \ 117706f2543Smrg } \ 118706f2543Smrg if (failed) \ 119706f2543Smrg break; \ 120706f2543Smrg } \ 121706f2543Smrg if (!failed) \ 122706f2543Smrg printk("passed\n"); \ 123706f2543Smrg} 124706f2543Smrg 125706f2543Smrg#define VAL_BYTE_BYTE_BINARY(name) \ 126706f2543Smrg printk("Validating %s ... ", #name); \ 127706f2543Smrg VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ 128706f2543Smrg VAL_TEST_BINARY(name) \ 129706f2543Smrg VAL_FAIL_BYTE_BYTE_BINARY(name) \ 130706f2543Smrg VAL_END_BINARY() 131706f2543Smrg 132706f2543Smrg#define VAL_WORD_WORD_BINARY(name) \ 133706f2543Smrg printk("Validating %s ... ", #name); \ 134706f2543Smrg VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ 135706f2543Smrg VAL_TEST_BINARY(name) \ 136706f2543Smrg VAL_FAIL_WORD_WORD_BINARY(name) \ 137706f2543Smrg VAL_END_BINARY() 138706f2543Smrg 139706f2543Smrg#define VAL_LONG_LONG_BINARY(name) \ 140706f2543Smrg printk("Validating %s ... ", #name); \ 141706f2543Smrg VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ 142706f2543Smrg VAL_TEST_BINARY(name) \ 143706f2543Smrg VAL_FAIL_LONG_LONG_BINARY(name) \ 144706f2543Smrg VAL_END_BINARY() 145706f2543Smrg 146706f2543Smrg#define VAL_VOID_BYTE_BINARY(name) \ 147706f2543Smrg printk("Validating %s ... ", #name); \ 148706f2543Smrg VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ 149706f2543Smrg VAL_TEST_BINARY_VOID(name) \ 150706f2543Smrg VAL_FAIL_BYTE_BYTE_BINARY(name) \ 151706f2543Smrg VAL_END_BINARY() 152706f2543Smrg 153706f2543Smrg#define VAL_VOID_WORD_BINARY(name) \ 154706f2543Smrg printk("Validating %s ... ", #name); \ 155706f2543Smrg VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ 156706f2543Smrg VAL_TEST_BINARY_VOID(name) \ 157706f2543Smrg VAL_FAIL_WORD_WORD_BINARY(name) \ 158706f2543Smrg VAL_END_BINARY() 159706f2543Smrg 160706f2543Smrg#define VAL_VOID_LONG_BINARY(name) \ 161706f2543Smrg printk("Validating %s ... ", #name); \ 162706f2543Smrg VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ 163706f2543Smrg VAL_TEST_BINARY_VOID(name) \ 164706f2543Smrg VAL_FAIL_LONG_LONG_BINARY(name) \ 165706f2543Smrg VAL_END_BINARY() 166706f2543Smrg 167706f2543Smrg#define VAL_BYTE_ROTATE(name) \ 168706f2543Smrg printk("Validating %s ... ", #name); \ 169706f2543Smrg VAL_START_BINARY(u8,u8,0xFF,8,1,1) \ 170706f2543Smrg VAL_TEST_BINARY(name) \ 171706f2543Smrg VAL_FAIL_BYTE_BYTE_BINARY(name) \ 172706f2543Smrg VAL_END_BINARY() 173706f2543Smrg 174706f2543Smrg#define VAL_WORD_ROTATE(name) \ 175706f2543Smrg printk("Validating %s ... ", #name); \ 176706f2543Smrg VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \ 177706f2543Smrg VAL_TEST_BINARY(name) \ 178706f2543Smrg VAL_FAIL_WORD_WORD_BINARY(name) \ 179706f2543Smrg VAL_END_BINARY() 180706f2543Smrg 181706f2543Smrg#define VAL_LONG_ROTATE(name) \ 182706f2543Smrg printk("Validating %s ... ", #name); \ 183706f2543Smrg VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \ 184706f2543Smrg VAL_TEST_BINARY(name) \ 185706f2543Smrg VAL_FAIL_LONG_LONG_BINARY(name) \ 186706f2543Smrg VAL_END_BINARY() 187706f2543Smrg 188706f2543Smrg#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\ 189706f2543Smrg{ \ 190706f2543Smrg parm_type d,s; \ 191706f2543Smrg res_type r,r_asm; \ 192706f2543Smrg u8 shift; \ 193706f2543Smrg u32 flags,inflags; \ 194706f2543Smrg int f,failed = false; \ 195706f2543Smrg char buf1[80],buf2[80]; \ 196706f2543Smrg for (d = 0; d < dmax; d += dincr) { \ 197706f2543Smrg for (s = 0; s < smax; s += sincr) { \ 198706f2543Smrg for (shift = 0; shift < maxshift; shift += 1) { \ 199706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 200706f2543Smrg for (f = 0; f < 2; f++) { 201706f2543Smrg 202706f2543Smrg#define VAL_TEST_TERNARY(name) \ 203706f2543Smrg r_asm = name##_asm(&flags,d,s,shift); \ 204706f2543Smrg r = name(d,s,shift); \ 205706f2543Smrg if (r != r_asm || M.x86.R_EFLG != flags) \ 206706f2543Smrg failed = true; \ 207706f2543Smrg if (failed || trace) { 208706f2543Smrg 209706f2543Smrg#define VAL_FAIL_WORD_WORD_TERNARY(name) \ 210706f2543Smrg if (failed) \ 211706f2543Smrg printk("fail\n"); \ 212706f2543Smrg printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ 213706f2543Smrg r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 214706f2543Smrg printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ 215706f2543Smrg r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); 216706f2543Smrg 217706f2543Smrg#define VAL_FAIL_LONG_LONG_TERNARY(name) \ 218706f2543Smrg if (failed) \ 219706f2543Smrg printk("fail\n"); \ 220706f2543Smrg printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ 221706f2543Smrg r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 222706f2543Smrg printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ 223706f2543Smrg r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); 224706f2543Smrg 225706f2543Smrg#define VAL_END_TERNARY() \ 226706f2543Smrg } \ 227706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 228706f2543Smrg if (failed) \ 229706f2543Smrg break; \ 230706f2543Smrg } \ 231706f2543Smrg if (failed) \ 232706f2543Smrg break; \ 233706f2543Smrg } \ 234706f2543Smrg if (failed) \ 235706f2543Smrg break; \ 236706f2543Smrg } \ 237706f2543Smrg if (failed) \ 238706f2543Smrg break; \ 239706f2543Smrg } \ 240706f2543Smrg if (!failed) \ 241706f2543Smrg printk("passed\n"); \ 242706f2543Smrg} 243706f2543Smrg 244706f2543Smrg#define VAL_WORD_ROTATE_DBL(name) \ 245706f2543Smrg printk("Validating %s ... ", #name); \ 246706f2543Smrg VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \ 247706f2543Smrg VAL_TEST_TERNARY(name) \ 248706f2543Smrg VAL_FAIL_WORD_WORD_TERNARY(name) \ 249706f2543Smrg VAL_END_TERNARY() 250706f2543Smrg 251706f2543Smrg#define VAL_LONG_ROTATE_DBL(name) \ 252706f2543Smrg printk("Validating %s ... ", #name); \ 253706f2543Smrg VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \ 254706f2543Smrg VAL_TEST_TERNARY(name) \ 255706f2543Smrg VAL_FAIL_LONG_LONG_TERNARY(name) \ 256706f2543Smrg VAL_END_TERNARY() 257706f2543Smrg 258706f2543Smrg#define VAL_START_UNARY(parm_type,max,incr) \ 259706f2543Smrg{ \ 260706f2543Smrg parm_type d,r,r_asm; \ 261706f2543Smrg u32 flags,inflags; \ 262706f2543Smrg int f,failed = false; \ 263706f2543Smrg char buf1[80],buf2[80]; \ 264706f2543Smrg for (d = 0; d < max; d += incr) { \ 265706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 266706f2543Smrg for (f = 0; f < 2; f++) { 267706f2543Smrg 268706f2543Smrg#define VAL_TEST_UNARY(name) \ 269706f2543Smrg r_asm = name##_asm(&flags,d); \ 270706f2543Smrg r = name(d); \ 271706f2543Smrg if (r != r_asm || M.x86.R_EFLG != flags) { \ 272706f2543Smrg failed = true; 273706f2543Smrg 274706f2543Smrg#define VAL_FAIL_BYTE_UNARY(name) \ 275706f2543Smrg printk("fail\n"); \ 276706f2543Smrg printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ 277706f2543Smrg r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 278706f2543Smrg printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ 279706f2543Smrg r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); 280706f2543Smrg 281706f2543Smrg#define VAL_FAIL_WORD_UNARY(name) \ 282706f2543Smrg printk("fail\n"); \ 283706f2543Smrg printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ 284706f2543Smrg r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 285706f2543Smrg printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ 286706f2543Smrg r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); 287706f2543Smrg 288706f2543Smrg#define VAL_FAIL_LONG_UNARY(name) \ 289706f2543Smrg printk("fail\n"); \ 290706f2543Smrg printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ 291706f2543Smrg r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 292706f2543Smrg printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ 293706f2543Smrg r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); 294706f2543Smrg 295706f2543Smrg#define VAL_END_UNARY() \ 296706f2543Smrg } \ 297706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \ 298706f2543Smrg if (failed) \ 299706f2543Smrg break; \ 300706f2543Smrg } \ 301706f2543Smrg if (failed) \ 302706f2543Smrg break; \ 303706f2543Smrg } \ 304706f2543Smrg if (!failed) \ 305706f2543Smrg printk("passed\n"); \ 306706f2543Smrg} 307706f2543Smrg 308706f2543Smrg#define VAL_BYTE_UNARY(name) \ 309706f2543Smrg printk("Validating %s ... ", #name); \ 310706f2543Smrg VAL_START_UNARY(u8,0xFF,0x1) \ 311706f2543Smrg VAL_TEST_UNARY(name) \ 312706f2543Smrg VAL_FAIL_BYTE_UNARY(name) \ 313706f2543Smrg VAL_END_UNARY() 314706f2543Smrg 315706f2543Smrg#define VAL_WORD_UNARY(name) \ 316706f2543Smrg printk("Validating %s ... ", #name); \ 317706f2543Smrg VAL_START_UNARY(u16,0xFF00,0x100) \ 318706f2543Smrg VAL_TEST_UNARY(name) \ 319706f2543Smrg VAL_FAIL_WORD_UNARY(name) \ 320706f2543Smrg VAL_END_UNARY() 321706f2543Smrg 322706f2543Smrg#define VAL_WORD_BYTE_UNARY(name) \ 323706f2543Smrg printk("Validating %s ... ", #name); \ 324706f2543Smrg VAL_START_UNARY(u16,0xFF,0x1) \ 325706f2543Smrg VAL_TEST_UNARY(name) \ 326706f2543Smrg VAL_FAIL_WORD_UNARY(name) \ 327706f2543Smrg VAL_END_UNARY() 328706f2543Smrg 329706f2543Smrg#define VAL_LONG_UNARY(name) \ 330706f2543Smrg printk("Validating %s ... ", #name); \ 331706f2543Smrg VAL_START_UNARY(u32,0xFF000000,0x1000000) \ 332706f2543Smrg VAL_TEST_UNARY(name) \ 333706f2543Smrg VAL_FAIL_LONG_UNARY(name) \ 334706f2543Smrg VAL_END_UNARY() 335706f2543Smrg 336706f2543Smrg#define VAL_BYTE_MUL(name) \ 337706f2543Smrg printk("Validating %s ... ", #name); \ 338706f2543Smrg{ \ 339706f2543Smrg u8 d,s; \ 340706f2543Smrg u16 r,r_asm; \ 341706f2543Smrg u32 flags,inflags; \ 342706f2543Smrg int f,failed = false; \ 343706f2543Smrg char buf1[80],buf2[80]; \ 344706f2543Smrg for (d = 0; d < 0xFF; d += 1) { \ 345706f2543Smrg for (s = 0; s < 0xFF; s += 1) { \ 346706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 347706f2543Smrg for (f = 0; f < 2; f++) { \ 348706f2543Smrg name##_asm(&flags,&r_asm,d,s); \ 349706f2543Smrg M.x86.R_AL = d; \ 350706f2543Smrg name(s); \ 351706f2543Smrg r = M.x86.R_AX; \ 352706f2543Smrg if (r != r_asm || M.x86.R_EFLG != flags) \ 353706f2543Smrg failed = true; \ 354706f2543Smrg if (failed || trace) { \ 355706f2543Smrg if (failed) \ 356706f2543Smrg printk("fail\n"); \ 357706f2543Smrg printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 358706f2543Smrg r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 359706f2543Smrg printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ 360706f2543Smrg r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 361706f2543Smrg } \ 362706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 363706f2543Smrg if (failed) \ 364706f2543Smrg break; \ 365706f2543Smrg } \ 366706f2543Smrg if (failed) \ 367706f2543Smrg break; \ 368706f2543Smrg } \ 369706f2543Smrg if (failed) \ 370706f2543Smrg break; \ 371706f2543Smrg } \ 372706f2543Smrg if (!failed) \ 373706f2543Smrg printk("passed\n"); \ 374706f2543Smrg} 375706f2543Smrg 376706f2543Smrg#define VAL_WORD_MUL(name) \ 377706f2543Smrg printk("Validating %s ... ", #name); \ 378706f2543Smrg{ \ 379706f2543Smrg u16 d,s; \ 380706f2543Smrg u16 r_lo,r_asm_lo; \ 381706f2543Smrg u16 r_hi,r_asm_hi; \ 382706f2543Smrg u32 flags,inflags; \ 383706f2543Smrg int f,failed = false; \ 384706f2543Smrg char buf1[80],buf2[80]; \ 385706f2543Smrg for (d = 0; d < 0xFF00; d += 0x100) { \ 386706f2543Smrg for (s = 0; s < 0xFF00; s += 0x100) { \ 387706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 388706f2543Smrg for (f = 0; f < 2; f++) { \ 389706f2543Smrg name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ 390706f2543Smrg M.x86.R_AX = d; \ 391706f2543Smrg name(s); \ 392706f2543Smrg r_lo = M.x86.R_AX; \ 393706f2543Smrg r_hi = M.x86.R_DX; \ 394706f2543Smrg if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ 395706f2543Smrg failed = true; \ 396706f2543Smrg if (failed || trace) { \ 397706f2543Smrg if (failed) \ 398706f2543Smrg printk("fail\n"); \ 399706f2543Smrg printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 400706f2543Smrg r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 401706f2543Smrg printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ 402706f2543Smrg r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 403706f2543Smrg } \ 404706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 405706f2543Smrg if (failed) \ 406706f2543Smrg break; \ 407706f2543Smrg } \ 408706f2543Smrg if (failed) \ 409706f2543Smrg break; \ 410706f2543Smrg } \ 411706f2543Smrg if (failed) \ 412706f2543Smrg break; \ 413706f2543Smrg } \ 414706f2543Smrg if (!failed) \ 415706f2543Smrg printk("passed\n"); \ 416706f2543Smrg} 417706f2543Smrg 418706f2543Smrg#define VAL_LONG_MUL(name) \ 419706f2543Smrg printk("Validating %s ... ", #name); \ 420706f2543Smrg{ \ 421706f2543Smrg u32 d,s; \ 422706f2543Smrg u32 r_lo,r_asm_lo; \ 423706f2543Smrg u32 r_hi,r_asm_hi; \ 424706f2543Smrg u32 flags,inflags; \ 425706f2543Smrg int f,failed = false; \ 426706f2543Smrg char buf1[80],buf2[80]; \ 427706f2543Smrg for (d = 0; d < 0xFF000000; d += 0x1000000) { \ 428706f2543Smrg for (s = 0; s < 0xFF000000; s += 0x1000000) { \ 429706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 430706f2543Smrg for (f = 0; f < 2; f++) { \ 431706f2543Smrg name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ 432706f2543Smrg M.x86.R_EAX = d; \ 433706f2543Smrg name(s); \ 434706f2543Smrg r_lo = M.x86.R_EAX; \ 435706f2543Smrg r_hi = M.x86.R_EDX; \ 436706f2543Smrg if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ 437706f2543Smrg failed = true; \ 438706f2543Smrg if (failed || trace) { \ 439706f2543Smrg if (failed) \ 440706f2543Smrg printk("fail\n"); \ 441706f2543Smrg printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 442706f2543Smrg r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 443706f2543Smrg printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ 444706f2543Smrg r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 445706f2543Smrg } \ 446706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 447706f2543Smrg if (failed) \ 448706f2543Smrg break; \ 449706f2543Smrg } \ 450706f2543Smrg if (failed) \ 451706f2543Smrg break; \ 452706f2543Smrg } \ 453706f2543Smrg if (failed) \ 454706f2543Smrg break; \ 455706f2543Smrg } \ 456706f2543Smrg if (!failed) \ 457706f2543Smrg printk("passed\n"); \ 458706f2543Smrg} 459706f2543Smrg 460706f2543Smrg#define VAL_BYTE_DIV(name) \ 461706f2543Smrg printk("Validating %s ... ", #name); \ 462706f2543Smrg{ \ 463706f2543Smrg u16 d,s; \ 464706f2543Smrg u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \ 465706f2543Smrg u32 flags,inflags; \ 466706f2543Smrg int f,failed = false; \ 467706f2543Smrg char buf1[80],buf2[80]; \ 468706f2543Smrg for (d = 0; d < 0xFF00; d += 0x100) { \ 469706f2543Smrg for (s = 1; s < 0xFF; s += 1) { \ 470706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 471706f2543Smrg for (f = 0; f < 2; f++) { \ 472706f2543Smrg M.x86.intr = 0; \ 473706f2543Smrg M.x86.R_AX = d; \ 474706f2543Smrg name(s); \ 475706f2543Smrg r_quot = M.x86.R_AL; \ 476706f2543Smrg r_rem = M.x86.R_AH; \ 477706f2543Smrg if (M.x86.intr & INTR_SYNCH) \ 478706f2543Smrg continue; \ 479706f2543Smrg name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \ 480706f2543Smrg if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ 481706f2543Smrg failed = true; \ 482706f2543Smrg if (failed || trace) { \ 483706f2543Smrg if (failed) \ 484706f2543Smrg printk("fail\n"); \ 485706f2543Smrg printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ 486706f2543Smrg r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 487706f2543Smrg printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ 488706f2543Smrg r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 489706f2543Smrg } \ 490706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 491706f2543Smrg if (failed) \ 492706f2543Smrg break; \ 493706f2543Smrg } \ 494706f2543Smrg if (failed) \ 495706f2543Smrg break; \ 496706f2543Smrg } \ 497706f2543Smrg if (failed) \ 498706f2543Smrg break; \ 499706f2543Smrg } \ 500706f2543Smrg if (!failed) \ 501706f2543Smrg printk("passed\n"); \ 502706f2543Smrg} 503706f2543Smrg 504706f2543Smrg#define VAL_WORD_DIV(name) \ 505706f2543Smrg printk("Validating %s ... ", #name); \ 506706f2543Smrg{ \ 507706f2543Smrg u32 d,s; \ 508706f2543Smrg u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \ 509706f2543Smrg u32 flags,inflags; \ 510706f2543Smrg int f,failed = false; \ 511706f2543Smrg char buf1[80],buf2[80]; \ 512706f2543Smrg for (d = 0; d < 0xFF000000; d += 0x1000000) { \ 513706f2543Smrg for (s = 0x100; s < 0xFF00; s += 0x100) { \ 514706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 515706f2543Smrg for (f = 0; f < 2; f++) { \ 516706f2543Smrg M.x86.intr = 0; \ 517706f2543Smrg M.x86.R_AX = d & 0xFFFF; \ 518706f2543Smrg M.x86.R_DX = d >> 16; \ 519706f2543Smrg name(s); \ 520706f2543Smrg r_quot = M.x86.R_AX; \ 521706f2543Smrg r_rem = M.x86.R_DX; \ 522706f2543Smrg if (M.x86.intr & INTR_SYNCH) \ 523706f2543Smrg continue; \ 524706f2543Smrg name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\ 525706f2543Smrg if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ 526706f2543Smrg failed = true; \ 527706f2543Smrg if (failed || trace) { \ 528706f2543Smrg if (failed) \ 529706f2543Smrg printk("fail\n"); \ 530706f2543Smrg printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ 531706f2543Smrg r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 532706f2543Smrg printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ 533706f2543Smrg r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 534706f2543Smrg } \ 535706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 536706f2543Smrg if (failed) \ 537706f2543Smrg break; \ 538706f2543Smrg } \ 539706f2543Smrg if (failed) \ 540706f2543Smrg break; \ 541706f2543Smrg } \ 542706f2543Smrg if (failed) \ 543706f2543Smrg break; \ 544706f2543Smrg } \ 545706f2543Smrg if (!failed) \ 546706f2543Smrg printk("passed\n"); \ 547706f2543Smrg} 548706f2543Smrg 549706f2543Smrg#define VAL_LONG_DIV(name) \ 550706f2543Smrg printk("Validating %s ... ", #name); \ 551706f2543Smrg{ \ 552706f2543Smrg u32 d,s; \ 553706f2543Smrg u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \ 554706f2543Smrg u32 flags,inflags; \ 555706f2543Smrg int f,failed = false; \ 556706f2543Smrg char buf1[80],buf2[80]; \ 557706f2543Smrg for (d = 0; d < 0xFF000000; d += 0x1000000) { \ 558706f2543Smrg for (s = 0x100; s < 0xFF00; s += 0x100) { \ 559706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags; \ 560706f2543Smrg for (f = 0; f < 2; f++) { \ 561706f2543Smrg M.x86.intr = 0; \ 562706f2543Smrg M.x86.R_EAX = d; \ 563706f2543Smrg M.x86.R_EDX = 0; \ 564706f2543Smrg name(s); \ 565706f2543Smrg r_quot = M.x86.R_EAX; \ 566706f2543Smrg r_rem = M.x86.R_EDX; \ 567706f2543Smrg if (M.x86.intr & INTR_SYNCH) \ 568706f2543Smrg continue; \ 569706f2543Smrg name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \ 570706f2543Smrg if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ 571706f2543Smrg failed = true; \ 572706f2543Smrg if (failed || trace) { \ 573706f2543Smrg if (failed) \ 574706f2543Smrg printk("fail\n"); \ 575706f2543Smrg printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ 576706f2543Smrg r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ 577706f2543Smrg printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ 578706f2543Smrg r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ 579706f2543Smrg } \ 580706f2543Smrg M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ 581706f2543Smrg if (failed) \ 582706f2543Smrg break; \ 583706f2543Smrg } \ 584706f2543Smrg if (failed) \ 585706f2543Smrg break; \ 586706f2543Smrg } \ 587706f2543Smrg if (failed) \ 588706f2543Smrg break; \ 589706f2543Smrg } \ 590706f2543Smrg if (!failed) \ 591706f2543Smrg printk("passed\n"); \ 592706f2543Smrg} 593706f2543Smrg 594706f2543Smrgvoid printk(const char *fmt, ...) 595706f2543Smrg{ 596706f2543Smrg va_list argptr; 597706f2543Smrg va_start(argptr, fmt); 598706f2543Smrg vfprintf(stdout, fmt, argptr); 599706f2543Smrg fflush(stdout); 600706f2543Smrg va_end(argptr); 601706f2543Smrg} 602706f2543Smrg 603706f2543Smrgchar * print_flags(char *buf,ulong flags) 604706f2543Smrg{ 605706f2543Smrg char *separator = ""; 606706f2543Smrg 607706f2543Smrg buf[0] = 0; 608706f2543Smrg if (flags & F_CF) { 609706f2543Smrg strcat(buf,separator); 610706f2543Smrg strcat(buf,"CF"); 611706f2543Smrg separator = ","; 612706f2543Smrg } 613706f2543Smrg if (flags & F_PF) { 614706f2543Smrg strcat(buf,separator); 615706f2543Smrg strcat(buf,"PF"); 616706f2543Smrg separator = ","; 617706f2543Smrg } 618706f2543Smrg if (flags & F_AF) { 619706f2543Smrg strcat(buf,separator); 620706f2543Smrg strcat(buf,"AF"); 621706f2543Smrg separator = ","; 622706f2543Smrg } 623706f2543Smrg if (flags & F_ZF) { 624706f2543Smrg strcat(buf,separator); 625706f2543Smrg strcat(buf,"ZF"); 626706f2543Smrg separator = ","; 627706f2543Smrg } 628706f2543Smrg if (flags & F_SF) { 629706f2543Smrg strcat(buf,separator); 630706f2543Smrg strcat(buf,"SF"); 631706f2543Smrg separator = ","; 632706f2543Smrg } 633706f2543Smrg if (flags & F_OF) { 634706f2543Smrg strcat(buf,separator); 635706f2543Smrg strcat(buf,"OF"); 636706f2543Smrg separator = ","; 637706f2543Smrg } 638706f2543Smrg if (separator[0] == 0) 639706f2543Smrg strcpy(buf,"None"); 640706f2543Smrg return buf; 641706f2543Smrg} 642706f2543Smrg 643706f2543Smrgint main(int argc) 644706f2543Smrg{ 645706f2543Smrg ulong def_flags; 646706f2543Smrg int trace = false; 647706f2543Smrg 648706f2543Smrg if (argc > 1) 649706f2543Smrg trace = true; 650706f2543Smrg memset(&M, 0, sizeof(M)); 651706f2543Smrg def_flags = get_flags_asm() & ~ALL_FLAGS; 652706f2543Smrg 653706f2543Smrg VAL_WORD_UNARY(aaa_word); 654706f2543Smrg VAL_WORD_UNARY(aas_word); 655706f2543Smrg 656706f2543Smrg VAL_WORD_UNARY(aad_word); 657706f2543Smrg VAL_WORD_UNARY(aam_word); 658706f2543Smrg 659706f2543Smrg VAL_BYTE_BYTE_BINARY(adc_byte); 660706f2543Smrg VAL_WORD_WORD_BINARY(adc_word); 661706f2543Smrg VAL_LONG_LONG_BINARY(adc_long); 662706f2543Smrg 663706f2543Smrg VAL_BYTE_BYTE_BINARY(add_byte); 664706f2543Smrg VAL_WORD_WORD_BINARY(add_word); 665706f2543Smrg VAL_LONG_LONG_BINARY(add_long); 666706f2543Smrg 667706f2543Smrg VAL_BYTE_BYTE_BINARY(and_byte); 668706f2543Smrg VAL_WORD_WORD_BINARY(and_word); 669706f2543Smrg VAL_LONG_LONG_BINARY(and_long); 670706f2543Smrg 671706f2543Smrg VAL_BYTE_BYTE_BINARY(cmp_byte); 672706f2543Smrg VAL_WORD_WORD_BINARY(cmp_word); 673706f2543Smrg VAL_LONG_LONG_BINARY(cmp_long); 674706f2543Smrg 675706f2543Smrg VAL_BYTE_UNARY(daa_byte); 676706f2543Smrg VAL_BYTE_UNARY(das_byte); /* Fails for 0x9A (out of range anyway) */ 677706f2543Smrg 678706f2543Smrg VAL_BYTE_UNARY(dec_byte); 679706f2543Smrg VAL_WORD_UNARY(dec_word); 680706f2543Smrg VAL_LONG_UNARY(dec_long); 681706f2543Smrg 682706f2543Smrg VAL_BYTE_UNARY(inc_byte); 683706f2543Smrg VAL_WORD_UNARY(inc_word); 684706f2543Smrg VAL_LONG_UNARY(inc_long); 685706f2543Smrg 686706f2543Smrg VAL_BYTE_BYTE_BINARY(or_byte); 687706f2543Smrg VAL_WORD_WORD_BINARY(or_word); 688706f2543Smrg VAL_LONG_LONG_BINARY(or_long); 689706f2543Smrg 690706f2543Smrg VAL_BYTE_UNARY(neg_byte); 691706f2543Smrg VAL_WORD_UNARY(neg_word); 692706f2543Smrg VAL_LONG_UNARY(neg_long); 693706f2543Smrg 694706f2543Smrg VAL_BYTE_UNARY(not_byte); 695706f2543Smrg VAL_WORD_UNARY(not_word); 696706f2543Smrg VAL_LONG_UNARY(not_long); 697706f2543Smrg 698706f2543Smrg VAL_BYTE_ROTATE(rcl_byte); 699706f2543Smrg VAL_WORD_ROTATE(rcl_word); 700706f2543Smrg VAL_LONG_ROTATE(rcl_long); 701706f2543Smrg 702706f2543Smrg VAL_BYTE_ROTATE(rcr_byte); 703706f2543Smrg VAL_WORD_ROTATE(rcr_word); 704706f2543Smrg VAL_LONG_ROTATE(rcr_long); 705706f2543Smrg 706706f2543Smrg VAL_BYTE_ROTATE(rol_byte); 707706f2543Smrg VAL_WORD_ROTATE(rol_word); 708706f2543Smrg VAL_LONG_ROTATE(rol_long); 709706f2543Smrg 710706f2543Smrg VAL_BYTE_ROTATE(ror_byte); 711706f2543Smrg VAL_WORD_ROTATE(ror_word); 712706f2543Smrg VAL_LONG_ROTATE(ror_long); 713706f2543Smrg 714706f2543Smrg VAL_BYTE_ROTATE(shl_byte); 715706f2543Smrg VAL_WORD_ROTATE(shl_word); 716706f2543Smrg VAL_LONG_ROTATE(shl_long); 717706f2543Smrg 718706f2543Smrg VAL_BYTE_ROTATE(shr_byte); 719706f2543Smrg VAL_WORD_ROTATE(shr_word); 720706f2543Smrg VAL_LONG_ROTATE(shr_long); 721706f2543Smrg 722706f2543Smrg VAL_BYTE_ROTATE(sar_byte); 723706f2543Smrg VAL_WORD_ROTATE(sar_word); 724706f2543Smrg VAL_LONG_ROTATE(sar_long); 725706f2543Smrg 726706f2543Smrg VAL_WORD_ROTATE_DBL(shld_word); 727706f2543Smrg VAL_LONG_ROTATE_DBL(shld_long); 728706f2543Smrg 729706f2543Smrg VAL_WORD_ROTATE_DBL(shrd_word); 730706f2543Smrg VAL_LONG_ROTATE_DBL(shrd_long); 731706f2543Smrg 732706f2543Smrg VAL_BYTE_BYTE_BINARY(sbb_byte); 733706f2543Smrg VAL_WORD_WORD_BINARY(sbb_word); 734706f2543Smrg VAL_LONG_LONG_BINARY(sbb_long); 735706f2543Smrg 736706f2543Smrg VAL_BYTE_BYTE_BINARY(sub_byte); 737706f2543Smrg VAL_WORD_WORD_BINARY(sub_word); 738706f2543Smrg VAL_LONG_LONG_BINARY(sub_long); 739706f2543Smrg 740706f2543Smrg VAL_BYTE_BYTE_BINARY(xor_byte); 741706f2543Smrg VAL_WORD_WORD_BINARY(xor_word); 742706f2543Smrg VAL_LONG_LONG_BINARY(xor_long); 743706f2543Smrg 744706f2543Smrg VAL_VOID_BYTE_BINARY(test_byte); 745706f2543Smrg VAL_VOID_WORD_BINARY(test_word); 746706f2543Smrg VAL_VOID_LONG_BINARY(test_long); 747706f2543Smrg 748706f2543Smrg VAL_BYTE_MUL(imul_byte); 749706f2543Smrg VAL_WORD_MUL(imul_word); 750706f2543Smrg VAL_LONG_MUL(imul_long); 751706f2543Smrg 752706f2543Smrg VAL_BYTE_MUL(mul_byte); 753706f2543Smrg VAL_WORD_MUL(mul_word); 754706f2543Smrg VAL_LONG_MUL(mul_long); 755706f2543Smrg 756706f2543Smrg VAL_BYTE_DIV(idiv_byte); 757706f2543Smrg VAL_WORD_DIV(idiv_word); 758706f2543Smrg VAL_LONG_DIV(idiv_long); 759706f2543Smrg 760706f2543Smrg VAL_BYTE_DIV(div_byte); 761706f2543Smrg VAL_WORD_DIV(div_word); 762706f2543Smrg VAL_LONG_DIV(div_long); 763706f2543Smrg 764706f2543Smrg return 0; 765706f2543Smrg} 766