1 /* 2 * x86 CPU test 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #define _GNU_SOURCE 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <inttypes.h> 24 #include <math.h> 25 #include <signal.h> 26 #include <setjmp.h> 27 #include <errno.h> 28 #include <sys/ucontext.h> 29 #include <sys/mman.h> 30 31 #if !defined(__x86_64__) 32 //#define TEST_VM86 33 #define TEST_SEGS 34 #endif 35 //#define LINUX_VM86_IOPL_FIX 36 //#define TEST_P4_FLAGS 37 #define TEST_CMOV 1 38 #define TEST_FCOMI 1 39 40 #if defined(__x86_64__) 41 #define FMT64X "%016lx" 42 #define FMTLX "%016lx" 43 #define X86_64_ONLY(x) x 44 #else 45 #define FMT64X "%016" PRIx64 46 #define FMTLX "%08lx" 47 #define X86_64_ONLY(x) 48 #endif 49 50 #ifdef TEST_VM86 51 #include <asm/vm86.h> 52 #endif 53 54 #define xglue(x, y) x ## y 55 #define glue(x, y) xglue(x, y) 56 #define stringify(s) tostring(s) 57 #define tostring(s) #s 58 59 #define CC_C 0x0001 60 #define CC_P 0x0004 61 #define CC_A 0x0010 62 #define CC_Z 0x0040 63 #define CC_S 0x0080 64 #define CC_O 0x0800 65 66 #define __init_call __attribute__ ((unused,__section__ ("initcall"))) 67 68 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) 69 70 #if defined(__x86_64__) 71 static inline long i2l(long v) 72 { 73 return v | ((v ^ 0xabcd) << 32); 74 } 75 #else 76 static inline long i2l(long v) 77 { 78 return v; 79 } 80 #endif 81 82 #define OP add 83 #include "test-i386.h" 84 85 #define OP sub 86 #include "test-i386.h" 87 88 #define OP xor 89 #include "test-i386.h" 90 91 #define OP and 92 #include "test-i386.h" 93 94 #define OP or 95 #include "test-i386.h" 96 97 #define OP cmp 98 #include "test-i386.h" 99 100 #define OP adc 101 #define OP_CC 102 #include "test-i386.h" 103 104 #define OP sbb 105 #define OP_CC 106 #include "test-i386.h" 107 108 #define OP inc 109 #define OP_CC 110 #define OP1 111 #include "test-i386.h" 112 113 #define OP dec 114 #define OP_CC 115 #define OP1 116 #include "test-i386.h" 117 118 #define OP neg 119 #define OP_CC 120 #define OP1 121 #include "test-i386.h" 122 123 #define OP not 124 #define OP_CC 125 #define OP1 126 #include "test-i386.h" 127 128 #undef CC_MASK 129 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O) 130 131 #define OP shl 132 #include "test-i386-shift.h" 133 134 #define OP shr 135 #include "test-i386-shift.h" 136 137 #define OP sar 138 #include "test-i386-shift.h" 139 140 #define OP rol 141 #include "test-i386-shift.h" 142 143 #define OP ror 144 #include "test-i386-shift.h" 145 146 #define OP rcr 147 #define OP_CC 148 #include "test-i386-shift.h" 149 150 #define OP rcl 151 #define OP_CC 152 #include "test-i386-shift.h" 153 154 #define OP shld 155 #define OP_SHIFTD 156 #define OP_NOBYTE 157 #include "test-i386-shift.h" 158 159 #define OP shrd 160 #define OP_SHIFTD 161 #define OP_NOBYTE 162 #include "test-i386-shift.h" 163 164 /* XXX: should be more precise ? */ 165 #undef CC_MASK 166 #define CC_MASK (CC_C) 167 168 #define OP bt 169 #define OP_NOBYTE 170 #include "test-i386-shift.h" 171 172 #define OP bts 173 #define OP_NOBYTE 174 #include "test-i386-shift.h" 175 176 #define OP btr 177 #define OP_NOBYTE 178 #include "test-i386-shift.h" 179 180 #define OP btc 181 #define OP_NOBYTE 182 #include "test-i386-shift.h" 183 184 /* lea test (modrm support) */ 185 #define TEST_LEAQ(STR)\ 186 {\ 187 asm("lea " STR ", %0"\ 188 : "=r" (res)\ 189 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ 190 printf("lea %s = " FMTLX "\n", STR, res);\ 191 } 192 193 #define TEST_LEA(STR)\ 194 {\ 195 asm("lea " STR ", %0"\ 196 : "=r" (res)\ 197 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ 198 printf("lea %s = " FMTLX "\n", STR, res);\ 199 } 200 201 #define TEST_LEA16(STR)\ 202 {\ 203 asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\ 204 : "=r" (res)\ 205 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ 206 printf("lea %s = %08lx\n", STR, res);\ 207 } 208 209 210 void test_lea(void) 211 { 212 long eax, ebx, ecx, edx, esi, edi, res; 213 eax = i2l(0x0001); 214 ebx = i2l(0x0002); 215 ecx = i2l(0x0004); 216 edx = i2l(0x0008); 217 esi = i2l(0x0010); 218 edi = i2l(0x0020); 219 220 TEST_LEA("0x4000"); 221 222 TEST_LEA("(%%eax)"); 223 TEST_LEA("(%%ebx)"); 224 TEST_LEA("(%%ecx)"); 225 TEST_LEA("(%%edx)"); 226 TEST_LEA("(%%esi)"); 227 TEST_LEA("(%%edi)"); 228 229 TEST_LEA("0x40(%%eax)"); 230 TEST_LEA("0x40(%%ebx)"); 231 TEST_LEA("0x40(%%ecx)"); 232 TEST_LEA("0x40(%%edx)"); 233 TEST_LEA("0x40(%%esi)"); 234 TEST_LEA("0x40(%%edi)"); 235 236 TEST_LEA("0x4000(%%eax)"); 237 TEST_LEA("0x4000(%%ebx)"); 238 TEST_LEA("0x4000(%%ecx)"); 239 TEST_LEA("0x4000(%%edx)"); 240 TEST_LEA("0x4000(%%esi)"); 241 TEST_LEA("0x4000(%%edi)"); 242 243 TEST_LEA("(%%eax, %%ecx)"); 244 TEST_LEA("(%%ebx, %%edx)"); 245 TEST_LEA("(%%ecx, %%ecx)"); 246 TEST_LEA("(%%edx, %%ecx)"); 247 TEST_LEA("(%%esi, %%ecx)"); 248 TEST_LEA("(%%edi, %%ecx)"); 249 250 TEST_LEA("0x40(%%eax, %%ecx)"); 251 TEST_LEA("0x4000(%%ebx, %%edx)"); 252 253 TEST_LEA("(%%ecx, %%ecx, 2)"); 254 TEST_LEA("(%%edx, %%ecx, 4)"); 255 TEST_LEA("(%%esi, %%ecx, 8)"); 256 257 TEST_LEA("(,%%eax, 2)"); 258 TEST_LEA("(,%%ebx, 4)"); 259 TEST_LEA("(,%%ecx, 8)"); 260 261 TEST_LEA("0x40(,%%eax, 2)"); 262 TEST_LEA("0x40(,%%ebx, 4)"); 263 TEST_LEA("0x40(,%%ecx, 8)"); 264 265 266 TEST_LEA("-10(%%ecx, %%ecx, 2)"); 267 TEST_LEA("-10(%%edx, %%ecx, 4)"); 268 TEST_LEA("-10(%%esi, %%ecx, 8)"); 269 270 TEST_LEA("0x4000(%%ecx, %%ecx, 2)"); 271 TEST_LEA("0x4000(%%edx, %%ecx, 4)"); 272 TEST_LEA("0x4000(%%esi, %%ecx, 8)"); 273 274 #if defined(__x86_64__) 275 TEST_LEAQ("0x4000"); 276 TEST_LEAQ("0x4000(%%rip)"); 277 278 TEST_LEAQ("(%%rax)"); 279 TEST_LEAQ("(%%rbx)"); 280 TEST_LEAQ("(%%rcx)"); 281 TEST_LEAQ("(%%rdx)"); 282 TEST_LEAQ("(%%rsi)"); 283 TEST_LEAQ("(%%rdi)"); 284 285 TEST_LEAQ("0x40(%%rax)"); 286 TEST_LEAQ("0x40(%%rbx)"); 287 TEST_LEAQ("0x40(%%rcx)"); 288 TEST_LEAQ("0x40(%%rdx)"); 289 TEST_LEAQ("0x40(%%rsi)"); 290 TEST_LEAQ("0x40(%%rdi)"); 291 292 TEST_LEAQ("0x4000(%%rax)"); 293 TEST_LEAQ("0x4000(%%rbx)"); 294 TEST_LEAQ("0x4000(%%rcx)"); 295 TEST_LEAQ("0x4000(%%rdx)"); 296 TEST_LEAQ("0x4000(%%rsi)"); 297 TEST_LEAQ("0x4000(%%rdi)"); 298 299 TEST_LEAQ("(%%rax, %%rcx)"); 300 TEST_LEAQ("(%%rbx, %%rdx)"); 301 TEST_LEAQ("(%%rcx, %%rcx)"); 302 TEST_LEAQ("(%%rdx, %%rcx)"); 303 TEST_LEAQ("(%%rsi, %%rcx)"); 304 TEST_LEAQ("(%%rdi, %%rcx)"); 305 306 TEST_LEAQ("0x40(%%rax, %%rcx)"); 307 TEST_LEAQ("0x4000(%%rbx, %%rdx)"); 308 309 TEST_LEAQ("(%%rcx, %%rcx, 2)"); 310 TEST_LEAQ("(%%rdx, %%rcx, 4)"); 311 TEST_LEAQ("(%%rsi, %%rcx, 8)"); 312 313 TEST_LEAQ("(,%%rax, 2)"); 314 TEST_LEAQ("(,%%rbx, 4)"); 315 TEST_LEAQ("(,%%rcx, 8)"); 316 317 TEST_LEAQ("0x40(,%%rax, 2)"); 318 TEST_LEAQ("0x40(,%%rbx, 4)"); 319 TEST_LEAQ("0x40(,%%rcx, 8)"); 320 321 322 TEST_LEAQ("-10(%%rcx, %%rcx, 2)"); 323 TEST_LEAQ("-10(%%rdx, %%rcx, 4)"); 324 TEST_LEAQ("-10(%%rsi, %%rcx, 8)"); 325 326 TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)"); 327 TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)"); 328 TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)"); 329 #else 330 /* limited 16 bit addressing test */ 331 TEST_LEA16("0x4000"); 332 TEST_LEA16("(%%bx)"); 333 TEST_LEA16("(%%si)"); 334 TEST_LEA16("(%%di)"); 335 TEST_LEA16("0x40(%%bx)"); 336 TEST_LEA16("0x40(%%si)"); 337 TEST_LEA16("0x40(%%di)"); 338 TEST_LEA16("0x4000(%%bx)"); 339 TEST_LEA16("0x4000(%%si)"); 340 TEST_LEA16("(%%bx,%%si)"); 341 TEST_LEA16("(%%bx,%%di)"); 342 TEST_LEA16("0x40(%%bx,%%si)"); 343 TEST_LEA16("0x40(%%bx,%%di)"); 344 TEST_LEA16("0x4000(%%bx,%%si)"); 345 TEST_LEA16("0x4000(%%bx,%%di)"); 346 #endif 347 } 348 349 #define TEST_JCC(JCC, v1, v2)\ 350 {\ 351 int res;\ 352 asm("movl $1, %0\n\t"\ 353 "cmpl %2, %1\n\t"\ 354 "j" JCC " 1f\n\t"\ 355 "movl $0, %0\n\t"\ 356 "1:\n\t"\ 357 : "=r" (res)\ 358 : "r" (v1), "r" (v2));\ 359 printf("%-10s %d\n", "j" JCC, res);\ 360 \ 361 asm("movl $0, %0\n\t"\ 362 "cmpl %2, %1\n\t"\ 363 "set" JCC " %b0\n\t"\ 364 : "=r" (res)\ 365 : "r" (v1), "r" (v2));\ 366 printf("%-10s %d\n", "set" JCC, res);\ 367 if (TEST_CMOV) {\ 368 long val = i2l(1);\ 369 long res = i2l(0x12345678);\ 370 X86_64_ONLY(\ 371 asm("cmpl %2, %1\n\t"\ 372 "cmov" JCC "q %3, %0\n\t"\ 373 : "=r" (res)\ 374 : "r" (v1), "r" (v2), "m" (val), "0" (res));\ 375 printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\ 376 asm("cmpl %2, %1\n\t"\ 377 "cmov" JCC "l %k3, %k0\n\t"\ 378 : "=r" (res)\ 379 : "r" (v1), "r" (v2), "m" (val), "0" (res));\ 380 printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\ 381 asm("cmpl %2, %1\n\t"\ 382 "cmov" JCC "w %w3, %w0\n\t"\ 383 : "=r" (res)\ 384 : "r" (v1), "r" (v2), "r" (1), "0" (res));\ 385 printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\ 386 } \ 387 } 388 389 /* various jump tests */ 390 void test_jcc(void) 391 { 392 TEST_JCC("ne", 1, 1); 393 TEST_JCC("ne", 1, 0); 394 395 TEST_JCC("e", 1, 1); 396 TEST_JCC("e", 1, 0); 397 398 TEST_JCC("l", 1, 1); 399 TEST_JCC("l", 1, 0); 400 TEST_JCC("l", 1, -1); 401 402 TEST_JCC("le", 1, 1); 403 TEST_JCC("le", 1, 0); 404 TEST_JCC("le", 1, -1); 405 406 TEST_JCC("ge", 1, 1); 407 TEST_JCC("ge", 1, 0); 408 TEST_JCC("ge", -1, 1); 409 410 TEST_JCC("g", 1, 1); 411 TEST_JCC("g", 1, 0); 412 TEST_JCC("g", 1, -1); 413 414 TEST_JCC("b", 1, 1); 415 TEST_JCC("b", 1, 0); 416 TEST_JCC("b", 1, -1); 417 418 TEST_JCC("be", 1, 1); 419 TEST_JCC("be", 1, 0); 420 TEST_JCC("be", 1, -1); 421 422 TEST_JCC("ae", 1, 1); 423 TEST_JCC("ae", 1, 0); 424 TEST_JCC("ae", 1, -1); 425 426 TEST_JCC("a", 1, 1); 427 TEST_JCC("a", 1, 0); 428 TEST_JCC("a", 1, -1); 429 430 431 TEST_JCC("p", 1, 1); 432 TEST_JCC("p", 1, 0); 433 434 TEST_JCC("np", 1, 1); 435 TEST_JCC("np", 1, 0); 436 437 TEST_JCC("o", 0x7fffffff, 0); 438 TEST_JCC("o", 0x7fffffff, -1); 439 440 TEST_JCC("no", 0x7fffffff, 0); 441 TEST_JCC("no", 0x7fffffff, -1); 442 443 TEST_JCC("s", 0, 1); 444 TEST_JCC("s", 0, -1); 445 TEST_JCC("s", 0, 0); 446 447 TEST_JCC("ns", 0, 1); 448 TEST_JCC("ns", 0, -1); 449 TEST_JCC("ns", 0, 0); 450 } 451 452 #define TEST_LOOP(insn) \ 453 {\ 454 for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\ 455 ecx = ecx_vals[i];\ 456 for(zf = 0; zf < 2; zf++) {\ 457 asm("test %2, %2\n\t"\ 458 "movl $1, %0\n\t"\ 459 insn " 1f\n\t" \ 460 "movl $0, %0\n\t"\ 461 "1:\n\t"\ 462 : "=a" (res)\ 463 : "c" (ecx), "b" (!zf)); \ 464 printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res); \ 465 }\ 466 }\ 467 } 468 469 void test_loop(void) 470 { 471 long ecx, zf; 472 const long ecx_vals[] = { 473 0, 474 1, 475 0x10000, 476 0x10001, 477 #if defined(__x86_64__) 478 0x100000000L, 479 0x100000001L, 480 #endif 481 }; 482 int i, res; 483 484 #if !defined(__x86_64__) 485 TEST_LOOP("jcxz"); 486 TEST_LOOP("loopw"); 487 TEST_LOOP("loopzw"); 488 TEST_LOOP("loopnzw"); 489 #endif 490 491 TEST_LOOP("jecxz"); 492 TEST_LOOP("loopl"); 493 TEST_LOOP("loopzl"); 494 TEST_LOOP("loopnzl"); 495 } 496 497 #undef CC_MASK 498 #ifdef TEST_P4_FLAGS 499 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) 500 #else 501 #define CC_MASK (CC_O | CC_C) 502 #endif 503 504 #define OP mul 505 #include "test-i386-muldiv.h" 506 507 #define OP imul 508 #include "test-i386-muldiv.h" 509 510 void test_imulw2(long op0, long op1) 511 { 512 long res, s1, s0, flags; 513 s0 = op0; 514 s1 = op1; 515 res = s0; 516 flags = 0; 517 asm volatile ("push %4\n\t" 518 "popf\n\t" 519 "imulw %w2, %w0\n\t" 520 "pushf\n\t" 521 "pop %1\n\t" 522 : "=q" (res), "=g" (flags) 523 : "q" (s1), "0" (res), "1" (flags)); 524 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n", 525 "imulw", s0, s1, res, flags & CC_MASK); 526 } 527 528 void test_imull2(long op0, long op1) 529 { 530 long res, s1, s0, flags; 531 s0 = op0; 532 s1 = op1; 533 res = s0; 534 flags = 0; 535 asm volatile ("push %4\n\t" 536 "popf\n\t" 537 "imull %k2, %k0\n\t" 538 "pushf\n\t" 539 "pop %1\n\t" 540 : "=q" (res), "=g" (flags) 541 : "q" (s1), "0" (res), "1" (flags)); 542 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n", 543 "imull", s0, s1, res, flags & CC_MASK); 544 } 545 546 #if defined(__x86_64__) 547 void test_imulq2(long op0, long op1) 548 { 549 long res, s1, s0, flags; 550 s0 = op0; 551 s1 = op1; 552 res = s0; 553 flags = 0; 554 asm volatile ("push %4\n\t" 555 "popf\n\t" 556 "imulq %2, %0\n\t" 557 "pushf\n\t" 558 "pop %1\n\t" 559 : "=q" (res), "=g" (flags) 560 : "q" (s1), "0" (res), "1" (flags)); 561 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n", 562 "imulq", s0, s1, res, flags & CC_MASK); 563 } 564 #endif 565 566 #define TEST_IMUL_IM(size, rsize, op0, op1)\ 567 {\ 568 long res, flags, s1;\ 569 flags = 0;\ 570 res = 0;\ 571 s1 = op1;\ 572 asm volatile ("push %3\n\t"\ 573 "popf\n\t"\ 574 "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \ 575 "pushf\n\t"\ 576 "pop %1\n\t"\ 577 : "=r" (res), "=g" (flags)\ 578 : "r" (s1), "1" (flags), "0" (res));\ 579 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\ 580 "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\ 581 } 582 583 584 #undef CC_MASK 585 #define CC_MASK (0) 586 587 #define OP div 588 #include "test-i386-muldiv.h" 589 590 #define OP idiv 591 #include "test-i386-muldiv.h" 592 593 void test_mul(void) 594 { 595 test_imulb(0x1234561d, 4); 596 test_imulb(3, -4); 597 test_imulb(0x80, 0x80); 598 test_imulb(0x10, 0x10); 599 600 test_imulw(0, 0x1234001d, 45); 601 test_imulw(0, 23, -45); 602 test_imulw(0, 0x8000, 0x8000); 603 test_imulw(0, 0x100, 0x100); 604 605 test_imull(0, 0x1234001d, 45); 606 test_imull(0, 23, -45); 607 test_imull(0, 0x80000000, 0x80000000); 608 test_imull(0, 0x10000, 0x10000); 609 610 test_mulb(0x1234561d, 4); 611 test_mulb(3, -4); 612 test_mulb(0x80, 0x80); 613 test_mulb(0x10, 0x10); 614 615 test_mulw(0, 0x1234001d, 45); 616 test_mulw(0, 23, -45); 617 test_mulw(0, 0x8000, 0x8000); 618 test_mulw(0, 0x100, 0x100); 619 620 test_mull(0, 0x1234001d, 45); 621 test_mull(0, 23, -45); 622 test_mull(0, 0x80000000, 0x80000000); 623 test_mull(0, 0x10000, 0x10000); 624 625 test_imulw2(0x1234001d, 45); 626 test_imulw2(23, -45); 627 test_imulw2(0x8000, 0x8000); 628 test_imulw2(0x100, 0x100); 629 630 test_imull2(0x1234001d, 45); 631 test_imull2(23, -45); 632 test_imull2(0x80000000, 0x80000000); 633 test_imull2(0x10000, 0x10000); 634 635 TEST_IMUL_IM("w", "w", 45, 0x1234); 636 TEST_IMUL_IM("w", "w", -45, 23); 637 TEST_IMUL_IM("w", "w", 0x8000, 0x80000000); 638 TEST_IMUL_IM("w", "w", 0x7fff, 0x1000); 639 640 TEST_IMUL_IM("l", "k", 45, 0x1234); 641 TEST_IMUL_IM("l", "k", -45, 23); 642 TEST_IMUL_IM("l", "k", 0x8000, 0x80000000); 643 TEST_IMUL_IM("l", "k", 0x7fff, 0x1000); 644 645 test_idivb(0x12341678, 0x127e); 646 test_idivb(0x43210123, -5); 647 test_idivb(0x12340004, -1); 648 649 test_idivw(0, 0x12345678, 12347); 650 test_idivw(0, -23223, -45); 651 test_idivw(0, 0x12348000, -1); 652 test_idivw(0x12343, 0x12345678, 0x81238567); 653 654 test_idivl(0, 0x12345678, 12347); 655 test_idivl(0, -233223, -45); 656 test_idivl(0, 0x80000000, -1); 657 test_idivl(0x12343, 0x12345678, 0x81234567); 658 659 test_divb(0x12341678, 0x127e); 660 test_divb(0x43210123, -5); 661 test_divb(0x12340004, -1); 662 663 test_divw(0, 0x12345678, 12347); 664 test_divw(0, -23223, -45); 665 test_divw(0, 0x12348000, -1); 666 test_divw(0x12343, 0x12345678, 0x81238567); 667 668 test_divl(0, 0x12345678, 12347); 669 test_divl(0, -233223, -45); 670 test_divl(0, 0x80000000, -1); 671 test_divl(0x12343, 0x12345678, 0x81234567); 672 673 #if defined(__x86_64__) 674 test_imulq(0, 0x1234001d1234001d, 45); 675 test_imulq(0, 23, -45); 676 test_imulq(0, 0x8000000000000000, 0x8000000000000000); 677 test_imulq(0, 0x100000000, 0x100000000); 678 679 test_mulq(0, 0x1234001d1234001d, 45); 680 test_mulq(0, 23, -45); 681 test_mulq(0, 0x8000000000000000, 0x8000000000000000); 682 test_mulq(0, 0x100000000, 0x100000000); 683 684 test_imulq2(0x1234001d1234001d, 45); 685 test_imulq2(23, -45); 686 test_imulq2(0x8000000000000000, 0x8000000000000000); 687 test_imulq2(0x100000000, 0x100000000); 688 689 TEST_IMUL_IM("q", "", 45, 0x12341234); 690 TEST_IMUL_IM("q", "", -45, 23); 691 TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000); 692 TEST_IMUL_IM("q", "", 0x7fff, 0x10000000); 693 694 test_idivq(0, 0x12345678abcdef, 12347); 695 test_idivq(0, -233223, -45); 696 test_idivq(0, 0x8000000000000000, -1); 697 test_idivq(0x12343, 0x12345678, 0x81234567); 698 699 test_divq(0, 0x12345678abcdef, 12347); 700 test_divq(0, -233223, -45); 701 test_divq(0, 0x8000000000000000, -1); 702 test_divq(0x12343, 0x12345678, 0x81234567); 703 #endif 704 } 705 706 #define TEST_BSX(op, size, op0)\ 707 {\ 708 long res, val, resz;\ 709 val = op0;\ 710 asm("xor %1, %1\n"\ 711 "mov $0x12345678, %0\n"\ 712 #op " %" size "2, %" size "0 ; setz %b1" \ 713 : "=&r" (res), "=&q" (resz)\ 714 : "r" (val));\ 715 printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\ 716 } 717 718 void test_xcnt(void) 719 { 720 TEST_BSX(tzcntw, "w", 0); 721 TEST_BSX(tzcntw, "w", 0x12340128); 722 TEST_BSX(lzcntw, "w", 0); 723 TEST_BSX(lzcntw, "w", 0x12340128); 724 TEST_BSX(popcntw, "w", 0); 725 TEST_BSX(popcntw, "w", 0x12340128); 726 TEST_BSX(tzcntl, "k", 0); 727 TEST_BSX(tzcntl, "k", 0x00340128); 728 TEST_BSX(lzcntl, "k", 0); 729 TEST_BSX(lzcntl, "k", 0x00340128); 730 TEST_BSX(popcntl, "k", 0); 731 TEST_BSX(popcntl, "k", 0x00340128); 732 #if defined(__x86_64__) 733 TEST_BSX(tzcntq, "", 0); 734 TEST_BSX(tzcntq, "", 0x003401281234); 735 TEST_BSX(lzcntq, "", 0); 736 TEST_BSX(lzcntq, "", 0x003401281234); 737 TEST_BSX(popcntq, "", 0); 738 TEST_BSX(popcntq, "", 0x003401281234); 739 #endif 740 } 741 742 void test_bsx(void) 743 { 744 TEST_BSX(bsrw, "w", 0); 745 TEST_BSX(bsrw, "w", 0x12340128); 746 TEST_BSX(bsfw, "w", 0); 747 TEST_BSX(bsfw, "w", 0x12340128); 748 TEST_BSX(bsrl, "k", 0); 749 TEST_BSX(bsrl, "k", 0x00340128); 750 TEST_BSX(bsfl, "k", 0); 751 TEST_BSX(bsfl, "k", 0x00340128); 752 #if defined(__x86_64__) 753 TEST_BSX(bsrq, "", 0); 754 TEST_BSX(bsrq, "", 0x003401281234); 755 TEST_BSX(bsfq, "", 0); 756 TEST_BSX(bsfq, "", 0x003401281234); 757 #endif 758 } 759 760 /**********************************************/ 761 762 union float64u { 763 double d; 764 uint64_t l; 765 }; 766 767 union float64u q_nan = { .l = 0xFFF8000000000000LL }; 768 union float64u s_nan = { .l = 0xFFF0000000000000LL }; 769 770 void test_fops(double a, double b) 771 { 772 printf("a=%f b=%f a+b=%f\n", a, b, a + b); 773 printf("a=%f b=%f a-b=%f\n", a, b, a - b); 774 printf("a=%f b=%f a*b=%f\n", a, b, a * b); 775 printf("a=%f b=%f a/b=%f\n", a, b, a / b); 776 printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b)); 777 printf("a=%f sqrt(a)=%f\n", a, sqrt(a)); 778 printf("a=%f sin(a)=%f\n", a, sin(a)); 779 printf("a=%f cos(a)=%f\n", a, cos(a)); 780 printf("a=%f tan(a)=%f\n", a, tan(a)); 781 printf("a=%f log(a)=%f\n", a, log(a)); 782 printf("a=%f exp(a)=%f\n", a, exp(a)); 783 printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b)); 784 /* just to test some op combining */ 785 printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a))); 786 printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a))); 787 printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a))); 788 789 } 790 791 void fpu_clear_exceptions(void) 792 { 793 struct QEMU_PACKED { 794 uint16_t fpuc; 795 uint16_t dummy1; 796 uint16_t fpus; 797 uint16_t dummy2; 798 uint16_t fptag; 799 uint16_t dummy3; 800 uint32_t ignored[4]; 801 long double fpregs[8]; 802 } float_env32; 803 804 asm volatile ("fnstenv %0\n" : "=m" (float_env32)); 805 float_env32.fpus &= ~0x7f; 806 asm volatile ("fldenv %0\n" : : "m" (float_env32)); 807 } 808 809 /* XXX: display exception bits when supported */ 810 #define FPUS_EMASK 0x0000 811 //#define FPUS_EMASK 0x007f 812 813 void test_fcmp(double a, double b) 814 { 815 long eflags, fpus; 816 817 fpu_clear_exceptions(); 818 asm("fcom %2\n" 819 "fstsw %%ax\n" 820 : "=a" (fpus) 821 : "t" (a), "u" (b)); 822 printf("fcom(%f %f)=%04lx\n", 823 a, b, fpus & (0x4500 | FPUS_EMASK)); 824 fpu_clear_exceptions(); 825 asm("fucom %2\n" 826 "fstsw %%ax\n" 827 : "=a" (fpus) 828 : "t" (a), "u" (b)); 829 printf("fucom(%f %f)=%04lx\n", 830 a, b, fpus & (0x4500 | FPUS_EMASK)); 831 if (TEST_FCOMI) { 832 /* test f(u)comi instruction */ 833 fpu_clear_exceptions(); 834 asm("fcomi %3, %2\n" 835 "fstsw %%ax\n" 836 "pushf\n" 837 "pop %0\n" 838 : "=r" (eflags), "=a" (fpus) 839 : "t" (a), "u" (b)); 840 printf("fcomi(%f %f)=%04lx %02lx\n", 841 a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); 842 fpu_clear_exceptions(); 843 asm("fucomi %3, %2\n" 844 "fstsw %%ax\n" 845 "pushf\n" 846 "pop %0\n" 847 : "=r" (eflags), "=a" (fpus) 848 : "t" (a), "u" (b)); 849 printf("fucomi(%f %f)=%04lx %02lx\n", 850 a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); 851 } 852 fpu_clear_exceptions(); 853 asm volatile("fxam\n" 854 "fstsw %%ax\n" 855 : "=a" (fpus) 856 : "t" (a)); 857 printf("fxam(%f)=%04lx\n", a, fpus & 0x4700); 858 fpu_clear_exceptions(); 859 } 860 861 void test_fcvt(double a) 862 { 863 float fa; 864 long double la; 865 int16_t fpuc; 866 int i; 867 int64_t lla; 868 int ia; 869 int16_t wa; 870 double ra; 871 872 fa = a; 873 la = a; 874 printf("(float)%f = %f\n", a, fa); 875 printf("(long double)%f = %Lf\n", a, la); 876 printf("a=" FMT64X "\n", *(uint64_t *)&a); 877 printf("la=" FMT64X " %04x\n", *(uint64_t *)&la, 878 *(unsigned short *)((char *)(&la) + 8)); 879 880 /* test all roundings */ 881 asm volatile ("fstcw %0" : "=m" (fpuc)); 882 for(i=0;i<4;i++) { 883 uint16_t val16; 884 val16 = (fpuc & ~0x0c00) | (i << 10); 885 asm volatile ("fldcw %0" : : "m" (val16)); 886 asm volatile ("fists %0" : "=m" (wa) : "t" (a)); 887 asm volatile ("fistl %0" : "=m" (ia) : "t" (a)); 888 asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st"); 889 asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a)); 890 asm volatile ("fldcw %0" : : "m" (fpuc)); 891 printf("(short)a = %d\n", wa); 892 printf("(int)a = %d\n", ia); 893 printf("(int64_t)a = " FMT64X "\n", lla); 894 printf("rint(a) = %f\n", ra); 895 } 896 } 897 898 #define TEST(N) \ 899 asm("fld" #N : "=t" (a)); \ 900 printf("fld" #N "= %f\n", a); 901 902 void test_fconst(void) 903 { 904 double a; 905 TEST(1); 906 TEST(l2t); 907 TEST(l2e); 908 TEST(pi); 909 TEST(lg2); 910 TEST(ln2); 911 TEST(z); 912 } 913 914 void test_fbcd(double a) 915 { 916 unsigned short bcd[5]; 917 double b; 918 919 asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st"); 920 asm("fbld %1" : "=t" (b) : "m" (bcd[0])); 921 printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 922 a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b); 923 } 924 925 #define TEST_ENV(env, save, restore)\ 926 {\ 927 memset((env), 0xaa, sizeof(*(env)));\ 928 for(i=0;i<5;i++)\ 929 asm volatile ("fldl %0" : : "m" (dtab[i]));\ 930 asm volatile (save " %0\n" : : "m" (*(env)));\ 931 asm volatile (restore " %0\n": : "m" (*(env)));\ 932 for(i=0;i<5;i++)\ 933 asm volatile ("fstpl %0" : "=m" (rtab[i]));\ 934 for(i=0;i<5;i++)\ 935 printf("res[%d]=%f\n", i, rtab[i]);\ 936 printf("fpuc=%04x fpus=%04x fptag=%04x\n",\ 937 (env)->fpuc,\ 938 (env)->fpus & 0xff00,\ 939 (env)->fptag);\ 940 } 941 942 void test_fenv(void) 943 { 944 struct __attribute__((__packed__)) { 945 uint16_t fpuc; 946 uint16_t dummy1; 947 uint16_t fpus; 948 uint16_t dummy2; 949 uint16_t fptag; 950 uint16_t dummy3; 951 uint32_t ignored[4]; 952 long double fpregs[8]; 953 } float_env32; 954 struct __attribute__((__packed__)) { 955 uint16_t fpuc; 956 uint16_t fpus; 957 uint16_t fptag; 958 uint16_t ignored[4]; 959 long double fpregs[8]; 960 } float_env16; 961 double dtab[8]; 962 double rtab[8]; 963 int i; 964 965 for(i=0;i<8;i++) 966 dtab[i] = i + 1; 967 968 TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); 969 TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); 970 TEST_ENV(&float_env32, "fnstenv", "fldenv"); 971 TEST_ENV(&float_env32, "fnsave", "frstor"); 972 973 /* test for ffree */ 974 for(i=0;i<5;i++) 975 asm volatile ("fldl %0" : : "m" (dtab[i])); 976 asm volatile("ffree %st(2)"); 977 asm volatile ("fnstenv %0\n" : : "m" (float_env32)); 978 asm volatile ("fninit"); 979 printf("fptag=%04x\n", float_env32.fptag); 980 } 981 982 983 #define TEST_FCMOV(a, b, eflags, CC)\ 984 {\ 985 double res;\ 986 asm("push %3\n"\ 987 "popf\n"\ 988 "fcmov" CC " %2, %0\n"\ 989 : "=t" (res)\ 990 : "0" (a), "u" (b), "g" (eflags));\ 991 printf("fcmov%s eflags=0x%04lx-> %f\n", \ 992 CC, (long)eflags, res);\ 993 } 994 995 void test_fcmov(void) 996 { 997 double a, b; 998 long eflags, i; 999 1000 a = 1.0; 1001 b = 2.0; 1002 for(i = 0; i < 4; i++) { 1003 eflags = 0; 1004 if (i & 1) 1005 eflags |= CC_C; 1006 if (i & 2) 1007 eflags |= CC_Z; 1008 TEST_FCMOV(a, b, eflags, "b"); 1009 TEST_FCMOV(a, b, eflags, "e"); 1010 TEST_FCMOV(a, b, eflags, "be"); 1011 TEST_FCMOV(a, b, eflags, "nb"); 1012 TEST_FCMOV(a, b, eflags, "ne"); 1013 TEST_FCMOV(a, b, eflags, "nbe"); 1014 } 1015 TEST_FCMOV(a, b, 0, "u"); 1016 TEST_FCMOV(a, b, CC_P, "u"); 1017 TEST_FCMOV(a, b, 0, "nu"); 1018 TEST_FCMOV(a, b, CC_P, "nu"); 1019 } 1020 1021 void test_floats(void) 1022 { 1023 test_fops(2, 3); 1024 test_fops(1.4, -5); 1025 test_fcmp(2, -1); 1026 test_fcmp(2, 2); 1027 test_fcmp(2, 3); 1028 test_fcmp(2, q_nan.d); 1029 test_fcmp(q_nan.d, -1); 1030 test_fcmp(-1.0/0.0, -1); 1031 test_fcmp(1.0/0.0, -1); 1032 test_fcvt(0.5); 1033 test_fcvt(-0.5); 1034 test_fcvt(1.0/7.0); 1035 test_fcvt(-1.0/9.0); 1036 test_fcvt(32768); 1037 test_fcvt(-1e20); 1038 test_fcvt(-1.0/0.0); 1039 test_fcvt(1.0/0.0); 1040 test_fcvt(q_nan.d); 1041 test_fconst(); 1042 test_fbcd(1234567890123456.0); 1043 test_fbcd(-123451234567890.0); 1044 test_fenv(); 1045 if (TEST_CMOV) { 1046 test_fcmov(); 1047 } 1048 } 1049 1050 /**********************************************/ 1051 #if !defined(__x86_64__) 1052 1053 #define TEST_BCD(op, op0, cc_in, cc_mask)\ 1054 {\ 1055 int res, flags;\ 1056 res = op0;\ 1057 flags = cc_in;\ 1058 asm ("push %3\n\t"\ 1059 "popf\n\t"\ 1060 #op "\n\t"\ 1061 "pushf\n\t"\ 1062 "pop %1\n\t"\ 1063 : "=a" (res), "=g" (flags)\ 1064 : "0" (res), "1" (flags));\ 1065 printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\ 1066 #op, op0, res, cc_in, flags & cc_mask);\ 1067 } 1068 1069 void test_bcd(void) 1070 { 1071 TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1072 TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1073 TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1074 TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1075 TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1076 TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1077 TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1078 TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1079 TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1080 TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1081 TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1082 TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1083 TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1084 1085 TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1086 TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1087 TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1088 TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1089 TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1090 TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1091 TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1092 TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1093 TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1094 TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1095 TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1096 TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1097 TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1098 1099 TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A)); 1100 TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A)); 1101 TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A)); 1102 TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A)); 1103 TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A)); 1104 TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A)); 1105 TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A)); 1106 TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A)); 1107 1108 TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A)); 1109 TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A)); 1110 TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A)); 1111 TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A)); 1112 TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A)); 1113 TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A)); 1114 TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A)); 1115 TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A)); 1116 1117 TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); 1118 TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); 1119 } 1120 #endif 1121 1122 #define TEST_XCHG(op, size, opconst)\ 1123 {\ 1124 long op0, op1;\ 1125 op0 = i2l(0x12345678);\ 1126 op1 = i2l(0xfbca7654);\ 1127 asm(#op " %" size "0, %" size "1" \ 1128 : "=q" (op0), opconst (op1) \ 1129 : "0" (op0));\ 1130 printf("%-10s A=" FMTLX " B=" FMTLX "\n",\ 1131 #op, op0, op1);\ 1132 } 1133 1134 #define TEST_CMPXCHG(op, size, opconst, eax)\ 1135 {\ 1136 long op0, op1, op2;\ 1137 op0 = i2l(0x12345678);\ 1138 op1 = i2l(0xfbca7654);\ 1139 op2 = i2l(eax);\ 1140 asm(#op " %" size "0, %" size "1" \ 1141 : "=q" (op0), opconst (op1) \ 1142 : "0" (op0), "a" (op2));\ 1143 printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\ 1144 #op, op2, op0, op1);\ 1145 } 1146 1147 void test_xchg(void) 1148 { 1149 #if defined(__x86_64__) 1150 TEST_XCHG(xchgq, "", "+q"); 1151 #endif 1152 TEST_XCHG(xchgl, "k", "+q"); 1153 TEST_XCHG(xchgw, "w", "+q"); 1154 TEST_XCHG(xchgb, "b", "+q"); 1155 1156 #if defined(__x86_64__) 1157 TEST_XCHG(xchgq, "", "+m"); 1158 #endif 1159 TEST_XCHG(xchgl, "k", "+m"); 1160 TEST_XCHG(xchgw, "w", "+m"); 1161 TEST_XCHG(xchgb, "b", "+m"); 1162 1163 #if defined(__x86_64__) 1164 TEST_XCHG(xaddq, "", "+q"); 1165 #endif 1166 TEST_XCHG(xaddl, "k", "+q"); 1167 TEST_XCHG(xaddw, "w", "+q"); 1168 TEST_XCHG(xaddb, "b", "+q"); 1169 1170 { 1171 int res; 1172 res = 0x12345678; 1173 asm("xaddl %1, %0" : "=r" (res) : "0" (res)); 1174 printf("xaddl same res=%08x\n", res); 1175 } 1176 1177 #if defined(__x86_64__) 1178 TEST_XCHG(xaddq, "", "+m"); 1179 #endif 1180 TEST_XCHG(xaddl, "k", "+m"); 1181 TEST_XCHG(xaddw, "w", "+m"); 1182 TEST_XCHG(xaddb, "b", "+m"); 1183 1184 #if defined(__x86_64__) 1185 TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654); 1186 #endif 1187 TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654); 1188 TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654); 1189 TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654); 1190 1191 #if defined(__x86_64__) 1192 TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc); 1193 #endif 1194 TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc); 1195 TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc); 1196 TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc); 1197 1198 #if defined(__x86_64__) 1199 TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654); 1200 #endif 1201 TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654); 1202 TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654); 1203 TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654); 1204 1205 #if defined(__x86_64__) 1206 TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc); 1207 #endif 1208 TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc); 1209 TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc); 1210 TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc); 1211 1212 { 1213 uint64_t op0, op1, op2; 1214 long eax, edx; 1215 long i, eflags; 1216 1217 for(i = 0; i < 2; i++) { 1218 op0 = 0x123456789abcdLL; 1219 eax = i2l(op0 & 0xffffffff); 1220 edx = i2l(op0 >> 32); 1221 if (i == 0) 1222 op1 = 0xfbca765423456LL; 1223 else 1224 op1 = op0; 1225 op2 = 0x6532432432434LL; 1226 asm("cmpxchg8b %2\n" 1227 "pushf\n" 1228 "pop %3\n" 1229 : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags) 1230 : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32))); 1231 printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n", 1232 eax, edx, op1, eflags & CC_Z); 1233 } 1234 } 1235 } 1236 1237 #ifdef TEST_SEGS 1238 /**********************************************/ 1239 /* segmentation tests */ 1240 1241 #include <sys/syscall.h> 1242 #include <unistd.h> 1243 #include <asm/ldt.h> 1244 #include <linux/version.h> 1245 1246 static inline int modify_ldt(int func, void * ptr, unsigned long bytecount) 1247 { 1248 return syscall(__NR_modify_ldt, func, ptr, bytecount); 1249 } 1250 1251 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66) 1252 #define modify_ldt_ldt_s user_desc 1253 #endif 1254 1255 #define MK_SEL(n) (((n) << 3) | 7) 1256 1257 uint8_t seg_data1[4096]; 1258 uint8_t seg_data2[4096]; 1259 1260 #define TEST_LR(op, size, seg, mask)\ 1261 {\ 1262 int res, res2;\ 1263 uint16_t mseg = seg;\ 1264 res = 0x12345678;\ 1265 asm (op " %" size "2, %" size "0\n" \ 1266 "movl $0, %1\n"\ 1267 "jnz 1f\n"\ 1268 "movl $1, %1\n"\ 1269 "1:\n"\ 1270 : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\ 1271 printf(op ": Z=%d %08x\n", res2, res & ~(mask));\ 1272 } 1273 1274 #define TEST_ARPL(op, size, op1, op2)\ 1275 {\ 1276 long a, b, c; \ 1277 a = (op1); \ 1278 b = (op2); \ 1279 asm volatile(op " %" size "3, %" size "0\n"\ 1280 "movl $0,%1\n"\ 1281 "jnz 1f\n"\ 1282 "movl $1,%1\n"\ 1283 "1:\n"\ 1284 : "=r" (a), "=r" (c) : "0" (a), "r" (b)); \ 1285 printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\ 1286 (long)(op1), (long)(op2), a, c);\ 1287 } 1288 1289 /* NOTE: we use Linux modify_ldt syscall */ 1290 void test_segs(void) 1291 { 1292 struct modify_ldt_ldt_s ldt; 1293 long long ldt_table[3]; 1294 int res, res2; 1295 char tmp; 1296 struct { 1297 uint32_t offset; 1298 uint16_t seg; 1299 } __attribute__((__packed__)) segoff; 1300 1301 ldt.entry_number = 1; 1302 ldt.base_addr = (unsigned long)&seg_data1; 1303 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; 1304 ldt.seg_32bit = 1; 1305 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1306 ldt.read_exec_only = 0; 1307 ldt.limit_in_pages = 1; 1308 ldt.seg_not_present = 0; 1309 ldt.useable = 1; 1310 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1311 1312 ldt.entry_number = 2; 1313 ldt.base_addr = (unsigned long)&seg_data2; 1314 ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12; 1315 ldt.seg_32bit = 1; 1316 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1317 ldt.read_exec_only = 0; 1318 ldt.limit_in_pages = 1; 1319 ldt.seg_not_present = 0; 1320 ldt.useable = 1; 1321 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1322 1323 modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ 1324 #if 0 1325 { 1326 int i; 1327 for(i=0;i<3;i++) 1328 printf("%d: %016Lx\n", i, ldt_table[i]); 1329 } 1330 #endif 1331 /* do some tests with fs or gs */ 1332 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); 1333 1334 seg_data1[1] = 0xaa; 1335 seg_data2[1] = 0x55; 1336 1337 asm volatile ("fs movzbl 0x1, %0" : "=r" (res)); 1338 printf("FS[1] = %02x\n", res); 1339 1340 asm volatile ("pushl %%gs\n" 1341 "movl %1, %%gs\n" 1342 "gs movzbl 0x1, %0\n" 1343 "popl %%gs\n" 1344 : "=r" (res) 1345 : "r" (MK_SEL(2))); 1346 printf("GS[1] = %02x\n", res); 1347 1348 /* tests with ds/ss (implicit segment case) */ 1349 tmp = 0xa5; 1350 asm volatile ("pushl %%ebp\n\t" 1351 "pushl %%ds\n\t" 1352 "movl %2, %%ds\n\t" 1353 "movl %3, %%ebp\n\t" 1354 "movzbl 0x1, %0\n\t" 1355 "movzbl (%%ebp), %1\n\t" 1356 "popl %%ds\n\t" 1357 "popl %%ebp\n\t" 1358 : "=r" (res), "=r" (res2) 1359 : "r" (MK_SEL(1)), "r" (&tmp)); 1360 printf("DS[1] = %02x\n", res); 1361 printf("SS[tmp] = %02x\n", res2); 1362 1363 segoff.seg = MK_SEL(2); 1364 segoff.offset = 0xabcdef12; 1365 asm volatile("lfs %2, %0\n\t" 1366 "movl %%fs, %1\n\t" 1367 : "=r" (res), "=g" (res2) 1368 : "m" (segoff)); 1369 printf("FS:reg = %04x:%08x\n", res2, res); 1370 1371 TEST_LR("larw", "w", MK_SEL(2), 0x0100); 1372 TEST_LR("larl", "", MK_SEL(2), 0x0100); 1373 TEST_LR("lslw", "w", MK_SEL(2), 0); 1374 TEST_LR("lsll", "", MK_SEL(2), 0); 1375 1376 TEST_LR("larw", "w", 0xfff8, 0); 1377 TEST_LR("larl", "", 0xfff8, 0); 1378 TEST_LR("lslw", "w", 0xfff8, 0); 1379 TEST_LR("lsll", "", 0xfff8, 0); 1380 1381 TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1); 1382 TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3); 1383 TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1); 1384 } 1385 1386 /* 16 bit code test */ 1387 extern char code16_start, code16_end; 1388 extern char code16_func1; 1389 extern char code16_func2; 1390 extern char code16_func3; 1391 1392 void test_code16(void) 1393 { 1394 struct modify_ldt_ldt_s ldt; 1395 int res, res2; 1396 1397 /* build a code segment */ 1398 ldt.entry_number = 1; 1399 ldt.base_addr = (unsigned long)&code16_start; 1400 ldt.limit = &code16_end - &code16_start; 1401 ldt.seg_32bit = 0; 1402 ldt.contents = MODIFY_LDT_CONTENTS_CODE; 1403 ldt.read_exec_only = 0; 1404 ldt.limit_in_pages = 0; 1405 ldt.seg_not_present = 0; 1406 ldt.useable = 1; 1407 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1408 1409 /* call the first function */ 1410 asm volatile ("lcall %1, %2" 1411 : "=a" (res) 1412 : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc"); 1413 printf("func1() = 0x%08x\n", res); 1414 asm volatile ("lcall %2, %3" 1415 : "=a" (res), "=c" (res2) 1416 : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc"); 1417 printf("func2() = 0x%08x spdec=%d\n", res, res2); 1418 asm volatile ("lcall %1, %2" 1419 : "=a" (res) 1420 : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc"); 1421 printf("func3() = 0x%08x\n", res); 1422 } 1423 #endif 1424 1425 #if defined(__x86_64__) 1426 asm(".globl func_lret\n" 1427 "func_lret:\n" 1428 "movl $0x87654641, %eax\n" 1429 "lretq\n"); 1430 #else 1431 asm(".globl func_lret\n" 1432 "func_lret:\n" 1433 "movl $0x87654321, %eax\n" 1434 "lret\n" 1435 1436 ".globl func_iret\n" 1437 "func_iret:\n" 1438 "movl $0xabcd4321, %eax\n" 1439 "iret\n"); 1440 #endif 1441 1442 extern char func_lret; 1443 extern char func_iret; 1444 1445 void test_misc(void) 1446 { 1447 char table[256]; 1448 long res, i; 1449 1450 for(i=0;i<256;i++) table[i] = 256 - i; 1451 res = 0x12345678; 1452 asm ("xlat" : "=a" (res) : "b" (table), "0" (res)); 1453 printf("xlat: EAX=" FMTLX "\n", res); 1454 1455 #if defined(__x86_64__) 1456 #if 0 1457 { 1458 /* XXX: see if Intel Core2 and AMD64 behavior really 1459 differ. Here we implemented the Intel way which is not 1460 compatible yet with QEMU. */ 1461 static struct QEMU_PACKED { 1462 uint64_t offset; 1463 uint16_t seg; 1464 } desc; 1465 long cs_sel; 1466 1467 asm volatile ("mov %%cs, %0" : "=r" (cs_sel)); 1468 1469 asm volatile ("push %1\n" 1470 "call func_lret\n" 1471 : "=a" (res) 1472 : "r" (cs_sel) : "memory", "cc"); 1473 printf("func_lret=" FMTLX "\n", res); 1474 1475 desc.offset = (long)&func_lret; 1476 desc.seg = cs_sel; 1477 1478 asm volatile ("xor %%rax, %%rax\n" 1479 "rex64 lcall *(%%rcx)\n" 1480 : "=a" (res) 1481 : "c" (&desc) 1482 : "memory", "cc"); 1483 printf("func_lret2=" FMTLX "\n", res); 1484 1485 asm volatile ("push %2\n" 1486 "mov $ 1f, %%rax\n" 1487 "push %%rax\n" 1488 "rex64 ljmp *(%%rcx)\n" 1489 "1:\n" 1490 : "=a" (res) 1491 : "c" (&desc), "b" (cs_sel) 1492 : "memory", "cc"); 1493 printf("func_lret3=" FMTLX "\n", res); 1494 } 1495 #endif 1496 #else 1497 asm volatile ("push %%cs ; call %1" 1498 : "=a" (res) 1499 : "m" (func_lret): "memory", "cc"); 1500 printf("func_lret=" FMTLX "\n", res); 1501 1502 asm volatile ("pushf ; push %%cs ; call %1" 1503 : "=a" (res) 1504 : "m" (func_iret): "memory", "cc"); 1505 printf("func_iret=" FMTLX "\n", res); 1506 #endif 1507 1508 #if defined(__x86_64__) 1509 /* specific popl test */ 1510 asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0" 1511 : "=g" (res)); 1512 printf("popl esp=" FMTLX "\n", res); 1513 #else 1514 /* specific popl test */ 1515 asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0" 1516 : "=g" (res)); 1517 printf("popl esp=" FMTLX "\n", res); 1518 1519 /* specific popw test */ 1520 asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0" 1521 : "=g" (res)); 1522 printf("popw esp=" FMTLX "\n", res); 1523 #endif 1524 } 1525 1526 uint8_t str_buffer[4096]; 1527 1528 #define TEST_STRING1(OP, size, DF, REP)\ 1529 {\ 1530 long esi, edi, eax, ecx, eflags;\ 1531 \ 1532 esi = (long)(str_buffer + sizeof(str_buffer) / 2);\ 1533 edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\ 1534 eax = i2l(0x12345678);\ 1535 ecx = 17;\ 1536 \ 1537 asm volatile ("push $0\n\t"\ 1538 "popf\n\t"\ 1539 DF "\n\t"\ 1540 REP #OP size "\n\t"\ 1541 "cld\n\t"\ 1542 "pushf\n\t"\ 1543 "pop %4\n\t"\ 1544 : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\ 1545 : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\ 1546 printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\ 1547 REP #OP size, esi, edi, eax, ecx,\ 1548 (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\ 1549 } 1550 1551 #define TEST_STRING(OP, REP)\ 1552 TEST_STRING1(OP, "b", "", REP);\ 1553 TEST_STRING1(OP, "w", "", REP);\ 1554 TEST_STRING1(OP, "l", "", REP);\ 1555 X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\ 1556 TEST_STRING1(OP, "b", "std", REP);\ 1557 TEST_STRING1(OP, "w", "std", REP);\ 1558 TEST_STRING1(OP, "l", "std", REP);\ 1559 X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP)) 1560 1561 void test_string(void) 1562 { 1563 int i; 1564 for(i = 0;i < sizeof(str_buffer); i++) 1565 str_buffer[i] = i + 0x56; 1566 TEST_STRING(stos, ""); 1567 TEST_STRING(stos, "rep "); 1568 TEST_STRING(lods, ""); /* to verify stos */ 1569 TEST_STRING(lods, "rep "); 1570 TEST_STRING(movs, ""); 1571 TEST_STRING(movs, "rep "); 1572 TEST_STRING(lods, ""); /* to verify stos */ 1573 1574 /* XXX: better tests */ 1575 TEST_STRING(scas, ""); 1576 TEST_STRING(scas, "repz "); 1577 TEST_STRING(scas, "repnz "); 1578 TEST_STRING(cmps, ""); 1579 TEST_STRING(cmps, "repz "); 1580 TEST_STRING(cmps, "repnz "); 1581 } 1582 1583 #ifdef TEST_VM86 1584 /* VM86 test */ 1585 1586 static inline void set_bit(uint8_t *a, unsigned int bit) 1587 { 1588 a[bit / 8] |= (1 << (bit % 8)); 1589 } 1590 1591 static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) 1592 { 1593 return (uint8_t *)((seg << 4) + (reg & 0xffff)); 1594 } 1595 1596 static inline void pushw(struct vm86_regs *r, int val) 1597 { 1598 r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); 1599 *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; 1600 } 1601 1602 static inline int vm86(int func, struct vm86plus_struct *v86) 1603 { 1604 return syscall(__NR_vm86, func, v86); 1605 } 1606 1607 extern char vm86_code_start; 1608 extern char vm86_code_end; 1609 1610 #define VM86_CODE_CS 0x100 1611 #define VM86_CODE_IP 0x100 1612 1613 void test_vm86(void) 1614 { 1615 struct vm86plus_struct ctx; 1616 struct vm86_regs *r; 1617 uint8_t *vm86_mem; 1618 int seg, ret; 1619 1620 vm86_mem = mmap((void *)0x00000000, 0x110000, 1621 PROT_WRITE | PROT_READ | PROT_EXEC, 1622 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 1623 if (vm86_mem == MAP_FAILED) { 1624 printf("ERROR: could not map vm86 memory"); 1625 return; 1626 } 1627 memset(&ctx, 0, sizeof(ctx)); 1628 1629 /* init basic registers */ 1630 r = &ctx.regs; 1631 r->eip = VM86_CODE_IP; 1632 r->esp = 0xfffe; 1633 seg = VM86_CODE_CS; 1634 r->cs = seg; 1635 r->ss = seg; 1636 r->ds = seg; 1637 r->es = seg; 1638 r->fs = seg; 1639 r->gs = seg; 1640 r->eflags = VIF_MASK; 1641 1642 /* move code to proper address. We use the same layout as a .com 1643 dos program. */ 1644 memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP, 1645 &vm86_code_start, &vm86_code_end - &vm86_code_start); 1646 1647 /* mark int 0x21 as being emulated */ 1648 set_bit((uint8_t *)&ctx.int_revectored, 0x21); 1649 1650 for(;;) { 1651 ret = vm86(VM86_ENTER, &ctx); 1652 switch(VM86_TYPE(ret)) { 1653 case VM86_INTx: 1654 { 1655 int int_num, ah, v; 1656 1657 int_num = VM86_ARG(ret); 1658 if (int_num != 0x21) 1659 goto unknown_int; 1660 ah = (r->eax >> 8) & 0xff; 1661 switch(ah) { 1662 case 0x00: /* exit */ 1663 goto the_end; 1664 case 0x02: /* write char */ 1665 { 1666 uint8_t c = r->edx; 1667 putchar(c); 1668 } 1669 break; 1670 case 0x09: /* write string */ 1671 { 1672 uint8_t c, *ptr; 1673 ptr = seg_to_linear(r->ds, r->edx); 1674 for(;;) { 1675 c = *ptr++; 1676 if (c == '$') 1677 break; 1678 putchar(c); 1679 } 1680 r->eax = (r->eax & ~0xff) | '$'; 1681 } 1682 break; 1683 case 0xff: /* extension: write eflags number in edx */ 1684 v = (int)r->edx; 1685 #ifndef LINUX_VM86_IOPL_FIX 1686 v &= ~0x3000; 1687 #endif 1688 printf("%08x\n", v); 1689 break; 1690 default: 1691 unknown_int: 1692 printf("unsupported int 0x%02x\n", int_num); 1693 goto the_end; 1694 } 1695 } 1696 break; 1697 case VM86_SIGNAL: 1698 /* a signal came, we just ignore that */ 1699 break; 1700 case VM86_STI: 1701 break; 1702 default: 1703 printf("ERROR: unhandled vm86 return code (0x%x)\n", ret); 1704 goto the_end; 1705 } 1706 } 1707 the_end: 1708 printf("VM86 end\n"); 1709 munmap(vm86_mem, 0x110000); 1710 } 1711 #endif 1712 1713 /* exception tests */ 1714 #if defined(__i386__) && !defined(REG_EAX) 1715 #define REG_EAX EAX 1716 #define REG_EBX EBX 1717 #define REG_ECX ECX 1718 #define REG_EDX EDX 1719 #define REG_ESI ESI 1720 #define REG_EDI EDI 1721 #define REG_EBP EBP 1722 #define REG_ESP ESP 1723 #define REG_EIP EIP 1724 #define REG_EFL EFL 1725 #define REG_TRAPNO TRAPNO 1726 #define REG_ERR ERR 1727 #endif 1728 1729 #if defined(__x86_64__) 1730 #define REG_EIP REG_RIP 1731 #endif 1732 1733 jmp_buf jmp_env; 1734 int v1; 1735 int tab[2]; 1736 1737 void sig_handler(int sig, siginfo_t *info, void *puc) 1738 { 1739 ucontext_t *uc = puc; 1740 1741 printf("si_signo=%d si_errno=%d si_code=%d", 1742 info->si_signo, info->si_errno, info->si_code); 1743 printf(" si_addr=0x%08lx", 1744 (unsigned long)info->si_addr); 1745 printf("\n"); 1746 1747 printf("trapno=" FMTLX " err=" FMTLX, 1748 (long)uc->uc_mcontext.gregs[REG_TRAPNO], 1749 (long)uc->uc_mcontext.gregs[REG_ERR]); 1750 printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]); 1751 printf("\n"); 1752 longjmp(jmp_env, 1); 1753 } 1754 1755 void test_exceptions(void) 1756 { 1757 struct sigaction act; 1758 volatile int val; 1759 1760 act.sa_sigaction = sig_handler; 1761 sigemptyset(&act.sa_mask); 1762 act.sa_flags = SA_SIGINFO | SA_NODEFER; 1763 sigaction(SIGFPE, &act, NULL); 1764 sigaction(SIGILL, &act, NULL); 1765 sigaction(SIGSEGV, &act, NULL); 1766 sigaction(SIGBUS, &act, NULL); 1767 sigaction(SIGTRAP, &act, NULL); 1768 1769 /* test division by zero reporting */ 1770 printf("DIVZ exception:\n"); 1771 if (setjmp(jmp_env) == 0) { 1772 /* now divide by zero */ 1773 v1 = 0; 1774 v1 = 2 / v1; 1775 } 1776 1777 #if !defined(__x86_64__) 1778 printf("BOUND exception:\n"); 1779 if (setjmp(jmp_env) == 0) { 1780 /* bound exception */ 1781 tab[0] = 1; 1782 tab[1] = 10; 1783 asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0])); 1784 } 1785 #endif 1786 1787 #ifdef TEST_SEGS 1788 printf("segment exceptions:\n"); 1789 if (setjmp(jmp_env) == 0) { 1790 /* load an invalid segment */ 1791 asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1)); 1792 } 1793 if (setjmp(jmp_env) == 0) { 1794 /* null data segment is valid */ 1795 asm volatile ("movl %0, %%fs" : : "r" (3)); 1796 /* null stack segment */ 1797 asm volatile ("movl %0, %%ss" : : "r" (3)); 1798 } 1799 1800 { 1801 struct modify_ldt_ldt_s ldt; 1802 ldt.entry_number = 1; 1803 ldt.base_addr = (unsigned long)&seg_data1; 1804 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; 1805 ldt.seg_32bit = 1; 1806 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1807 ldt.read_exec_only = 0; 1808 ldt.limit_in_pages = 1; 1809 ldt.seg_not_present = 1; 1810 ldt.useable = 1; 1811 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1812 1813 if (setjmp(jmp_env) == 0) { 1814 /* segment not present */ 1815 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); 1816 } 1817 } 1818 #endif 1819 1820 /* test SEGV reporting */ 1821 printf("PF exception:\n"); 1822 if (setjmp(jmp_env) == 0) { 1823 val = 1; 1824 /* we add a nop to test a weird PC retrieval case */ 1825 asm volatile ("nop"); 1826 /* now store in an invalid address */ 1827 *(char *)0x1234 = 1; 1828 } 1829 1830 /* test SEGV reporting */ 1831 printf("PF exception:\n"); 1832 if (setjmp(jmp_env) == 0) { 1833 val = 1; 1834 /* read from an invalid address */ 1835 v1 = *(char *)0x1234; 1836 } 1837 1838 /* test illegal instruction reporting */ 1839 printf("UD2 exception:\n"); 1840 if (setjmp(jmp_env) == 0) { 1841 /* now execute an invalid instruction */ 1842 asm volatile("ud2"); 1843 } 1844 printf("lock nop exception:\n"); 1845 if (setjmp(jmp_env) == 0) { 1846 /* now execute an invalid instruction */ 1847 asm volatile(".byte 0xf0, 0x90"); 1848 } 1849 1850 printf("INT exception:\n"); 1851 if (setjmp(jmp_env) == 0) { 1852 asm volatile ("int $0xfd"); 1853 } 1854 if (setjmp(jmp_env) == 0) { 1855 asm volatile ("int $0x01"); 1856 } 1857 if (setjmp(jmp_env) == 0) { 1858 asm volatile (".byte 0xcd, 0x03"); 1859 } 1860 if (setjmp(jmp_env) == 0) { 1861 asm volatile ("int $0x04"); 1862 } 1863 if (setjmp(jmp_env) == 0) { 1864 asm volatile ("int $0x05"); 1865 } 1866 1867 printf("INT3 exception:\n"); 1868 if (setjmp(jmp_env) == 0) { 1869 asm volatile ("int3"); 1870 } 1871 1872 printf("CLI exception:\n"); 1873 if (setjmp(jmp_env) == 0) { 1874 asm volatile ("cli"); 1875 } 1876 1877 printf("STI exception:\n"); 1878 if (setjmp(jmp_env) == 0) { 1879 asm volatile ("cli"); 1880 } 1881 1882 #if !defined(__x86_64__) 1883 printf("INTO exception:\n"); 1884 if (setjmp(jmp_env) == 0) { 1885 /* overflow exception */ 1886 asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff)); 1887 } 1888 #endif 1889 1890 printf("OUTB exception:\n"); 1891 if (setjmp(jmp_env) == 0) { 1892 asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0)); 1893 } 1894 1895 printf("INB exception:\n"); 1896 if (setjmp(jmp_env) == 0) { 1897 asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321)); 1898 } 1899 1900 printf("REP OUTSB exception:\n"); 1901 if (setjmp(jmp_env) == 0) { 1902 asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1)); 1903 } 1904 1905 printf("REP INSB exception:\n"); 1906 if (setjmp(jmp_env) == 0) { 1907 asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1)); 1908 } 1909 1910 printf("HLT exception:\n"); 1911 if (setjmp(jmp_env) == 0) { 1912 asm volatile ("hlt"); 1913 } 1914 1915 printf("single step exception:\n"); 1916 val = 0; 1917 if (setjmp(jmp_env) == 0) { 1918 asm volatile ("pushf\n" 1919 "orl $0x00100, (%%esp)\n" 1920 "popf\n" 1921 "movl $0xabcd, %0\n" 1922 "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory"); 1923 } 1924 printf("val=0x%x\n", val); 1925 } 1926 1927 #if !defined(__x86_64__) 1928 /* specific precise single step test */ 1929 void sig_trap_handler(int sig, siginfo_t *info, void *puc) 1930 { 1931 ucontext_t *uc = puc; 1932 printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]); 1933 } 1934 1935 const uint8_t sstep_buf1[4] = { 1, 2, 3, 4}; 1936 uint8_t sstep_buf2[4]; 1937 1938 void test_single_step(void) 1939 { 1940 struct sigaction act; 1941 volatile int val; 1942 int i; 1943 1944 val = 0; 1945 act.sa_sigaction = sig_trap_handler; 1946 sigemptyset(&act.sa_mask); 1947 act.sa_flags = SA_SIGINFO; 1948 sigaction(SIGTRAP, &act, NULL); 1949 asm volatile ("pushf\n" 1950 "orl $0x00100, (%%esp)\n" 1951 "popf\n" 1952 "movl $0xabcd, %0\n" 1953 1954 /* jmp test */ 1955 "movl $3, %%ecx\n" 1956 "1:\n" 1957 "addl $1, %0\n" 1958 "decl %%ecx\n" 1959 "jnz 1b\n" 1960 1961 /* movsb: the single step should stop at each movsb iteration */ 1962 "movl $sstep_buf1, %%esi\n" 1963 "movl $sstep_buf2, %%edi\n" 1964 "movl $0, %%ecx\n" 1965 "rep movsb\n" 1966 "movl $3, %%ecx\n" 1967 "rep movsb\n" 1968 "movl $1, %%ecx\n" 1969 "rep movsb\n" 1970 1971 /* cmpsb: the single step should stop at each cmpsb iteration */ 1972 "movl $sstep_buf1, %%esi\n" 1973 "movl $sstep_buf2, %%edi\n" 1974 "movl $0, %%ecx\n" 1975 "rep cmpsb\n" 1976 "movl $4, %%ecx\n" 1977 "rep cmpsb\n" 1978 1979 /* getpid() syscall: single step should skip one 1980 instruction */ 1981 "movl $20, %%eax\n" 1982 "int $0x80\n" 1983 "movl $0, %%eax\n" 1984 1985 /* when modifying SS, trace is not done on the next 1986 instruction */ 1987 "movl %%ss, %%ecx\n" 1988 "movl %%ecx, %%ss\n" 1989 "addl $1, %0\n" 1990 "movl $1, %%eax\n" 1991 "movl %%ecx, %%ss\n" 1992 "jmp 1f\n" 1993 "addl $1, %0\n" 1994 "1:\n" 1995 "movl $1, %%eax\n" 1996 "pushl %%ecx\n" 1997 "popl %%ss\n" 1998 "addl $1, %0\n" 1999 "movl $1, %%eax\n" 2000 2001 "pushf\n" 2002 "andl $~0x00100, (%%esp)\n" 2003 "popf\n" 2004 : "=m" (val) 2005 : 2006 : "cc", "memory", "eax", "ecx", "esi", "edi"); 2007 printf("val=%d\n", val); 2008 for(i = 0; i < 4; i++) 2009 printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]); 2010 } 2011 2012 /* self modifying code test */ 2013 uint8_t code[] = { 2014 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */ 2015 0xc3, /* ret */ 2016 }; 2017 2018 asm(".section \".data_x\",\"awx\"\n" 2019 "smc_code2:\n" 2020 "movl 4(%esp), %eax\n" 2021 "movl %eax, smc_patch_addr2 + 1\n" 2022 "nop\n" 2023 "nop\n" 2024 "nop\n" 2025 "nop\n" 2026 "nop\n" 2027 "nop\n" 2028 "nop\n" 2029 "nop\n" 2030 "smc_patch_addr2:\n" 2031 "movl $1, %eax\n" 2032 "ret\n" 2033 ".previous\n" 2034 ); 2035 2036 typedef int FuncType(void); 2037 extern int smc_code2(int); 2038 void test_self_modifying_code(void) 2039 { 2040 int i; 2041 printf("self modifying code:\n"); 2042 printf("func1 = 0x%x\n", ((FuncType *)code)()); 2043 for(i = 2; i <= 4; i++) { 2044 code[1] = i; 2045 printf("func%d = 0x%x\n", i, ((FuncType *)code)()); 2046 } 2047 2048 /* more difficult test : the modified code is just after the 2049 modifying instruction. It is forbidden in Intel specs, but it 2050 is used by old DOS programs */ 2051 for(i = 2; i <= 4; i++) { 2052 printf("smc_code2(%d) = %d\n", i, smc_code2(i)); 2053 } 2054 } 2055 #endif 2056 2057 long enter_stack[4096]; 2058 2059 #if defined(__x86_64__) 2060 #define RSP "%%rsp" 2061 #define RBP "%%rbp" 2062 #else 2063 #define RSP "%%esp" 2064 #define RBP "%%ebp" 2065 #endif 2066 2067 #if !defined(__x86_64__) 2068 /* causes an infinite loop, disable it for now. */ 2069 #define TEST_ENTER(size, stack_type, level) 2070 #else 2071 #define TEST_ENTER(size, stack_type, level)\ 2072 {\ 2073 long esp_save, esp_val, ebp_val, ebp_save, i;\ 2074 stack_type *ptr, *stack_end, *stack_ptr;\ 2075 memset(enter_stack, 0, sizeof(enter_stack));\ 2076 stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\ 2077 ebp_val = (long)stack_ptr;\ 2078 for(i=1;i<=32;i++)\ 2079 *--stack_ptr = i;\ 2080 esp_val = (long)stack_ptr;\ 2081 asm("mov " RSP ", %[esp_save]\n"\ 2082 "mov " RBP ", %[ebp_save]\n"\ 2083 "mov %[esp_val], " RSP "\n"\ 2084 "mov %[ebp_val], " RBP "\n"\ 2085 "enter" size " $8, $" #level "\n"\ 2086 "mov " RSP ", %[esp_val]\n"\ 2087 "mov " RBP ", %[ebp_val]\n"\ 2088 "mov %[esp_save], " RSP "\n"\ 2089 "mov %[ebp_save], " RBP "\n"\ 2090 : [esp_save] "=r" (esp_save),\ 2091 [ebp_save] "=r" (ebp_save),\ 2092 [esp_val] "=r" (esp_val),\ 2093 [ebp_val] "=r" (ebp_val)\ 2094 : "[esp_val]" (esp_val),\ 2095 "[ebp_val]" (ebp_val));\ 2096 printf("level=%d:\n", level);\ 2097 printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\ 2098 printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\ 2099 for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\ 2100 printf(FMTLX "\n", (long)ptr[0]);\ 2101 } 2102 #endif 2103 2104 static void test_enter(void) 2105 { 2106 #if defined(__x86_64__) 2107 TEST_ENTER("q", uint64_t, 0); 2108 TEST_ENTER("q", uint64_t, 1); 2109 TEST_ENTER("q", uint64_t, 2); 2110 TEST_ENTER("q", uint64_t, 31); 2111 #else 2112 TEST_ENTER("l", uint32_t, 0); 2113 TEST_ENTER("l", uint32_t, 1); 2114 TEST_ENTER("l", uint32_t, 2); 2115 TEST_ENTER("l", uint32_t, 31); 2116 #endif 2117 2118 TEST_ENTER("w", uint16_t, 0); 2119 TEST_ENTER("w", uint16_t, 1); 2120 TEST_ENTER("w", uint16_t, 2); 2121 TEST_ENTER("w", uint16_t, 31); 2122 } 2123 2124 #define TEST_CONV_RAX(op)\ 2125 {\ 2126 unsigned long a, r;\ 2127 a = i2l(0x8234a6f8);\ 2128 r = a;\ 2129 asm volatile(#op : "=a" (r) : "0" (r));\ 2130 printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\ 2131 } 2132 2133 #define TEST_CONV_RAX_RDX(op)\ 2134 {\ 2135 unsigned long a, d, r, rh; \ 2136 a = i2l(0x8234a6f8);\ 2137 d = i2l(0x8345a1f2);\ 2138 r = a;\ 2139 rh = d;\ 2140 asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh)); \ 2141 printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh); \ 2142 } 2143 2144 void test_conv(void) 2145 { 2146 TEST_CONV_RAX(cbw); 2147 TEST_CONV_RAX(cwde); 2148 #if defined(__x86_64__) 2149 TEST_CONV_RAX(cdqe); 2150 #endif 2151 2152 TEST_CONV_RAX_RDX(cwd); 2153 TEST_CONV_RAX_RDX(cdq); 2154 #if defined(__x86_64__) 2155 TEST_CONV_RAX_RDX(cqo); 2156 #endif 2157 2158 { 2159 unsigned long a, r; 2160 a = i2l(0x12345678); 2161 asm volatile("bswapl %k0" : "=r" (r) : "0" (a)); 2162 printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r); 2163 } 2164 #if defined(__x86_64__) 2165 { 2166 unsigned long a, r; 2167 a = i2l(0x12345678); 2168 asm volatile("bswapq %0" : "=r" (r) : "0" (a)); 2169 printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r); 2170 } 2171 #endif 2172 } 2173 2174 extern void *__start_initcall; 2175 extern void *__stop_initcall; 2176 2177 2178 int main(int argc, char **argv) 2179 { 2180 void **ptr; 2181 void (*func)(void); 2182 2183 ptr = &__start_initcall; 2184 while (ptr != &__stop_initcall) { 2185 func = *ptr++; 2186 func(); 2187 } 2188 test_bsx(); 2189 test_xcnt(); 2190 test_mul(); 2191 test_jcc(); 2192 test_loop(); 2193 test_floats(); 2194 #if !defined(__x86_64__) 2195 test_bcd(); 2196 #endif 2197 test_xchg(); 2198 test_string(); 2199 test_misc(); 2200 test_lea(); 2201 #ifdef TEST_SEGS 2202 test_segs(); 2203 test_code16(); 2204 #endif 2205 #ifdef TEST_VM86 2206 test_vm86(); 2207 #endif 2208 #if !defined(__x86_64__) 2209 test_exceptions(); 2210 test_self_modifying_code(); 2211 test_single_step(); 2212 #endif 2213 test_enter(); 2214 test_conv(); 2215 return 0; 2216 } 2217