1 2 /* To build: 3 4 gcc -g -o test-amd64 test-amd64.c -lm 5 6 */ 7 8 /* Contrary to what the next comment says, this is now an amd64 CPU 9 test. */ 10 11 /* 12 * x86 CPU test 13 * 14 * Copyright (c) 2003 Fabrice Bellard 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 */ 30 #define _GNU_SOURCE 31 #include <stdlib.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <inttypes.h> 35 #include <math.h> 36 #include <signal.h> 37 #include <setjmp.h> 38 #include <errno.h> 39 #include <sys/ucontext.h> 40 #include <sys/mman.h> 41 42 /* Setting this to 1 creates a very comprehensive test of 43 integer condition codes. */ 44 #define TEST_INTEGER_VERBOSE 1 45 46 typedef long long int int64; 47 48 //#define LINUX_VM86_IOPL_FIX 49 //#define TEST_P4_FLAGS 50 51 #define xglue(x, y) x ## y 52 #define glue(x, y) xglue(x, y) 53 #define stringify(s) tostring(s) 54 #define tostring(s) #s 55 56 #define CC_C 0x0001 57 #define CC_P 0x0004 58 #define CC_A 0x0010 59 #define CC_Z 0x0040 60 #define CC_S 0x0080 61 #define CC_O 0x0800 62 63 #define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) 64 65 static void *call_start __init_call = NULL; 66 67 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) 68 69 #define OP add 70 #include "test-amd64.h" 71 72 #define OP sub 73 #include "test-amd64.h" 74 75 #define OP xor 76 #include "test-amd64.h" 77 78 #define OP and 79 #include "test-amd64.h" 80 81 #define OP or 82 #include "test-amd64.h" 83 84 #define OP cmp 85 #include "test-amd64.h" 86 87 #define OP adc 88 #define OP_CC 89 #include "test-amd64.h" 90 91 #define OP sbb 92 #define OP_CC 93 #include "test-amd64.h" 94 95 #define OP inc 96 #define OP_CC 97 #define OP1 98 #include "test-amd64.h" 99 100 #define OP dec 101 #define OP_CC 102 #define OP1 103 #include "test-amd64.h" 104 105 #define OP neg 106 #define OP_CC 107 #define OP1 108 #include "test-amd64.h" 109 110 #define OP not 111 #define OP_CC 112 #define OP1 113 #include "test-amd64.h" 114 115 #undef CC_MASK 116 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O) 117 118 #define OP shl 119 #include "test-amd64-shift.h" 120 121 #define OP shr 122 #include "test-amd64-shift.h" 123 124 #define OP sar 125 #include "test-amd64-shift.h" 126 127 #define OP rol 128 #include "test-amd64-shift.h" 129 130 #define OP ror 131 #include "test-amd64-shift.h" 132 133 #define OP rcr 134 #define OP_CC 135 #include "test-amd64-shift.h" 136 137 #define OP rcl 138 #define OP_CC 139 #include "test-amd64-shift.h" 140 141 #if 0 142 #define OP shld 143 #define OP_SHIFTD 144 #define OP_NOBYTE 145 #include "test-amd64-shift.h" 146 147 #define OP shrd 148 #define OP_SHIFTD 149 #define OP_NOBYTE 150 #include "test-amd64-shift.h" 151 #endif 152 153 /* XXX: should be more precise ? */ 154 #undef CC_MASK 155 #define CC_MASK (CC_C) 156 157 #if 0 158 #define OP bt 159 #define OP_NOBYTE 160 #include "test-amd64-shift.h" 161 162 #define OP bts 163 #define OP_NOBYTE 164 #include "test-amd64-shift.h" 165 166 #define OP btr 167 #define OP_NOBYTE 168 #include "test-amd64-shift.h" 169 170 #define OP btc 171 #define OP_NOBYTE 172 #include "test-amd64-shift.h" 173 #endif 174 175 /* lea test (modrm support) */ 176 #define TEST_LEA(STR)\ 177 {\ 178 asm("leaq " STR ", %0"\ 179 : "=r" (res)\ 180 : "a" (rax), "b" (rbx), "c" (rcx), "d" (rdx), "S" (rsi), "D" (rdi));\ 181 printf("lea %s = %016llx\n", STR, res);\ 182 } 183 184 #define TEST_LEA16(STR)\ 185 {\ 186 asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\ 187 : "=wq" (res)\ 188 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ 189 printf("lea %s = %08x\n", STR, res);\ 190 } 191 192 193 void test_lea(void) 194 { 195 int64 rax, rbx, rcx, rdx, rsi, rdi, res; 196 rax = 0x0001; 197 rbx = 0x0002; 198 rcx = 0x0004; 199 rdx = 0x0008; 200 rsi = 0x0010; 201 rdi = 0x0020; 202 203 TEST_LEA("0x4000"); 204 205 TEST_LEA("(%%rax)"); 206 TEST_LEA("(%%rbx)"); 207 TEST_LEA("(%%rcx)"); 208 TEST_LEA("(%%rdx)"); 209 TEST_LEA("(%%rsi)"); 210 TEST_LEA("(%%rdi)"); 211 212 TEST_LEA("0x40(%%rax)"); 213 TEST_LEA("0x40(%%rbx)"); 214 TEST_LEA("0x40(%%rcx)"); 215 TEST_LEA("0x40(%%rdx)"); 216 TEST_LEA("0x40(%%rsi)"); 217 TEST_LEA("0x40(%%rdi)"); 218 219 TEST_LEA("0x4000(%%rax)"); 220 TEST_LEA("0x4000(%%rbx)"); 221 TEST_LEA("0x4000(%%rcx)"); 222 TEST_LEA("0x4000(%%rdx)"); 223 TEST_LEA("0x4000(%%rsi)"); 224 TEST_LEA("0x4000(%%rdi)"); 225 226 TEST_LEA("(%%rax, %%rcx)"); 227 TEST_LEA("(%%rbx, %%rdx)"); 228 TEST_LEA("(%%rcx, %%rcx)"); 229 TEST_LEA("(%%rdx, %%rcx)"); 230 TEST_LEA("(%%rsi, %%rcx)"); 231 TEST_LEA("(%%rdi, %%rcx)"); 232 233 TEST_LEA("0x40(%%rax, %%rcx)"); 234 TEST_LEA("0x4000(%%rbx, %%rdx)"); 235 236 TEST_LEA("(%%rcx, %%rcx, 2)"); 237 TEST_LEA("(%%rdx, %%rcx, 4)"); 238 TEST_LEA("(%%rsi, %%rcx, 8)"); 239 240 TEST_LEA("(,%%rax, 2)"); 241 TEST_LEA("(,%%rbx, 4)"); 242 TEST_LEA("(,%%rcx, 8)"); 243 244 TEST_LEA("0x40(,%%rax, 2)"); 245 TEST_LEA("0x40(,%%rbx, 4)"); 246 TEST_LEA("0x40(,%%rcx, 8)"); 247 248 249 TEST_LEA("-10(%%rcx, %%rcx, 2)"); 250 TEST_LEA("-10(%%rdx, %%rcx, 4)"); 251 TEST_LEA("-10(%%rsi, %%rcx, 8)"); 252 253 TEST_LEA("0x4000(%%rcx, %%rcx, 2)"); 254 TEST_LEA("0x4000(%%rdx, %%rcx, 4)"); 255 TEST_LEA("0x4000(%%rsi, %%rcx, 8)"); 256 } 257 258 #define TEST_JCC(JCC, v1, v2)\ 259 { int one = 1; \ 260 int res;\ 261 asm("movl $1, %0\n\t"\ 262 "cmpl %2, %1\n\t"\ 263 "j" JCC " 1f\n\t"\ 264 "movl $0, %0\n\t"\ 265 "1:\n\t"\ 266 : "=r" (res)\ 267 : "r" (v1), "r" (v2));\ 268 printf("%-10s %d\n", "j" JCC, res);\ 269 \ 270 asm("movl $0, %0\n\t"\ 271 "cmpl %2, %1\n\t"\ 272 "set" JCC " %b0\n\t"\ 273 : "=r" (res)\ 274 : "r" (v1), "r" (v2));\ 275 printf("%-10s %d\n", "set" JCC, res);\ 276 {\ 277 asm("movl $0x12345678, %0\n\t"\ 278 "cmpl %2, %1\n\t"\ 279 "cmov" JCC "l %3, %0\n\t"\ 280 : "=r" (res)\ 281 : "r" (v1), "r" (v2), "m" (one));\ 282 printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\ 283 asm("movl $0x12345678, %0\n\t"\ 284 "cmpl %2, %1\n\t"\ 285 "cmov" JCC "w %w3, %w0\n\t"\ 286 : "=r" (res)\ 287 : "r" (v1), "r" (v2), "r" (one));\ 288 printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\ 289 } \ 290 } 291 292 /* various jump tests */ 293 void test_jcc(void) 294 { 295 TEST_JCC("ne", 1, 1); 296 TEST_JCC("ne", 1, 0); 297 298 TEST_JCC("e", 1, 1); 299 TEST_JCC("e", 1, 0); 300 301 TEST_JCC("l", 1, 1); 302 TEST_JCC("l", 1, 0); 303 TEST_JCC("l", 1, -1); 304 305 TEST_JCC("le", 1, 1); 306 TEST_JCC("le", 1, 0); 307 TEST_JCC("le", 1, -1); 308 309 TEST_JCC("ge", 1, 1); 310 TEST_JCC("ge", 1, 0); 311 TEST_JCC("ge", -1, 1); 312 313 TEST_JCC("g", 1, 1); 314 TEST_JCC("g", 1, 0); 315 TEST_JCC("g", 1, -1); 316 317 TEST_JCC("b", 1, 1); 318 TEST_JCC("b", 1, 0); 319 TEST_JCC("b", 1, -1); 320 321 TEST_JCC("be", 1, 1); 322 TEST_JCC("be", 1, 0); 323 TEST_JCC("be", 1, -1); 324 325 TEST_JCC("ae", 1, 1); 326 TEST_JCC("ae", 1, 0); 327 TEST_JCC("ae", 1, -1); 328 329 TEST_JCC("a", 1, 1); 330 TEST_JCC("a", 1, 0); 331 TEST_JCC("a", 1, -1); 332 333 334 TEST_JCC("p", 1, 1); 335 TEST_JCC("p", 1, 0); 336 337 TEST_JCC("np", 1, 1); 338 TEST_JCC("np", 1, 0); 339 340 TEST_JCC("o", 0x7fffffff, 0); 341 TEST_JCC("o", 0x7fffffff, -1); 342 343 TEST_JCC("no", 0x7fffffff, 0); 344 TEST_JCC("no", 0x7fffffff, -1); 345 346 TEST_JCC("s", 0, 1); 347 TEST_JCC("s", 0, -1); 348 TEST_JCC("s", 0, 0); 349 350 TEST_JCC("ns", 0, 1); 351 TEST_JCC("ns", 0, -1); 352 TEST_JCC("ns", 0, 0); 353 } 354 355 #undef CC_MASK 356 #ifdef TEST_P4_FLAGS 357 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) 358 #else 359 #define CC_MASK (CC_O | CC_C) 360 #endif 361 362 #define OP mul 363 #include "test-amd64-muldiv.h" 364 365 #define OP imul 366 #include "test-amd64-muldiv.h" 367 368 void test_imulw2(int64 op0, int64 op1) 369 { 370 int64 res, s1, s0, flags; 371 s0 = op0; 372 s1 = op1; 373 res = s0; 374 flags = 0; 375 asm ("pushq %4\n\t" 376 "popfq\n\t" 377 "imulw %w2, %w0\n\t" 378 "pushfq\n\t" 379 "popq %1\n\t" 380 : "=q" (res), "=g" (flags) 381 : "q" (s1), "0" (res), "1" (flags)); 382 printf("%-10s A=%016llx B=%016llx R=%016llx CC=%04llx\n", 383 "imulw", s0, s1, res, flags & CC_MASK); 384 } 385 386 void test_imull2(int64 op0, int64 op1) 387 { 388 int res, s1; 389 int64 s0, flags; 390 s0 = op0; 391 s1 = op1; 392 res = s0; 393 flags = 0; 394 asm ("pushq %4\n\t" 395 "popfq\n\t" 396 "imull %2, %0\n\t" 397 "pushfq\n\t" 398 "popq %1\n\t" 399 : "=q" (res), "=g" (flags) 400 : "q" (s1), "0" (res), "1" (flags)); 401 printf("%-10s A=%016llx B=%08x R=%08x CC=%04llx\n", 402 "imull", s0, s1, res, flags & CC_MASK); 403 } 404 405 #define TEST_IMUL_IM(size, size1, op0, op1)\ 406 {\ 407 int64 res, flags;\ 408 flags = 0;\ 409 res = 0;\ 410 asm ("pushq %3\n\t"\ 411 "popfq\n\t"\ 412 "imul" size " $" #op0 ", %" size1 "2, %" size1 "0\n\t" \ 413 "pushfq\n\t"\ 414 "popq %1\n\t"\ 415 : "=r" (res), "=g" (flags)\ 416 : "r" (op1), "1" (flags), "0" (res));\ 417 printf("%-10s A=%08x B=%08x R=%016llx CC=%04llx\n",\ 418 "imul" size, op0, op1, res, flags & CC_MASK);\ 419 } 420 421 #define TEST_IMUL_IM_L(op0, op1)\ 422 {\ 423 int64 flags = 0;\ 424 int res = 0;\ 425 int res64 = 0;\ 426 asm ("pushq %3\n\t"\ 427 "popfq\n\t"\ 428 "imul $" #op0 ", %2, %0\n\t" \ 429 "pushfq\n\t"\ 430 "popq %1\n\t"\ 431 : "=r" (res64), "=g" (flags)\ 432 : "r" (op1), "1" (flags), "0" (res));\ 433 printf("%-10s A=%08x B=%08x R=%08x CC=%04llx\n",\ 434 "imull", op0, op1, res, flags & CC_MASK);\ 435 } 436 437 438 #undef CC_MASK 439 #define CC_MASK (0) 440 441 #define OP div 442 #include "test-amd64-muldiv.h" 443 444 #define OP idiv 445 #include "test-amd64-muldiv.h" 446 447 void test_mul(void) 448 { 449 test_imulb(0x1234561d, 4); 450 test_imulb(3, -4); 451 test_imulb(0x80, 0x80); 452 test_imulb(0x10, 0x10); 453 454 test_imulw(0, 0, 0); 455 test_imulw(0, 0xFF, 0xFF); 456 test_imulw(0, 0xFF, 0x100); 457 test_imulw(0, 0x1234001d, 45); 458 test_imulw(0, 23, -45); 459 test_imulw(0, 0x8000, 0x8000); 460 test_imulw(0, 0x100, 0x100); 461 462 test_imull(0, 0, 0); 463 test_imull(0, 0xFFFF, 0xFFFF); 464 test_imull(0, 0xFFFF, 0x10000); 465 test_imull(0, 0x1234001d, 45); 466 test_imull(0, 23, -45); 467 test_imull(0, 0x80000000, 0x80000000); 468 test_imull(0, 0x10000, 0x10000); 469 470 test_mulb(0x1234561d, 4); 471 test_mulb(3, -4); 472 test_mulb(0x80, 0x80); 473 test_mulb(0x10, 0x10); 474 475 test_mulw(0, 0x1234001d, 45); 476 test_mulw(0, 23, -45); 477 test_mulw(0, 0x8000, 0x8000); 478 test_mulw(0, 0x100, 0x100); 479 480 test_mull(0, 0x1234001d, 45); 481 test_mull(0, 23, -45); 482 test_mull(0, 0x80000000, 0x80000000); 483 test_mull(0, 0x10000, 0x10000); 484 485 test_imulw2(0x1234001d, 45); 486 test_imulw2(23, -45); 487 test_imulw2(0x8000, 0x8000); 488 test_imulw2(0x100, 0x100); 489 490 test_imull2(0x1234001d, 45); 491 test_imull2(23, -45); 492 test_imull2(0x80000000, 0x80000000); 493 test_imull2(0x10000, 0x10000); 494 495 TEST_IMUL_IM("w", "w", 45, 0x1234); 496 TEST_IMUL_IM("w", "w", -45, 23); 497 TEST_IMUL_IM("w", "w", 0x8000, 0x80000000); 498 TEST_IMUL_IM("w", "w", 0x7fff, 0x1000); 499 500 TEST_IMUL_IM_L(45, 0x1234); 501 TEST_IMUL_IM_L(-45, 23); 502 TEST_IMUL_IM_L(0x8000, 0x80000000); 503 TEST_IMUL_IM_L(0x7fff, 0x1000); 504 505 test_idivb(0x12341678, 0x127e); 506 test_idivb(0x43210123, -5); 507 test_idivb(0x12340004, -1); 508 509 test_idivw(0, 0x12345678, 12347); 510 test_idivw(0, -23223, -45); 511 test_idivw(0, 0x12348000, -1); 512 test_idivw(0x12343, 0x12345678, 0x81238567); 513 514 test_idivl(0, 0x12345678, 12347); 515 test_idivl(0, -233223, -45); 516 test_idivl(0, 0x80000000, -1); 517 test_idivl(0x12343, 0x12345678, 0x81234567); 518 519 test_idivq(0, 0x12345678, 12347); 520 test_idivq(0, -233223, -45); 521 test_idivq(0, 0x80000000, -1); 522 test_idivq(0x12343, 0x12345678, 0x81234567); 523 524 test_divb(0x12341678, 0x127e); 525 test_divb(0x43210123, -5); 526 test_divb(0x12340004, -1); 527 528 test_divw(0, 0x12345678, 12347); 529 test_divw(0, -23223, -45); 530 test_divw(0, 0x12348000, -1); 531 test_divw(0x12343, 0x12345678, 0x81238567); 532 533 test_divl(0, 0x12345678, 12347); 534 test_divl(0, -233223, -45); 535 test_divl(0, 0x80000000, -1); 536 test_divl(0x12343, 0x12345678, 0x81234567); 537 538 test_divq(0, 0x12345678, 12347); 539 test_divq(0, -233223, -45); 540 test_divq(0, 0x80000000, -1); 541 test_divq(0x12343, 0x12345678, 0x81234567); 542 } 543 544 #define TEST_BSX(op, size, op0)\ 545 {\ 546 int res, val, resz;\ 547 val = op0;\ 548 asm("xorl %1, %1\n"\ 549 "movl $0x12345678, %0\n"\ 550 #op " %" size "2, %" size "0 ; setz %b1" \ 551 : "=r" (res), "=q" (resz)\ 552 : "r" (val));\ 553 printf("%-10s A=%08x R=%08x %d\n", #op, val, res, resz);\ 554 } 555 556 void test_bsx(void) 557 { 558 TEST_BSX(bsrw, "w", 0); 559 TEST_BSX(bsrw, "w", 0x12340128); 560 TEST_BSX(bsrl, "", 0); 561 TEST_BSX(bsrl, "", 0x00340128); 562 TEST_BSX(bsfw, "w", 0); 563 TEST_BSX(bsfw, "w", 0x12340128); 564 TEST_BSX(bsfl, "", 0); 565 TEST_BSX(bsfl, "", 0x00340128); 566 } 567 568 /**********************************************/ 569 570 void test_fops(double a, double b) 571 { 572 printf("a=%f b=%f a+b=%f\n", a, b, a + b); 573 printf("a=%f b=%f a-b=%f\n", a, b, a - b); 574 printf("a=%f b=%f a*b=%f\n", a, b, a * b); 575 printf("a=%f b=%f a/b=%f\n", a, b, a / b); 576 printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b)); 577 printf("a=%f sqrt(a)=%f\n", a, sqrt(a)); 578 printf("a=%f sin(a)=%f\n", a, sin(a)); 579 printf("a=%f cos(a)=%f\n", a, cos(a)); 580 printf("a=%f tan(a)=%f\n", a, tan(a)); 581 printf("a=%f log(a)=%f\n", a, log(a)); 582 printf("a=%f exp(a)=%f\n", a, exp(a)); 583 printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b)); 584 /* just to test some op combining */ 585 printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a))); 586 printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a))); 587 printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a))); 588 } 589 590 void test_fcmp(double a, double b) 591 { 592 printf("(%f<%f)=%d\n", 593 a, b, a < b); 594 printf("(%f<=%f)=%d\n", 595 a, b, a <= b); 596 printf("(%f==%f)=%d\n", 597 a, b, a == b); 598 printf("(%f>%f)=%d\n", 599 a, b, a > b); 600 printf("(%f<=%f)=%d\n", 601 a, b, a >= b); 602 { 603 unsigned long long int rflags; 604 /* test f(u)comi instruction */ 605 asm("fcomi %2, %1\n" 606 "pushfq\n" 607 "popq %0\n" 608 : "=r" (rflags) 609 : "t" (a), "u" (b)); 610 printf("fcomi(%f %f)=%016llx\n", a, b, rflags & (CC_Z | CC_P | CC_C)); 611 } 612 } 613 614 void test_fcvt(double a) 615 { 616 float fa; 617 long double la; 618 int16_t fpuc; 619 int i; 620 int64 lla; 621 int ia; 622 int16_t wa; 623 double ra; 624 625 fa = a; 626 la = a; 627 printf("(float)%f = %f\n", a, fa); 628 printf("(long double)%f = %Lf\n", a, la); 629 printf("a=%016Lx\n", *(long long *)&a); 630 printf("la=%016Lx %04x\n", *(long long *)&la, 631 *(unsigned short *)((char *)(&la) + 8)); 632 633 /* test all roundings */ 634 asm volatile ("fstcw %0" : "=m" (fpuc)); 635 for(i=0;i<4;i++) { 636 short zz = (fpuc & ~0x0c00) | (i << 10); 637 asm volatile ("fldcw %0" : : "m" (zz)); 638 asm volatile ("fist %0" : "=m" (wa) : "t" (a)); 639 asm volatile ("fistl %0" : "=m" (ia) : "t" (a)); 640 asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st"); 641 asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a)); 642 asm volatile ("fldcw %0" : : "m" (fpuc)); 643 printf("(short)a = %d\n", wa); 644 printf("(int)a = %d\n", ia); 645 printf("(int64_t)a = %Ld\n", lla); 646 printf("rint(a) = %f\n", ra); 647 } 648 } 649 650 #define TEST(N) \ 651 asm("fld" #N : "=t" (a)); \ 652 printf("fld" #N "= %f\n", a); 653 654 void test_fconst(void) 655 { 656 double a; 657 TEST(1); 658 TEST(l2t); 659 TEST(l2e); 660 TEST(pi); 661 TEST(lg2); 662 TEST(ln2); 663 TEST(z); 664 } 665 666 void test_fbcd(double a) 667 { 668 unsigned short bcd[5]; 669 double b; 670 671 asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st"); 672 asm("fbld %1" : "=t" (b) : "m" (bcd[0])); 673 printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 674 a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b); 675 } 676 677 #define TEST_ENV(env, save, restore)\ 678 {\ 679 memset((env), 0xaa, sizeof(*(env)));\ 680 for(i=0;i<5;i++)\ 681 asm volatile ("fldl %0" : : "m" (dtab[i]));\ 682 asm(save " %0\n" : : "m" (*(env)));\ 683 asm(restore " %0\n": : "m" (*(env)));\ 684 for(i=0;i<5;i++)\ 685 asm volatile ("fstpl %0" : "=m" (rtab[i]));\ 686 for(i=0;i<5;i++)\ 687 printf("res[%d]=%f\n", i, rtab[i]);\ 688 printf("fpuc=%04x fpus=%04x fptag=%04x\n",\ 689 (env)->fpuc,\ 690 (env)->fpus & 0xff00,\ 691 (env)->fptag);\ 692 } 693 694 void test_fenv(void) 695 { 696 struct __attribute__((packed)) { 697 uint16_t fpuc; 698 uint16_t dummy1; 699 uint16_t fpus; 700 uint16_t dummy2; 701 uint16_t fptag; 702 uint16_t dummy3; 703 uint32_t ignored[4]; 704 long double fpregs[8]; 705 } float_env32; 706 struct __attribute__((packed)) { 707 uint16_t fpuc; 708 uint16_t fpus; 709 uint16_t fptag; 710 uint16_t ignored[4]; 711 long double fpregs[8]; 712 } float_env16; 713 double dtab[8]; 714 double rtab[8]; 715 int i; 716 717 for(i=0;i<8;i++) 718 dtab[i] = i + 1; 719 720 TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); 721 TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); 722 TEST_ENV(&float_env32, "fnstenv", "fldenv"); 723 TEST_ENV(&float_env32, "fnsave", "frstor"); 724 725 /* test for ffree */ 726 for(i=0;i<5;i++) 727 asm volatile ("fldl %0" : : "m" (dtab[i])); 728 asm volatile("ffree %st(2)"); 729 asm volatile ("fnstenv %0\n" : : "m" (float_env32)); 730 asm volatile ("fninit"); 731 printf("fptag=%04x\n", float_env32.fptag); 732 } 733 734 735 #define TEST_FCMOV(a, b, rflags, CC)\ 736 {\ 737 double res;\ 738 asm("pushq %3\n"\ 739 "popfq\n"\ 740 "fcmov" CC " %2, %0\n"\ 741 : "=t" (res)\ 742 : "0" (a), "u" (b), "g" (rflags));\ 743 printf("fcmov%s rflags=0x%04llx-> %f\n", \ 744 CC, rflags, res);\ 745 } 746 747 void test_fcmov(void) 748 { 749 double a, b; 750 int64 rflags, i; 751 752 a = 1.0; 753 b = 2.0; 754 for(i = 0; i < 4; i++) { 755 rflags = 0; 756 if (i & 1) 757 rflags |= CC_C; 758 if (i & 2) 759 rflags |= CC_Z; 760 TEST_FCMOV(a, b, rflags, "b"); 761 TEST_FCMOV(a, b, rflags, "e"); 762 TEST_FCMOV(a, b, rflags, "be"); 763 TEST_FCMOV(a, b, rflags, "nb"); 764 TEST_FCMOV(a, b, rflags, "ne"); 765 TEST_FCMOV(a, b, rflags, "nbe"); 766 } 767 TEST_FCMOV(a, b, (int64)0, "u"); 768 TEST_FCMOV(a, b, (int64)CC_P, "u"); 769 TEST_FCMOV(a, b, (int64)0, "nu"); 770 TEST_FCMOV(a, b, (int64)CC_P, "nu"); 771 } 772 773 void test_floats(void) 774 { 775 test_fops(2, 3); 776 test_fops(1.4, -5); 777 test_fcmp(2, -1); 778 test_fcmp(2, 2); 779 test_fcmp(2, 3); 780 test_fcvt(0.5); 781 test_fcvt(-0.5); 782 test_fcvt(1.0/7.0); 783 test_fcvt(-1.0/9.0); 784 test_fcvt(32768); 785 test_fcvt(-1e20); 786 test_fconst(); 787 // REINSTATE (maybe): test_fbcd(1234567890123456); 788 // REINSTATE (maybe): test_fbcd(-123451234567890); 789 // REINSTATE: test_fenv(); 790 // REINSTATE: test_fcmov(); 791 } 792 793 /**********************************************/ 794 #if 0 795 796 #define TEST_BCD(op, op0, cc_in, cc_mask)\ 797 {\ 798 int res, flags;\ 799 res = op0;\ 800 flags = cc_in;\ 801 asm ("push %3\n\t"\ 802 "popf\n\t"\ 803 #op "\n\t"\ 804 "pushf\n\t"\ 805 "popl %1\n\t"\ 806 : "=a" (res), "=g" (flags)\ 807 : "0" (res), "1" (flags));\ 808 printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\ 809 #op, op0, res, cc_in, flags & cc_mask);\ 810 } 811 812 void test_bcd(void) 813 { 814 TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 815 TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 816 TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 817 TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 818 TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 819 TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 820 TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 821 TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 822 TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 823 TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 824 TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 825 TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 826 TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 827 828 TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 829 TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 830 TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 831 TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 832 TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 833 TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 834 TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 835 TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 836 TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 837 TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 838 TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 839 TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 840 TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 841 842 TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A)); 843 TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A)); 844 TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A)); 845 TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A)); 846 TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A)); 847 TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A)); 848 TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A)); 849 TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A)); 850 851 TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A)); 852 TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A)); 853 TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A)); 854 TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A)); 855 TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A)); 856 TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A)); 857 TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A)); 858 TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A)); 859 860 TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); 861 TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); 862 } 863 #endif /* 0 */ 864 865 #define TEST_XCHG(op, size, opconst)\ 866 {\ 867 int op0, op1;\ 868 op0 = 0x12345678;\ 869 op1 = 0xfbca7654;\ 870 asm(#op " %" size "0, %" size "1" \ 871 : "=q" (op0), opconst (op1) \ 872 : "0" (op0), "1" (op1));\ 873 printf("%-10s A=%08x B=%08x\n",\ 874 #op, op0, op1);\ 875 } 876 877 #define TEST_CMPXCHG(op, size, opconst, eax)\ 878 {\ 879 int op0, op1;\ 880 op0 = 0x12345678;\ 881 op1 = 0xfbca7654;\ 882 asm(#op " %" size "0, %" size "1" \ 883 : "=q" (op0), opconst (op1) \ 884 : "0" (op0), "1" (op1), "a" (eax));\ 885 printf("%-10s EAX=%08x A=%08x C=%08x\n",\ 886 #op, eax, op0, op1);\ 887 } 888 889 void test_xchg(void) 890 { 891 TEST_XCHG(xchgl, "", "=q"); 892 TEST_XCHG(xchgw, "w", "=q"); 893 TEST_XCHG(xchgb, "b", "=q"); 894 895 TEST_XCHG(xchgl, "", "=m"); 896 TEST_XCHG(xchgw, "w", "=m"); 897 TEST_XCHG(xchgb, "b", "=m"); 898 899 #if 0 900 TEST_XCHG(xaddl, "", "=q"); 901 TEST_XCHG(xaddw, "w", "=q"); 902 TEST_XCHG(xaddb, "b", "=q"); 903 904 { 905 int res; 906 res = 0x12345678; 907 asm("xaddl %1, %0" : "=r" (res) : "0" (res)); 908 printf("xaddl same res=%08x\n", res); 909 } 910 911 TEST_XCHG(xaddl, "", "=m"); 912 TEST_XCHG(xaddw, "w", "=m"); 913 TEST_XCHG(xaddb, "b", "=m"); 914 #endif 915 TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654); 916 TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654); 917 TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654); 918 919 TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc); 920 TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc); 921 TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc); 922 923 TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654); 924 TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654); 925 TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654); 926 927 TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc); 928 TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc); 929 TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc); 930 #if 0 931 { 932 uint64_t op0, op1, op2; 933 int i, eflags; 934 935 for(i = 0; i < 2; i++) { 936 op0 = 0x123456789abcd; 937 if (i == 0) 938 op1 = 0xfbca765423456; 939 else 940 op1 = op0; 941 op2 = 0x6532432432434; 942 asm("cmpxchg8b %1\n" 943 "pushf\n" 944 "popl %2\n" 945 : "=A" (op0), "=m" (op1), "=g" (eflags) 946 : "0" (op0), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32))); 947 printf("cmpxchg8b: op0=%016llx op1=%016llx CC=%02x\n", 948 op0, op1, eflags & CC_Z); 949 } 950 } 951 #endif 952 } 953 954 /**********************************************/ 955 /* segmentation tests */ 956 #if 0 957 #include <asm/ldt.h> 958 #include <linux/unistd.h> 959 #include <linux/version.h> 960 961 _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) 962 963 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66) 964 #define modify_ldt_ldt_s user_desc 965 #endif 966 967 uint8_t seg_data1[4096]; 968 uint8_t seg_data2[4096]; 969 970 #define MK_SEL(n) (((n) << 3) | 7) 971 972 #define TEST_LR(op, size, seg, mask)\ 973 {\ 974 int res, res2;\ 975 res = 0x12345678;\ 976 asm (op " %" size "2, %" size "0\n" \ 977 "movl $0, %1\n"\ 978 "jnz 1f\n"\ 979 "movl $1, %1\n"\ 980 "1:\n"\ 981 : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\ 982 printf(op ": Z=%d %08x\n", res2, res & ~(mask));\ 983 } 984 985 /* NOTE: we use Linux modify_ldt syscall */ 986 void test_segs(void) 987 { 988 struct modify_ldt_ldt_s ldt; 989 long long ldt_table[3]; 990 int res, res2; 991 char tmp; 992 struct { 993 uint32_t offset; 994 uint16_t seg; 995 } __attribute__((packed)) segoff; 996 997 ldt.entry_number = 1; 998 ldt.base_addr = (unsigned long)&seg_data1; 999 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; 1000 ldt.seg_32bit = 1; 1001 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1002 ldt.read_exec_only = 0; 1003 ldt.limit_in_pages = 1; 1004 ldt.seg_not_present = 0; 1005 ldt.useable = 1; 1006 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1007 1008 ldt.entry_number = 2; 1009 ldt.base_addr = (unsigned long)&seg_data2; 1010 ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12; 1011 ldt.seg_32bit = 1; 1012 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1013 ldt.read_exec_only = 0; 1014 ldt.limit_in_pages = 1; 1015 ldt.seg_not_present = 0; 1016 ldt.useable = 1; 1017 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1018 1019 modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ 1020 #if 0 1021 { 1022 int i; 1023 for(i=0;i<3;i++) 1024 printf("%d: %016Lx\n", i, ldt_table[i]); 1025 } 1026 #endif 1027 /* do some tests with fs or gs */ 1028 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); 1029 1030 seg_data1[1] = 0xaa; 1031 seg_data2[1] = 0x55; 1032 1033 asm volatile ("fs movzbl 0x1, %0" : "=r" (res)); 1034 printf("FS[1] = %02x\n", res); 1035 1036 asm volatile ("pushl %%gs\n" 1037 "movl %1, %%gs\n" 1038 "gs movzbl 0x1, %0\n" 1039 "popl %%gs\n" 1040 : "=r" (res) 1041 : "r" (MK_SEL(2))); 1042 printf("GS[1] = %02x\n", res); 1043 1044 /* tests with ds/ss (implicit segment case) */ 1045 tmp = 0xa5; 1046 asm volatile ("pushl %%ebp\n\t" 1047 "pushl %%ds\n\t" 1048 "movl %2, %%ds\n\t" 1049 "movl %3, %%ebp\n\t" 1050 "movzbl 0x1, %0\n\t" 1051 "movzbl (%%ebp), %1\n\t" 1052 "popl %%ds\n\t" 1053 "popl %%ebp\n\t" 1054 : "=r" (res), "=r" (res2) 1055 : "r" (MK_SEL(1)), "r" (&tmp)); 1056 printf("DS[1] = %02x\n", res); 1057 printf("SS[tmp] = %02x\n", res2); 1058 1059 segoff.seg = MK_SEL(2); 1060 segoff.offset = 0xabcdef12; 1061 asm volatile("lfs %2, %0\n\t" 1062 "movl %%fs, %1\n\t" 1063 : "=r" (res), "=g" (res2) 1064 : "m" (segoff)); 1065 printf("FS:reg = %04x:%08x\n", res2, res); 1066 1067 TEST_LR("larw", "w", MK_SEL(2), 0x0100); 1068 TEST_LR("larl", "", MK_SEL(2), 0x0100); 1069 TEST_LR("lslw", "w", MK_SEL(2), 0); 1070 TEST_LR("lsll", "", MK_SEL(2), 0); 1071 1072 TEST_LR("larw", "w", 0xfff8, 0); 1073 TEST_LR("larl", "", 0xfff8, 0); 1074 TEST_LR("lslw", "w", 0xfff8, 0); 1075 TEST_LR("lsll", "", 0xfff8, 0); 1076 } 1077 #endif 1078 1079 #if 0 1080 /* 16 bit code test */ 1081 extern char code16_start, code16_end; 1082 extern char code16_func1; 1083 extern char code16_func2; 1084 extern char code16_func3; 1085 1086 void test_code16(void) 1087 { 1088 struct modify_ldt_ldt_s ldt; 1089 int res, res2; 1090 1091 /* build a code segment */ 1092 ldt.entry_number = 1; 1093 ldt.base_addr = (unsigned long)&code16_start; 1094 ldt.limit = &code16_end - &code16_start; 1095 ldt.seg_32bit = 0; 1096 ldt.contents = MODIFY_LDT_CONTENTS_CODE; 1097 ldt.read_exec_only = 0; 1098 ldt.limit_in_pages = 0; 1099 ldt.seg_not_present = 0; 1100 ldt.useable = 1; 1101 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1102 1103 /* call the first function */ 1104 asm volatile ("lcall %1, %2" 1105 : "=a" (res) 1106 : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc"); 1107 printf("func1() = 0x%08x\n", res); 1108 asm volatile ("lcall %2, %3" 1109 : "=a" (res), "=c" (res2) 1110 : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc"); 1111 printf("func2() = 0x%08x spdec=%d\n", res, res2); 1112 asm volatile ("lcall %1, %2" 1113 : "=a" (res) 1114 : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc"); 1115 printf("func3() = 0x%08x\n", res); 1116 } 1117 #endif 1118 1119 extern char func_lret32; 1120 extern char func_iret32; 1121 1122 void test_misc(void) 1123 { 1124 // char table[256]; 1125 // int res, i; 1126 1127 #if 0 1128 // REINSTATE 1129 for(i=0;i<256;i++) table[i] = 256 - i; 1130 res = 0x12345678; 1131 asm ("xlat" : "=a" (res) : "b" (table), "0" (res)); 1132 printf("xlat: EAX=%08x\n", res); 1133 #endif 1134 #if 0 1135 // REINSTATE 1136 asm volatile ("pushl %%cs ; call %1" 1137 : "=a" (res) 1138 : "m" (func_lret32): "memory", "cc"); 1139 printf("func_lret32=%x\n", res); 1140 1141 asm volatile ("pushfl ; pushl %%cs ; call %1" 1142 : "=a" (res) 1143 : "m" (func_iret32): "memory", "cc"); 1144 printf("func_iret32=%x\n", res); 1145 #endif 1146 #if 0 1147 /* specific popl test */ 1148 asm volatile ("pushq $0x9abcdef12345678 ; popl (%%rsp) ; addq $4,%%rsp" 1149 : "=g" (res)); 1150 printf("popl esp=%x\n", res); 1151 #endif 1152 #if 0 1153 // REINSTATE 1154 /* specific popw test */ 1155 asm volatile ("pushq $12345432 ; pushq $0x9abcdef ; popw (%%rsp) ; addl $2, %%rsp ; popq %0" 1156 : "=g" (res)); 1157 printf("popw rsp=%x\n", res); 1158 #endif 1159 } 1160 1161 uint8_t str_buffer[4096]; 1162 1163 #define TEST_STRING1(OP, size, DF, REP)\ 1164 {\ 1165 int64 rsi, rdi, rax, rcx, rflags;\ 1166 \ 1167 rsi = (long)(str_buffer + sizeof(str_buffer) / 2);\ 1168 rdi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\ 1169 rax = 0x12345678;\ 1170 rcx = 17;\ 1171 \ 1172 asm volatile ("pushq $0\n\t"\ 1173 "popfq\n\t"\ 1174 DF "\n\t"\ 1175 REP #OP size "\n\t"\ 1176 "cld\n\t"\ 1177 "pushfq\n\t"\ 1178 "popq %4\n\t"\ 1179 : "=S" (rsi), "=D" (rdi), "=a" (rax), "=c" (rcx), "=g" (rflags)\ 1180 : "0" (rsi), "1" (rdi), "2" (rax), "3" (rcx));\ 1181 printf("%-10s ESI=%016llx EDI=%016llx EAX=%016llx ECX=%016llx EFL=%04llx\n",\ 1182 REP #OP size, rsi, rdi, rax, rcx,\ 1183 rflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\ 1184 } 1185 1186 #define TEST_STRING(OP, REP)\ 1187 TEST_STRING1(OP, "b", "", REP);\ 1188 TEST_STRING1(OP, "w", "", REP);\ 1189 TEST_STRING1(OP, "l", "", REP);\ 1190 TEST_STRING1(OP, "b", "std", REP);\ 1191 TEST_STRING1(OP, "w", "std", REP);\ 1192 TEST_STRING1(OP, "l", "std", REP) 1193 1194 void test_string(void) 1195 { 1196 int64 i; 1197 for(i = 0;i < sizeof(str_buffer); i++) 1198 str_buffer[i] = i + 0x56; 1199 TEST_STRING(stos, ""); 1200 TEST_STRING(stos, "rep "); 1201 // REINSTATE: TEST_STRING(lods, ""); /* to verify stos */ 1202 // REINSTATE: TEST_STRING(lods, "rep "); 1203 TEST_STRING(movs, ""); 1204 TEST_STRING(movs, "rep "); 1205 // REINSTATE: TEST_STRING(lods, ""); /* to verify stos */ 1206 1207 /* XXX: better tests */ 1208 TEST_STRING(scas, ""); 1209 // REINSTATE: TEST_STRING(scas, "repz "); 1210 TEST_STRING(scas, "repnz "); 1211 // REINSTATE: TEST_STRING(cmps, ""); 1212 TEST_STRING(cmps, "repz "); 1213 // REINSTATE: TEST_STRING(cmps, "repnz "); 1214 } 1215 1216 /* VM86 test */ 1217 #if 0 1218 static inline void set_bit(uint8_t *a, unsigned int bit) 1219 { 1220 a[bit / 8] |= (1 << (bit % 8)); 1221 } 1222 1223 static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) 1224 { 1225 return (uint8_t *)((seg << 4) + (reg & 0xffff)); 1226 } 1227 1228 static inline void pushw(struct vm86_regs *r, int val) 1229 { 1230 r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); 1231 *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; 1232 } 1233 1234 #undef __syscall_return 1235 #define __syscall_return(type, res) \ 1236 do { \ 1237 return (type) (res); \ 1238 } while (0) 1239 1240 _syscall2(int, vm86, int, func, struct vm86plus_struct *, v86) 1241 1242 extern char vm86_code_start; 1243 extern char vm86_code_end; 1244 1245 #define VM86_CODE_CS 0x100 1246 #define VM86_CODE_IP 0x100 1247 1248 void test_vm86(void) 1249 { 1250 struct vm86plus_struct ctx; 1251 struct vm86_regs *r; 1252 uint8_t *vm86_mem; 1253 int seg, ret; 1254 1255 vm86_mem = mmap((void *)0x00000000, 0x110000, 1256 PROT_WRITE | PROT_READ | PROT_EXEC, 1257 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 1258 if (vm86_mem == MAP_FAILED) { 1259 printf("ERROR: could not map vm86 memory"); 1260 return; 1261 } 1262 memset(&ctx, 0, sizeof(ctx)); 1263 1264 /* init basic registers */ 1265 r = &ctx.regs; 1266 r->eip = VM86_CODE_IP; 1267 r->esp = 0xfffe; 1268 seg = VM86_CODE_CS; 1269 r->cs = seg; 1270 r->ss = seg; 1271 r->ds = seg; 1272 r->es = seg; 1273 r->fs = seg; 1274 r->gs = seg; 1275 r->eflags = VIF_MASK; 1276 1277 /* move code to proper address. We use the same layout as a .com 1278 dos program. */ 1279 memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP, 1280 &vm86_code_start, &vm86_code_end - &vm86_code_start); 1281 1282 /* mark int 0x21 as being emulated */ 1283 set_bit((uint8_t *)&ctx.int_revectored, 0x21); 1284 1285 for(;;) { 1286 ret = vm86(VM86_ENTER, &ctx); 1287 switch(VM86_TYPE(ret)) { 1288 case VM86_INTx: 1289 { 1290 int int_num, ah, v; 1291 1292 int_num = VM86_ARG(ret); 1293 if (int_num != 0x21) 1294 goto unknown_int; 1295 ah = (r->eax >> 8) & 0xff; 1296 switch(ah) { 1297 case 0x00: /* exit */ 1298 goto the_end; 1299 case 0x02: /* write char */ 1300 { 1301 uint8_t c = r->edx; 1302 putchar(c); 1303 } 1304 break; 1305 case 0x09: /* write string */ 1306 { 1307 uint8_t c, *ptr; 1308 ptr = seg_to_linear(r->ds, r->edx); 1309 for(;;) { 1310 c = *ptr++; 1311 if (c == '$') 1312 break; 1313 putchar(c); 1314 } 1315 r->eax = (r->eax & ~0xff) | '$'; 1316 } 1317 break; 1318 case 0xff: /* extension: write eflags number in edx */ 1319 v = (int)r->edx; 1320 #ifndef LINUX_VM86_IOPL_FIX 1321 v &= ~0x3000; 1322 #endif 1323 printf("%08x\n", v); 1324 break; 1325 default: 1326 unknown_int: 1327 printf("unsupported int 0x%02x\n", int_num); 1328 goto the_end; 1329 } 1330 } 1331 break; 1332 case VM86_SIGNAL: 1333 /* a signal came, we just ignore that */ 1334 break; 1335 case VM86_STI: 1336 break; 1337 default: 1338 printf("ERROR: unhandled vm86 return code (0x%x)\n", ret); 1339 goto the_end; 1340 } 1341 } 1342 the_end: 1343 printf("VM86 end\n"); 1344 munmap(vm86_mem, 0x110000); 1345 } 1346 #endif 1347 1348 /* exception tests */ 1349 #if 0 1350 #ifndef REG_EAX 1351 #define REG_EAX EAX 1352 #define REG_EBX EBX 1353 #define REG_ECX ECX 1354 #define REG_EDX EDX 1355 #define REG_ESI ESI 1356 #define REG_EDI EDI 1357 #define REG_EBP EBP 1358 #define REG_ESP ESP 1359 #define REG_EIP EIP 1360 #define REG_EFL EFL 1361 #define REG_TRAPNO TRAPNO 1362 #define REG_ERR ERR 1363 #endif 1364 1365 jmp_buf jmp_env; 1366 int v1; 1367 int tab[2]; 1368 1369 void sig_handler(int sig, siginfo_t *info, void *puc) 1370 { 1371 struct ucontext *uc = puc; 1372 1373 printf("si_signo=%d si_errno=%d si_code=%d", 1374 info->si_signo, info->si_errno, info->si_code); 1375 printf(" si_addr=0x%08lx", 1376 (unsigned long)info->si_addr); 1377 printf("\n"); 1378 1379 printf("trapno=0x%02x err=0x%08x", 1380 uc->uc_mcontext.gregs[REG_TRAPNO], 1381 uc->uc_mcontext.gregs[REG_ERR]); 1382 printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]); 1383 printf("\n"); 1384 longjmp(jmp_env, 1); 1385 } 1386 1387 void test_exceptions(void) 1388 { 1389 struct modify_ldt_ldt_s ldt; 1390 struct sigaction act; 1391 volatile int val; 1392 1393 act.sa_sigaction = sig_handler; 1394 sigemptyset(&act.sa_mask); 1395 act.sa_flags = SA_SIGINFO; 1396 sigaction(SIGFPE, &act, NULL); 1397 sigaction(SIGILL, &act, NULL); 1398 sigaction(SIGSEGV, &act, NULL); 1399 sigaction(SIGBUS, &act, NULL); 1400 sigaction(SIGTRAP, &act, NULL); 1401 1402 /* test division by zero reporting */ 1403 printf("DIVZ exception:\n"); 1404 if (setjmp(jmp_env) == 0) { 1405 /* now divide by zero */ 1406 v1 = 0; 1407 v1 = 2 / v1; 1408 } 1409 1410 printf("BOUND exception:\n"); 1411 if (setjmp(jmp_env) == 0) { 1412 /* bound exception */ 1413 tab[0] = 1; 1414 tab[1] = 10; 1415 asm volatile ("bound %0, %1" : : "r" (11), "m" (tab)); 1416 } 1417 1418 printf("segment exceptions:\n"); 1419 if (setjmp(jmp_env) == 0) { 1420 /* load an invalid segment */ 1421 asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1)); 1422 } 1423 if (setjmp(jmp_env) == 0) { 1424 /* null data segment is valid */ 1425 asm volatile ("movl %0, %%fs" : : "r" (3)); 1426 /* null stack segment */ 1427 asm volatile ("movl %0, %%ss" : : "r" (3)); 1428 } 1429 1430 ldt.entry_number = 1; 1431 ldt.base_addr = (unsigned long)&seg_data1; 1432 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; 1433 ldt.seg_32bit = 1; 1434 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1435 ldt.read_exec_only = 0; 1436 ldt.limit_in_pages = 1; 1437 ldt.seg_not_present = 1; 1438 ldt.useable = 1; 1439 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1440 1441 if (setjmp(jmp_env) == 0) { 1442 /* segment not present */ 1443 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); 1444 } 1445 1446 /* test SEGV reporting */ 1447 printf("PF exception:\n"); 1448 if (setjmp(jmp_env) == 0) { 1449 val = 1; 1450 /* we add a nop to test a weird PC retrieval case */ 1451 asm volatile ("nop"); 1452 /* now store in an invalid address */ 1453 *(char *)0x1234 = 1; 1454 } 1455 1456 /* test SEGV reporting */ 1457 printf("PF exception:\n"); 1458 if (setjmp(jmp_env) == 0) { 1459 val = 1; 1460 /* read from an invalid address */ 1461 v1 = *(char *)0x1234; 1462 } 1463 1464 /* test illegal instruction reporting */ 1465 printf("UD2 exception:\n"); 1466 if (setjmp(jmp_env) == 0) { 1467 /* now execute an invalid instruction */ 1468 asm volatile("ud2"); 1469 } 1470 printf("lock nop exception:\n"); 1471 if (setjmp(jmp_env) == 0) { 1472 /* now execute an invalid instruction */ 1473 asm volatile("lock nop"); 1474 } 1475 1476 printf("INT exception:\n"); 1477 if (setjmp(jmp_env) == 0) { 1478 asm volatile ("int $0xfd"); 1479 } 1480 if (setjmp(jmp_env) == 0) { 1481 asm volatile ("int $0x01"); 1482 } 1483 if (setjmp(jmp_env) == 0) { 1484 asm volatile (".byte 0xcd, 0x03"); 1485 } 1486 if (setjmp(jmp_env) == 0) { 1487 asm volatile ("int $0x04"); 1488 } 1489 if (setjmp(jmp_env) == 0) { 1490 asm volatile ("int $0x05"); 1491 } 1492 1493 printf("INT3 exception:\n"); 1494 if (setjmp(jmp_env) == 0) { 1495 asm volatile ("int3"); 1496 } 1497 1498 printf("CLI exception:\n"); 1499 if (setjmp(jmp_env) == 0) { 1500 asm volatile ("cli"); 1501 } 1502 1503 printf("STI exception:\n"); 1504 if (setjmp(jmp_env) == 0) { 1505 asm volatile ("cli"); 1506 } 1507 1508 printf("INTO exception:\n"); 1509 if (setjmp(jmp_env) == 0) { 1510 /* overflow exception */ 1511 asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff)); 1512 } 1513 1514 printf("OUTB exception:\n"); 1515 if (setjmp(jmp_env) == 0) { 1516 asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0)); 1517 } 1518 1519 printf("INB exception:\n"); 1520 if (setjmp(jmp_env) == 0) { 1521 asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321)); 1522 } 1523 1524 printf("REP OUTSB exception:\n"); 1525 if (setjmp(jmp_env) == 0) { 1526 asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1)); 1527 } 1528 1529 printf("REP INSB exception:\n"); 1530 if (setjmp(jmp_env) == 0) { 1531 asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1)); 1532 } 1533 1534 printf("HLT exception:\n"); 1535 if (setjmp(jmp_env) == 0) { 1536 asm volatile ("hlt"); 1537 } 1538 1539 printf("single step exception:\n"); 1540 val = 0; 1541 if (setjmp(jmp_env) == 0) { 1542 asm volatile ("pushf\n" 1543 "orl $0x00100, (%%esp)\n" 1544 "popf\n" 1545 "movl $0xabcd, %0\n" 1546 "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory"); 1547 } 1548 printf("val=0x%x\n", val); 1549 } 1550 1551 /* specific precise single step test */ 1552 void sig_trap_handler(int sig, siginfo_t *info, void *puc) 1553 { 1554 struct ucontext *uc = puc; 1555 printf("EIP=0x%08x\n", uc->uc_mcontext.gregs[REG_EIP]); 1556 } 1557 1558 const uint8_t sstep_buf1[4] = { 1, 2, 3, 4}; 1559 uint8_t sstep_buf2[4]; 1560 1561 void test_single_step(void) 1562 { 1563 struct sigaction act; 1564 volatile int val; 1565 int i; 1566 1567 val = 0; 1568 act.sa_sigaction = sig_trap_handler; 1569 sigemptyset(&act.sa_mask); 1570 act.sa_flags = SA_SIGINFO; 1571 sigaction(SIGTRAP, &act, NULL); 1572 asm volatile ("pushf\n" 1573 "orl $0x00100, (%%esp)\n" 1574 "popf\n" 1575 "movl $0xabcd, %0\n" 1576 1577 /* jmp test */ 1578 "movl $3, %%ecx\n" 1579 "1:\n" 1580 "addl $1, %0\n" 1581 "decl %%ecx\n" 1582 "jnz 1b\n" 1583 1584 /* movsb: the single step should stop at each movsb iteration */ 1585 "movl $sstep_buf1, %%esi\n" 1586 "movl $sstep_buf2, %%edi\n" 1587 "movl $0, %%ecx\n" 1588 "rep movsb\n" 1589 "movl $3, %%ecx\n" 1590 "rep movsb\n" 1591 "movl $1, %%ecx\n" 1592 "rep movsb\n" 1593 1594 /* cmpsb: the single step should stop at each cmpsb iteration */ 1595 "movl $sstep_buf1, %%esi\n" 1596 "movl $sstep_buf2, %%edi\n" 1597 "movl $0, %%ecx\n" 1598 "rep cmpsb\n" 1599 "movl $4, %%ecx\n" 1600 "rep cmpsb\n" 1601 1602 /* getpid() syscall: single step should skip one 1603 instruction */ 1604 "movl $20, %%eax\n" 1605 "int $0x80\n" 1606 "movl $0, %%eax\n" 1607 1608 /* when modifying SS, trace is not done on the next 1609 instruction */ 1610 "movl %%ss, %%ecx\n" 1611 "movl %%ecx, %%ss\n" 1612 "addl $1, %0\n" 1613 "movl $1, %%eax\n" 1614 "movl %%ecx, %%ss\n" 1615 "jmp 1f\n" 1616 "addl $1, %0\n" 1617 "1:\n" 1618 "movl $1, %%eax\n" 1619 "pushl %%ecx\n" 1620 "popl %%ss\n" 1621 "addl $1, %0\n" 1622 "movl $1, %%eax\n" 1623 1624 "pushf\n" 1625 "andl $~0x00100, (%%esp)\n" 1626 "popf\n" 1627 : "=m" (val) 1628 : 1629 : "cc", "memory", "eax", "ecx", "esi", "edi"); 1630 printf("val=%d\n", val); 1631 for(i = 0; i < 4; i++) 1632 printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]); 1633 } 1634 1635 /* self modifying code test */ 1636 uint8_t code[] = { 1637 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */ 1638 0xc3, /* ret */ 1639 }; 1640 1641 asm("smc_code2:\n" 1642 "movl 4(%esp), %eax\n" 1643 "movl %eax, smc_patch_addr2 + 1\n" 1644 "nop\n" 1645 "nop\n" 1646 "nop\n" 1647 "nop\n" 1648 "nop\n" 1649 "nop\n" 1650 "nop\n" 1651 "nop\n" 1652 "smc_patch_addr2:\n" 1653 "movl $1, %eax\n" 1654 "ret\n"); 1655 1656 typedef int FuncType(void); 1657 extern int smc_code2(int); 1658 void test_self_modifying_code(void) 1659 { 1660 int i; 1661 1662 printf("self modifying code:\n"); 1663 printf("func1 = 0x%x\n", ((FuncType *)code)()); 1664 for(i = 2; i <= 4; i++) { 1665 code[1] = i; 1666 printf("func%d = 0x%x\n", i, ((FuncType *)code)()); 1667 } 1668 1669 /* more difficult test : the modified code is just after the 1670 modifying instruction. It is forbidden in Intel specs, but it 1671 is used by old DOS programs */ 1672 for(i = 2; i <= 4; i++) { 1673 printf("smc_code2(%d) = %d\n", i, smc_code2(i)); 1674 } 1675 } 1676 1677 static void *call_end __init_call = NULL; 1678 #endif 1679 1680 int main(int argc, char **argv) 1681 { 1682 void **ptr; 1683 void (*func)(void); 1684 1685 #if 1 1686 ptr = &call_start + 1; 1687 while (*ptr != NULL) { 1688 func = *ptr++; 1689 func(); 1690 } 1691 #endif 1692 test_bsx(); //REINSTATE64 1693 test_mul(); 1694 test_jcc(); 1695 // test_floats(); REINSTATE64 1696 //test_bcd(); 1697 //test_xchg(); REINSTATE64 1698 test_string(); 1699 //test_misc(); // REINSTATE 1700 test_lea(); 1701 // test_segs(); 1702 //test_code16(); 1703 //test_vm86(); 1704 //test_exceptions(); 1705 //test_self_modifying_code(); 1706 //test_single_step(); 1707 printf("bye\n"); 1708 return 0; 1709 } 1710