| /**************************************************************************** |
| * |
| * Realmode X86 Emulator Library |
| * |
| * Copyright (C) 1996-1999 SciTech Software, Inc. |
| * Copyright (C) David Mosberger-Tang |
| * Copyright (C) 1999 Egbert Eich |
| * |
| * ======================================================================== |
| * |
| * Permission to use, copy, modify, distribute, and sell this software and |
| * its documentation for any purpose is hereby granted without fee, |
| * provided that the above copyright notice appear in all copies and that |
| * both that copyright notice and this permission notice appear in |
| * supporting documentation, and that the name of the authors not be used |
| * in advertising or publicity pertaining to distribution of the software |
| * without specific, written prior permission. The authors makes no |
| * representations about the suitability of this software for any purpose. |
| * It is provided "as is" without express or implied warranty. |
| * |
| * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
| * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF |
| * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
| * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| * |
| * ======================================================================== |
| * |
| * Language: Watcom C 10.6 or later |
| * Environment: 32-bit DOS |
| * Developer: Kendall Bennett |
| * |
| * Description: Program to validate the x86 emulator library for |
| * correctness. We run the emulator primitive operations |
| * functions against the real x86 CPU, and compare the result |
| * and flags to ensure correctness. |
| * |
| * We use inline assembler to compile and build this program. |
| * |
| ****************************************************************************/ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdarg.h> |
| #include "x86emu.h" |
| #include "x86emu/prim_asm.h" |
| |
| /*-------------------------- Implementation -------------------------------*/ |
| |
| #define true 1 |
| #define false 0 |
| |
| #define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF) |
| |
| #define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \ |
| { \ |
| parm_type d,s; \ |
| res_type r,r_asm; \ |
| ulong flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < dmax; d += dincr) { \ |
| for (s = 0; s < smax; s += sincr) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { |
| |
| #define VAL_TEST_BINARY(name) \ |
| r_asm = name##_asm(&flags,d,s); \ |
| r = name(d,s); \ |
| if (r != r_asm || M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { |
| |
| #define VAL_TEST_BINARY_VOID(name) \ |
| name##_asm(&flags,d,s); \ |
| name(d,s); \ |
| r = r_asm = 0; \ |
| if (M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { |
| |
| #define VAL_FAIL_BYTE_BYTE_BINARY(name) \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ |
| r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_FAIL_WORD_WORD_BINARY(name) \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ |
| r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_FAIL_LONG_LONG_BINARY(name) \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ |
| r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_END_BINARY() \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_BYTE_BYTE_BINARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ |
| VAL_TEST_BINARY(name) \ |
| VAL_FAIL_BYTE_BYTE_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_WORD_WORD_BINARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ |
| VAL_TEST_BINARY(name) \ |
| VAL_FAIL_WORD_WORD_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_LONG_LONG_BINARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ |
| VAL_TEST_BINARY(name) \ |
| VAL_FAIL_LONG_LONG_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_VOID_BYTE_BINARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ |
| VAL_TEST_BINARY_VOID(name) \ |
| VAL_FAIL_BYTE_BYTE_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_VOID_WORD_BINARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ |
| VAL_TEST_BINARY_VOID(name) \ |
| VAL_FAIL_WORD_WORD_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_VOID_LONG_BINARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ |
| VAL_TEST_BINARY_VOID(name) \ |
| VAL_FAIL_LONG_LONG_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_BYTE_ROTATE(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u8,u8,0xFF,8,1,1) \ |
| VAL_TEST_BINARY(name) \ |
| VAL_FAIL_BYTE_BYTE_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_WORD_ROTATE(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \ |
| VAL_TEST_BINARY(name) \ |
| VAL_FAIL_WORD_WORD_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_LONG_ROTATE(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \ |
| VAL_TEST_BINARY(name) \ |
| VAL_FAIL_LONG_LONG_BINARY(name) \ |
| VAL_END_BINARY() |
| |
| #define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\ |
| { \ |
| parm_type d,s; \ |
| res_type r,r_asm; \ |
| u8 shift; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < dmax; d += dincr) { \ |
| for (s = 0; s < smax; s += sincr) { \ |
| for (shift = 0; shift < maxshift; shift += 1) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { |
| |
| #define VAL_TEST_TERNARY(name) \ |
| r_asm = name##_asm(&flags,d,s,shift); \ |
| r = name(d,s,shift); \ |
| if (r != r_asm || M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { |
| |
| #define VAL_FAIL_WORD_WORD_TERNARY(name) \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ |
| r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_FAIL_LONG_LONG_TERNARY(name) \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ |
| r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_END_TERNARY() \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_WORD_ROTATE_DBL(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \ |
| VAL_TEST_TERNARY(name) \ |
| VAL_FAIL_WORD_WORD_TERNARY(name) \ |
| VAL_END_TERNARY() |
| |
| #define VAL_LONG_ROTATE_DBL(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \ |
| VAL_TEST_TERNARY(name) \ |
| VAL_FAIL_LONG_LONG_TERNARY(name) \ |
| VAL_END_TERNARY() |
| |
| #define VAL_START_UNARY(parm_type,max,incr) \ |
| { \ |
| parm_type d,r,r_asm; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < max; d += incr) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { |
| |
| #define VAL_TEST_UNARY(name) \ |
| r_asm = name##_asm(&flags,d); \ |
| r = name(d); \ |
| if (r != r_asm || M.x86.R_EFLG != flags) { \ |
| failed = true; |
| |
| #define VAL_FAIL_BYTE_UNARY(name) \ |
| printk("fail\n"); \ |
| printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ |
| r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_FAIL_WORD_UNARY(name) \ |
| printk("fail\n"); \ |
| printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ |
| r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_FAIL_LONG_UNARY(name) \ |
| printk("fail\n"); \ |
| printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ |
| r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); |
| |
| #define VAL_END_UNARY() \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_BYTE_UNARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_UNARY(u8,0xFF,0x1) \ |
| VAL_TEST_UNARY(name) \ |
| VAL_FAIL_BYTE_UNARY(name) \ |
| VAL_END_UNARY() |
| |
| #define VAL_WORD_UNARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_UNARY(u16,0xFF00,0x100) \ |
| VAL_TEST_UNARY(name) \ |
| VAL_FAIL_WORD_UNARY(name) \ |
| VAL_END_UNARY() |
| |
| #define VAL_WORD_BYTE_UNARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_UNARY(u16,0xFF,0x1) \ |
| VAL_TEST_UNARY(name) \ |
| VAL_FAIL_WORD_UNARY(name) \ |
| VAL_END_UNARY() |
| |
| #define VAL_LONG_UNARY(name) \ |
| printk("Validating %s ... ", #name); \ |
| VAL_START_UNARY(u32,0xFF000000,0x1000000) \ |
| VAL_TEST_UNARY(name) \ |
| VAL_FAIL_LONG_UNARY(name) \ |
| VAL_END_UNARY() |
| |
| #define VAL_BYTE_MUL(name) \ |
| printk("Validating %s ... ", #name); \ |
| { \ |
| u8 d,s; \ |
| u16 r,r_asm; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < 0xFF; d += 1) { \ |
| for (s = 0; s < 0xFF; s += 1) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { \ |
| name##_asm(&flags,&r_asm,d,s); \ |
| M.x86.R_AL = d; \ |
| name(s); \ |
| r = M.x86.R_AX; \ |
| if (r != r_asm || M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ |
| r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ |
| r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_WORD_MUL(name) \ |
| printk("Validating %s ... ", #name); \ |
| { \ |
| u16 d,s; \ |
| u16 r_lo,r_asm_lo; \ |
| u16 r_hi,r_asm_hi; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < 0xFF00; d += 0x100) { \ |
| for (s = 0; s < 0xFF00; s += 0x100) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { \ |
| name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ |
| M.x86.R_AX = d; \ |
| name(s); \ |
| r_lo = M.x86.R_AX; \ |
| r_hi = M.x86.R_DX; \ |
| if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ |
| failed = true; \ |
| if (failed || trace) { \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ |
| r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ |
| r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_LONG_MUL(name) \ |
| printk("Validating %s ... ", #name); \ |
| { \ |
| u32 d,s; \ |
| u32 r_lo,r_asm_lo; \ |
| u32 r_hi,r_asm_hi; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < 0xFF000000; d += 0x1000000) { \ |
| for (s = 0; s < 0xFF000000; s += 0x1000000) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { \ |
| name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ |
| M.x86.R_EAX = d; \ |
| name(s); \ |
| r_lo = M.x86.R_EAX; \ |
| r_hi = M.x86.R_EDX; \ |
| if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ |
| failed = true; \ |
| if (failed || trace) { \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ |
| r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ |
| r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_BYTE_DIV(name) \ |
| printk("Validating %s ... ", #name); \ |
| { \ |
| u16 d,s; \ |
| u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < 0xFF00; d += 0x100) { \ |
| for (s = 1; s < 0xFF; s += 1) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { \ |
| M.x86.intr = 0; \ |
| M.x86.R_AX = d; \ |
| name(s); \ |
| r_quot = M.x86.R_AL; \ |
| r_rem = M.x86.R_AH; \ |
| if (M.x86.intr & INTR_SYNCH) \ |
| continue; \ |
| name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \ |
| if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ |
| r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ |
| r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_WORD_DIV(name) \ |
| printk("Validating %s ... ", #name); \ |
| { \ |
| u32 d,s; \ |
| u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < 0xFF000000; d += 0x1000000) { \ |
| for (s = 0x100; s < 0xFF00; s += 0x100) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { \ |
| M.x86.intr = 0; \ |
| M.x86.R_AX = d & 0xFFFF; \ |
| M.x86.R_DX = d >> 16; \ |
| name(s); \ |
| r_quot = M.x86.R_AX; \ |
| r_rem = M.x86.R_DX; \ |
| if (M.x86.intr & INTR_SYNCH) \ |
| continue; \ |
| name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\ |
| if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ |
| r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ |
| r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| #define VAL_LONG_DIV(name) \ |
| printk("Validating %s ... ", #name); \ |
| { \ |
| u32 d,s; \ |
| u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \ |
| u32 flags,inflags; \ |
| int f,failed = false; \ |
| char buf1[80],buf2[80]; \ |
| for (d = 0; d < 0xFF000000; d += 0x1000000) { \ |
| for (s = 0x100; s < 0xFF00; s += 0x100) { \ |
| M.x86.R_EFLG = inflags = flags = def_flags; \ |
| for (f = 0; f < 2; f++) { \ |
| M.x86.intr = 0; \ |
| M.x86.R_EAX = d; \ |
| M.x86.R_EDX = 0; \ |
| name(s); \ |
| r_quot = M.x86.R_EAX; \ |
| r_rem = M.x86.R_EDX; \ |
| if (M.x86.intr & INTR_SYNCH) \ |
| continue; \ |
| name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \ |
| if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ |
| failed = true; \ |
| if (failed || trace) { \ |
| if (failed) \ |
| printk("fail\n"); \ |
| printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ |
| r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ |
| printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ |
| r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ |
| } \ |
| M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (failed) \ |
| break; \ |
| } \ |
| if (!failed) \ |
| printk("passed\n"); \ |
| } |
| |
| void printk(const char *fmt, ...) |
| { |
| va_list argptr; |
| va_start(argptr, fmt); |
| vfprintf(stdout, fmt, argptr); |
| fflush(stdout); |
| va_end(argptr); |
| } |
| |
| char * print_flags(char *buf,ulong flags) |
| { |
| char *separator = ""; |
| |
| buf[0] = 0; |
| if (flags & F_CF) { |
| strcat(buf,separator); |
| strcat(buf,"CF"); |
| separator = ","; |
| } |
| if (flags & F_PF) { |
| strcat(buf,separator); |
| strcat(buf,"PF"); |
| separator = ","; |
| } |
| if (flags & F_AF) { |
| strcat(buf,separator); |
| strcat(buf,"AF"); |
| separator = ","; |
| } |
| if (flags & F_ZF) { |
| strcat(buf,separator); |
| strcat(buf,"ZF"); |
| separator = ","; |
| } |
| if (flags & F_SF) { |
| strcat(buf,separator); |
| strcat(buf,"SF"); |
| separator = ","; |
| } |
| if (flags & F_OF) { |
| strcat(buf,separator); |
| strcat(buf,"OF"); |
| separator = ","; |
| } |
| if (separator[0] == 0) |
| strcpy(buf,"None"); |
| return buf; |
| } |
| |
| int main(int argc) |
| { |
| ulong def_flags; |
| int trace = false; |
| |
| if (argc > 1) |
| trace = true; |
| memset(&M, 0, sizeof(M)); |
| def_flags = get_flags_asm() & ~ALL_FLAGS; |
| |
| VAL_WORD_UNARY(aaa_word); |
| VAL_WORD_UNARY(aas_word); |
| |
| VAL_WORD_UNARY(aad_word); |
| VAL_WORD_UNARY(aam_word); |
| |
| VAL_BYTE_BYTE_BINARY(adc_byte); |
| VAL_WORD_WORD_BINARY(adc_word); |
| VAL_LONG_LONG_BINARY(adc_long); |
| |
| VAL_BYTE_BYTE_BINARY(add_byte); |
| VAL_WORD_WORD_BINARY(add_word); |
| VAL_LONG_LONG_BINARY(add_long); |
| |
| VAL_BYTE_BYTE_BINARY(and_byte); |
| VAL_WORD_WORD_BINARY(and_word); |
| VAL_LONG_LONG_BINARY(and_long); |
| |
| VAL_BYTE_BYTE_BINARY(cmp_byte); |
| VAL_WORD_WORD_BINARY(cmp_word); |
| VAL_LONG_LONG_BINARY(cmp_long); |
| |
| VAL_BYTE_UNARY(daa_byte); |
| VAL_BYTE_UNARY(das_byte); /* Fails for 0x9A (out of range anyway) */ |
| |
| VAL_BYTE_UNARY(dec_byte); |
| VAL_WORD_UNARY(dec_word); |
| VAL_LONG_UNARY(dec_long); |
| |
| VAL_BYTE_UNARY(inc_byte); |
| VAL_WORD_UNARY(inc_word); |
| VAL_LONG_UNARY(inc_long); |
| |
| VAL_BYTE_BYTE_BINARY(or_byte); |
| VAL_WORD_WORD_BINARY(or_word); |
| VAL_LONG_LONG_BINARY(or_long); |
| |
| VAL_BYTE_UNARY(neg_byte); |
| VAL_WORD_UNARY(neg_word); |
| VAL_LONG_UNARY(neg_long); |
| |
| VAL_BYTE_UNARY(not_byte); |
| VAL_WORD_UNARY(not_word); |
| VAL_LONG_UNARY(not_long); |
| |
| VAL_BYTE_ROTATE(rcl_byte); |
| VAL_WORD_ROTATE(rcl_word); |
| VAL_LONG_ROTATE(rcl_long); |
| |
| VAL_BYTE_ROTATE(rcr_byte); |
| VAL_WORD_ROTATE(rcr_word); |
| VAL_LONG_ROTATE(rcr_long); |
| |
| VAL_BYTE_ROTATE(rol_byte); |
| VAL_WORD_ROTATE(rol_word); |
| VAL_LONG_ROTATE(rol_long); |
| |
| VAL_BYTE_ROTATE(ror_byte); |
| VAL_WORD_ROTATE(ror_word); |
| VAL_LONG_ROTATE(ror_long); |
| |
| VAL_BYTE_ROTATE(shl_byte); |
| VAL_WORD_ROTATE(shl_word); |
| VAL_LONG_ROTATE(shl_long); |
| |
| VAL_BYTE_ROTATE(shr_byte); |
| VAL_WORD_ROTATE(shr_word); |
| VAL_LONG_ROTATE(shr_long); |
| |
| VAL_BYTE_ROTATE(sar_byte); |
| VAL_WORD_ROTATE(sar_word); |
| VAL_LONG_ROTATE(sar_long); |
| |
| VAL_WORD_ROTATE_DBL(shld_word); |
| VAL_LONG_ROTATE_DBL(shld_long); |
| |
| VAL_WORD_ROTATE_DBL(shrd_word); |
| VAL_LONG_ROTATE_DBL(shrd_long); |
| |
| VAL_BYTE_BYTE_BINARY(sbb_byte); |
| VAL_WORD_WORD_BINARY(sbb_word); |
| VAL_LONG_LONG_BINARY(sbb_long); |
| |
| VAL_BYTE_BYTE_BINARY(sub_byte); |
| VAL_WORD_WORD_BINARY(sub_word); |
| VAL_LONG_LONG_BINARY(sub_long); |
| |
| VAL_BYTE_BYTE_BINARY(xor_byte); |
| VAL_WORD_WORD_BINARY(xor_word); |
| VAL_LONG_LONG_BINARY(xor_long); |
| |
| VAL_VOID_BYTE_BINARY(test_byte); |
| VAL_VOID_WORD_BINARY(test_word); |
| VAL_VOID_LONG_BINARY(test_long); |
| |
| VAL_BYTE_MUL(imul_byte); |
| VAL_WORD_MUL(imul_word); |
| VAL_LONG_MUL(imul_long); |
| |
| VAL_BYTE_MUL(mul_byte); |
| VAL_WORD_MUL(mul_word); |
| VAL_LONG_MUL(mul_long); |
| |
| VAL_BYTE_DIV(idiv_byte); |
| VAL_WORD_DIV(idiv_word); |
| VAL_LONG_DIV(idiv_long); |
| |
| VAL_BYTE_DIV(div_byte); |
| VAL_WORD_DIV(div_word); |
| VAL_LONG_DIV(div_long); |
| |
| return 0; |
| } |