]>
Commit | Line | Data |
---|---|---|
93afd047 MT |
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 printk(const char *fmt, ...) | |
595 | { | |
596 | va_list argptr; | |
597 | va_start(argptr, fmt); | |
598 | vfprintf(stdout, fmt, argptr); | |
599 | fflush(stdout); | |
600 | va_end(argptr); | |
601 | } | |
602 | ||
603 | char * print_flags(char *buf,ulong flags) | |
604 | { | |
605 | char *separator = ""; | |
606 | ||
607 | buf[0] = 0; | |
608 | if (flags & F_CF) { | |
609 | strcat(buf,separator); | |
610 | strcat(buf,"CF"); | |
611 | separator = ","; | |
612 | } | |
613 | if (flags & F_PF) { | |
614 | strcat(buf,separator); | |
615 | strcat(buf,"PF"); | |
616 | separator = ","; | |
617 | } | |
618 | if (flags & F_AF) { | |
619 | strcat(buf,separator); | |
620 | strcat(buf,"AF"); | |
621 | separator = ","; | |
622 | } | |
623 | if (flags & F_ZF) { | |
624 | strcat(buf,separator); | |
625 | strcat(buf,"ZF"); | |
626 | separator = ","; | |
627 | } | |
628 | if (flags & F_SF) { | |
629 | strcat(buf,separator); | |
630 | strcat(buf,"SF"); | |
631 | separator = ","; | |
632 | } | |
633 | if (flags & F_OF) { | |
634 | strcat(buf,separator); | |
635 | strcat(buf,"OF"); | |
636 | separator = ","; | |
637 | } | |
638 | if (separator[0] == 0) | |
639 | strcpy(buf,"None"); | |
640 | return buf; | |
641 | } | |
642 | ||
643 | int main(int argc) | |
644 | { | |
645 | ulong def_flags; | |
646 | int trace = false; | |
647 | ||
648 | if (argc > 1) | |
649 | trace = true; | |
650 | memset(&M, 0, sizeof(M)); | |
651 | def_flags = get_flags_asm() & ~ALL_FLAGS; | |
652 | ||
653 | VAL_WORD_UNARY(aaa_word); | |
654 | VAL_WORD_UNARY(aas_word); | |
655 | ||
656 | VAL_WORD_UNARY(aad_word); | |
657 | VAL_WORD_UNARY(aam_word); | |
658 | ||
659 | VAL_BYTE_BYTE_BINARY(adc_byte); | |
660 | VAL_WORD_WORD_BINARY(adc_word); | |
661 | VAL_LONG_LONG_BINARY(adc_long); | |
662 | ||
663 | VAL_BYTE_BYTE_BINARY(add_byte); | |
664 | VAL_WORD_WORD_BINARY(add_word); | |
665 | VAL_LONG_LONG_BINARY(add_long); | |
666 | ||
667 | VAL_BYTE_BYTE_BINARY(and_byte); | |
668 | VAL_WORD_WORD_BINARY(and_word); | |
669 | VAL_LONG_LONG_BINARY(and_long); | |
670 | ||
671 | VAL_BYTE_BYTE_BINARY(cmp_byte); | |
672 | VAL_WORD_WORD_BINARY(cmp_word); | |
673 | VAL_LONG_LONG_BINARY(cmp_long); | |
674 | ||
675 | VAL_BYTE_UNARY(daa_byte); | |
676 | VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway) | |
677 | ||
678 | VAL_BYTE_UNARY(dec_byte); | |
679 | VAL_WORD_UNARY(dec_word); | |
680 | VAL_LONG_UNARY(dec_long); | |
681 | ||
682 | VAL_BYTE_UNARY(inc_byte); | |
683 | VAL_WORD_UNARY(inc_word); | |
684 | VAL_LONG_UNARY(inc_long); | |
685 | ||
686 | VAL_BYTE_BYTE_BINARY(or_byte); | |
687 | VAL_WORD_WORD_BINARY(or_word); | |
688 | VAL_LONG_LONG_BINARY(or_long); | |
689 | ||
690 | VAL_BYTE_UNARY(neg_byte); | |
691 | VAL_WORD_UNARY(neg_word); | |
692 | VAL_LONG_UNARY(neg_long); | |
693 | ||
694 | VAL_BYTE_UNARY(not_byte); | |
695 | VAL_WORD_UNARY(not_word); | |
696 | VAL_LONG_UNARY(not_long); | |
697 | ||
698 | VAL_BYTE_ROTATE(rcl_byte); | |
699 | VAL_WORD_ROTATE(rcl_word); | |
700 | VAL_LONG_ROTATE(rcl_long); | |
701 | ||
702 | VAL_BYTE_ROTATE(rcr_byte); | |
703 | VAL_WORD_ROTATE(rcr_word); | |
704 | VAL_LONG_ROTATE(rcr_long); | |
705 | ||
706 | VAL_BYTE_ROTATE(rol_byte); | |
707 | VAL_WORD_ROTATE(rol_word); | |
708 | VAL_LONG_ROTATE(rol_long); | |
709 | ||
710 | VAL_BYTE_ROTATE(ror_byte); | |
711 | VAL_WORD_ROTATE(ror_word); | |
712 | VAL_LONG_ROTATE(ror_long); | |
713 | ||
714 | VAL_BYTE_ROTATE(shl_byte); | |
715 | VAL_WORD_ROTATE(shl_word); | |
716 | VAL_LONG_ROTATE(shl_long); | |
717 | ||
718 | VAL_BYTE_ROTATE(shr_byte); | |
719 | VAL_WORD_ROTATE(shr_word); | |
720 | VAL_LONG_ROTATE(shr_long); | |
721 | ||
722 | VAL_BYTE_ROTATE(sar_byte); | |
723 | VAL_WORD_ROTATE(sar_word); | |
724 | VAL_LONG_ROTATE(sar_long); | |
725 | ||
726 | VAL_WORD_ROTATE_DBL(shld_word); | |
727 | VAL_LONG_ROTATE_DBL(shld_long); | |
728 | ||
729 | VAL_WORD_ROTATE_DBL(shrd_word); | |
730 | VAL_LONG_ROTATE_DBL(shrd_long); | |
731 | ||
732 | VAL_BYTE_BYTE_BINARY(sbb_byte); | |
733 | VAL_WORD_WORD_BINARY(sbb_word); | |
734 | VAL_LONG_LONG_BINARY(sbb_long); | |
735 | ||
736 | VAL_BYTE_BYTE_BINARY(sub_byte); | |
737 | VAL_WORD_WORD_BINARY(sub_word); | |
738 | VAL_LONG_LONG_BINARY(sub_long); | |
739 | ||
740 | VAL_BYTE_BYTE_BINARY(xor_byte); | |
741 | VAL_WORD_WORD_BINARY(xor_word); | |
742 | VAL_LONG_LONG_BINARY(xor_long); | |
743 | ||
744 | VAL_VOID_BYTE_BINARY(test_byte); | |
745 | VAL_VOID_WORD_BINARY(test_word); | |
746 | VAL_VOID_LONG_BINARY(test_long); | |
747 | ||
748 | VAL_BYTE_MUL(imul_byte); | |
749 | VAL_WORD_MUL(imul_word); | |
750 | VAL_LONG_MUL(imul_long); | |
751 | ||
752 | VAL_BYTE_MUL(mul_byte); | |
753 | VAL_WORD_MUL(mul_word); | |
754 | VAL_LONG_MUL(mul_long); | |
755 | ||
756 | VAL_BYTE_DIV(idiv_byte); | |
757 | VAL_WORD_DIV(idiv_word); | |
758 | VAL_LONG_DIV(idiv_long); | |
759 | ||
760 | VAL_BYTE_DIV(div_byte); | |
761 | VAL_WORD_DIV(div_word); | |
762 | VAL_LONG_DIV(div_long); | |
763 | ||
764 | return 0; | |
765 | } |