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_bsx(void) 719 { 720 TEST_BSX(bsrw, "w", 0); 721 TEST_BSX(bsrw, "w", 0x12340128); 722 TEST_BSX(bsfw, "w", 0); 723 TEST_BSX(bsfw, "w", 0x12340128); 724 TEST_BSX(bsrl, "k", 0); 725 TEST_BSX(bsrl, "k", 0x00340128); 726 TEST_BSX(bsfl, "k", 0); 727 TEST_BSX(bsfl, "k", 0x00340128); 728 #if defined(__x86_64__) 729 TEST_BSX(bsrq, "", 0); 730 TEST_BSX(bsrq, "", 0x003401281234); 731 TEST_BSX(bsfq, "", 0); 732 TEST_BSX(bsfq, "", 0x003401281234); 733 #endif 734 } 735 736 /**********************************************/ 737 738 union float64u { 739 double d; 740 uint64_t l; 741 }; 742 743 union float64u q_nan = { .l = 0xFFF8000000000000LL }; 744 union float64u s_nan = { .l = 0xFFF0000000000000LL }; 745 746 void test_fops(double a, double b) 747 { 748 printf("a=%f b=%f a+b=%f\n", a, b, a + b); 749 printf("a=%f b=%f a-b=%f\n", a, b, a - b); 750 printf("a=%f b=%f a*b=%f\n", a, b, a * b); 751 printf("a=%f b=%f a/b=%f\n", a, b, a / b); 752 printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b)); 753 printf("a=%f sqrt(a)=%f\n", a, sqrt(a)); 754 printf("a=%f sin(a)=%f\n", a, sin(a)); 755 printf("a=%f cos(a)=%f\n", a, cos(a)); 756 printf("a=%f tan(a)=%f\n", a, tan(a)); 757 printf("a=%f log(a)=%f\n", a, log(a)); 758 printf("a=%f exp(a)=%f\n", a, exp(a)); 759 printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b)); 760 /* just to test some op combining */ 761 printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a))); 762 printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a))); 763 printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a))); 764 765 } 766 767 void fpu_clear_exceptions(void) 768 { 769 struct QEMU_PACKED { 770 uint16_t fpuc; 771 uint16_t dummy1; 772 uint16_t fpus; 773 uint16_t dummy2; 774 uint16_t fptag; 775 uint16_t dummy3; 776 uint32_t ignored[4]; 777 long double fpregs[8]; 778 } float_env32; 779 780 asm volatile ("fnstenv %0\n" : "=m" (float_env32)); 781 float_env32.fpus &= ~0x7f; 782 asm volatile ("fldenv %0\n" : : "m" (float_env32)); 783 } 784 785 /* XXX: display exception bits when supported */ 786 #define FPUS_EMASK 0x0000 787 //#define FPUS_EMASK 0x007f 788 789 void test_fcmp(double a, double b) 790 { 791 long eflags, fpus; 792 793 fpu_clear_exceptions(); 794 asm("fcom %2\n" 795 "fstsw %%ax\n" 796 : "=a" (fpus) 797 : "t" (a), "u" (b)); 798 printf("fcom(%f %f)=%04lx\n", 799 a, b, fpus & (0x4500 | FPUS_EMASK)); 800 fpu_clear_exceptions(); 801 asm("fucom %2\n" 802 "fstsw %%ax\n" 803 : "=a" (fpus) 804 : "t" (a), "u" (b)); 805 printf("fucom(%f %f)=%04lx\n", 806 a, b, fpus & (0x4500 | FPUS_EMASK)); 807 if (TEST_FCOMI) { 808 /* test f(u)comi instruction */ 809 fpu_clear_exceptions(); 810 asm("fcomi %3, %2\n" 811 "fstsw %%ax\n" 812 "pushf\n" 813 "pop %0\n" 814 : "=r" (eflags), "=a" (fpus) 815 : "t" (a), "u" (b)); 816 printf("fcomi(%f %f)=%04lx %02lx\n", 817 a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); 818 fpu_clear_exceptions(); 819 asm("fucomi %3, %2\n" 820 "fstsw %%ax\n" 821 "pushf\n" 822 "pop %0\n" 823 : "=r" (eflags), "=a" (fpus) 824 : "t" (a), "u" (b)); 825 printf("fucomi(%f %f)=%04lx %02lx\n", 826 a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); 827 } 828 fpu_clear_exceptions(); 829 asm volatile("fxam\n" 830 "fstsw %%ax\n" 831 : "=a" (fpus) 832 : "t" (a)); 833 printf("fxam(%f)=%04lx\n", a, fpus & 0x4700); 834 fpu_clear_exceptions(); 835 } 836 837 void test_fcvt(double a) 838 { 839 float fa; 840 long double la; 841 int16_t fpuc; 842 int i; 843 int64_t lla; 844 int ia; 845 int16_t wa; 846 double ra; 847 848 fa = a; 849 la = a; 850 printf("(float)%f = %f\n", a, fa); 851 printf("(long double)%f = %Lf\n", a, la); 852 printf("a=" FMT64X "\n", *(uint64_t *)&a); 853 printf("la=" FMT64X " %04x\n", *(uint64_t *)&la, 854 *(unsigned short *)((char *)(&la) + 8)); 855 856 /* test all roundings */ 857 asm volatile ("fstcw %0" : "=m" (fpuc)); 858 for(i=0;i<4;i++) { 859 uint16_t val16; 860 val16 = (fpuc & ~0x0c00) | (i << 10); 861 asm volatile ("fldcw %0" : : "m" (val16)); 862 asm volatile ("fists %0" : "=m" (wa) : "t" (a)); 863 asm volatile ("fistl %0" : "=m" (ia) : "t" (a)); 864 asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st"); 865 asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a)); 866 asm volatile ("fldcw %0" : : "m" (fpuc)); 867 printf("(short)a = %d\n", wa); 868 printf("(int)a = %d\n", ia); 869 printf("(int64_t)a = " FMT64X "\n", lla); 870 printf("rint(a) = %f\n", ra); 871 } 872 } 873 874 #define TEST(N) \ 875 asm("fld" #N : "=t" (a)); \ 876 printf("fld" #N "= %f\n", a); 877 878 void test_fconst(void) 879 { 880 double a; 881 TEST(1); 882 TEST(l2t); 883 TEST(l2e); 884 TEST(pi); 885 TEST(lg2); 886 TEST(ln2); 887 TEST(z); 888 } 889 890 void test_fbcd(double a) 891 { 892 unsigned short bcd[5]; 893 double b; 894 895 asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st"); 896 asm("fbld %1" : "=t" (b) : "m" (bcd[0])); 897 printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 898 a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b); 899 } 900 901 #define TEST_ENV(env, save, restore)\ 902 {\ 903 memset((env), 0xaa, sizeof(*(env)));\ 904 for(i=0;i<5;i++)\ 905 asm volatile ("fldl %0" : : "m" (dtab[i]));\ 906 asm volatile (save " %0\n" : : "m" (*(env)));\ 907 asm volatile (restore " %0\n": : "m" (*(env)));\ 908 for(i=0;i<5;i++)\ 909 asm volatile ("fstpl %0" : "=m" (rtab[i]));\ 910 for(i=0;i<5;i++)\ 911 printf("res[%d]=%f\n", i, rtab[i]);\ 912 printf("fpuc=%04x fpus=%04x fptag=%04x\n",\ 913 (env)->fpuc,\ 914 (env)->fpus & 0xff00,\ 915 (env)->fptag);\ 916 } 917 918 void test_fenv(void) 919 { 920 struct __attribute__((__packed__)) { 921 uint16_t fpuc; 922 uint16_t dummy1; 923 uint16_t fpus; 924 uint16_t dummy2; 925 uint16_t fptag; 926 uint16_t dummy3; 927 uint32_t ignored[4]; 928 long double fpregs[8]; 929 } float_env32; 930 struct __attribute__((__packed__)) { 931 uint16_t fpuc; 932 uint16_t fpus; 933 uint16_t fptag; 934 uint16_t ignored[4]; 935 long double fpregs[8]; 936 } float_env16; 937 double dtab[8]; 938 double rtab[8]; 939 int i; 940 941 for(i=0;i<8;i++) 942 dtab[i] = i + 1; 943 944 TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); 945 TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); 946 TEST_ENV(&float_env32, "fnstenv", "fldenv"); 947 TEST_ENV(&float_env32, "fnsave", "frstor"); 948 949 /* test for ffree */ 950 for(i=0;i<5;i++) 951 asm volatile ("fldl %0" : : "m" (dtab[i])); 952 asm volatile("ffree %st(2)"); 953 asm volatile ("fnstenv %0\n" : : "m" (float_env32)); 954 asm volatile ("fninit"); 955 printf("fptag=%04x\n", float_env32.fptag); 956 } 957 958 959 #define TEST_FCMOV(a, b, eflags, CC)\ 960 {\ 961 double res;\ 962 asm("push %3\n"\ 963 "popf\n"\ 964 "fcmov" CC " %2, %0\n"\ 965 : "=t" (res)\ 966 : "0" (a), "u" (b), "g" (eflags));\ 967 printf("fcmov%s eflags=0x%04lx-> %f\n", \ 968 CC, (long)eflags, res);\ 969 } 970 971 void test_fcmov(void) 972 { 973 double a, b; 974 long eflags, i; 975 976 a = 1.0; 977 b = 2.0; 978 for(i = 0; i < 4; i++) { 979 eflags = 0; 980 if (i & 1) 981 eflags |= CC_C; 982 if (i & 2) 983 eflags |= CC_Z; 984 TEST_FCMOV(a, b, eflags, "b"); 985 TEST_FCMOV(a, b, eflags, "e"); 986 TEST_FCMOV(a, b, eflags, "be"); 987 TEST_FCMOV(a, b, eflags, "nb"); 988 TEST_FCMOV(a, b, eflags, "ne"); 989 TEST_FCMOV(a, b, eflags, "nbe"); 990 } 991 TEST_FCMOV(a, b, 0, "u"); 992 TEST_FCMOV(a, b, CC_P, "u"); 993 TEST_FCMOV(a, b, 0, "nu"); 994 TEST_FCMOV(a, b, CC_P, "nu"); 995 } 996 997 void test_floats(void) 998 { 999 test_fops(2, 3); 1000 test_fops(1.4, -5); 1001 test_fcmp(2, -1); 1002 test_fcmp(2, 2); 1003 test_fcmp(2, 3); 1004 test_fcmp(2, q_nan.d); 1005 test_fcmp(q_nan.d, -1); 1006 test_fcmp(-1.0/0.0, -1); 1007 test_fcmp(1.0/0.0, -1); 1008 test_fcvt(0.5); 1009 test_fcvt(-0.5); 1010 test_fcvt(1.0/7.0); 1011 test_fcvt(-1.0/9.0); 1012 test_fcvt(32768); 1013 test_fcvt(-1e20); 1014 test_fcvt(-1.0/0.0); 1015 test_fcvt(1.0/0.0); 1016 test_fcvt(q_nan.d); 1017 test_fconst(); 1018 test_fbcd(1234567890123456.0); 1019 test_fbcd(-123451234567890.0); 1020 test_fenv(); 1021 if (TEST_CMOV) { 1022 test_fcmov(); 1023 } 1024 } 1025 1026 /**********************************************/ 1027 #if !defined(__x86_64__) 1028 1029 #define TEST_BCD(op, op0, cc_in, cc_mask)\ 1030 {\ 1031 int res, flags;\ 1032 res = op0;\ 1033 flags = cc_in;\ 1034 asm ("push %3\n\t"\ 1035 "popf\n\t"\ 1036 #op "\n\t"\ 1037 "pushf\n\t"\ 1038 "pop %1\n\t"\ 1039 : "=a" (res), "=g" (flags)\ 1040 : "0" (res), "1" (flags));\ 1041 printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\ 1042 #op, op0, res, cc_in, flags & cc_mask);\ 1043 } 1044 1045 void test_bcd(void) 1046 { 1047 TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1048 TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1049 TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1050 TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1051 TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1052 TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1053 TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1054 TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1055 TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1056 TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1057 TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1058 TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1059 TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1060 1061 TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1062 TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1063 TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1064 TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1065 TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1066 TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1067 TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1068 TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1069 TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1070 TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1071 TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1072 TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1073 TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); 1074 1075 TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A)); 1076 TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A)); 1077 TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A)); 1078 TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A)); 1079 TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A)); 1080 TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A)); 1081 TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A)); 1082 TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A)); 1083 1084 TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A)); 1085 TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A)); 1086 TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A)); 1087 TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A)); 1088 TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A)); 1089 TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A)); 1090 TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A)); 1091 TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A)); 1092 1093 TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); 1094 TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); 1095 } 1096 #endif 1097 1098 #define TEST_XCHG(op, size, opconst)\ 1099 {\ 1100 long op0, op1;\ 1101 op0 = i2l(0x12345678);\ 1102 op1 = i2l(0xfbca7654);\ 1103 asm(#op " %" size "0, %" size "1" \ 1104 : "=q" (op0), opconst (op1) \ 1105 : "0" (op0));\ 1106 printf("%-10s A=" FMTLX " B=" FMTLX "\n",\ 1107 #op, op0, op1);\ 1108 } 1109 1110 #define TEST_CMPXCHG(op, size, opconst, eax)\ 1111 {\ 1112 long op0, op1, op2;\ 1113 op0 = i2l(0x12345678);\ 1114 op1 = i2l(0xfbca7654);\ 1115 op2 = i2l(eax);\ 1116 asm(#op " %" size "0, %" size "1" \ 1117 : "=q" (op0), opconst (op1) \ 1118 : "0" (op0), "a" (op2));\ 1119 printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\ 1120 #op, op2, op0, op1);\ 1121 } 1122 1123 void test_xchg(void) 1124 { 1125 #if defined(__x86_64__) 1126 TEST_XCHG(xchgq, "", "+q"); 1127 #endif 1128 TEST_XCHG(xchgl, "k", "+q"); 1129 TEST_XCHG(xchgw, "w", "+q"); 1130 TEST_XCHG(xchgb, "b", "+q"); 1131 1132 #if defined(__x86_64__) 1133 TEST_XCHG(xchgq, "", "+m"); 1134 #endif 1135 TEST_XCHG(xchgl, "k", "+m"); 1136 TEST_XCHG(xchgw, "w", "+m"); 1137 TEST_XCHG(xchgb, "b", "+m"); 1138 1139 #if defined(__x86_64__) 1140 TEST_XCHG(xaddq, "", "+q"); 1141 #endif 1142 TEST_XCHG(xaddl, "k", "+q"); 1143 TEST_XCHG(xaddw, "w", "+q"); 1144 TEST_XCHG(xaddb, "b", "+q"); 1145 1146 { 1147 int res; 1148 res = 0x12345678; 1149 asm("xaddl %1, %0" : "=r" (res) : "0" (res)); 1150 printf("xaddl same res=%08x\n", res); 1151 } 1152 1153 #if defined(__x86_64__) 1154 TEST_XCHG(xaddq, "", "+m"); 1155 #endif 1156 TEST_XCHG(xaddl, "k", "+m"); 1157 TEST_XCHG(xaddw, "w", "+m"); 1158 TEST_XCHG(xaddb, "b", "+m"); 1159 1160 #if defined(__x86_64__) 1161 TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654); 1162 #endif 1163 TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654); 1164 TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654); 1165 TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654); 1166 1167 #if defined(__x86_64__) 1168 TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc); 1169 #endif 1170 TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc); 1171 TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc); 1172 TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc); 1173 1174 #if defined(__x86_64__) 1175 TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654); 1176 #endif 1177 TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654); 1178 TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654); 1179 TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654); 1180 1181 #if defined(__x86_64__) 1182 TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc); 1183 #endif 1184 TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc); 1185 TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc); 1186 TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc); 1187 1188 { 1189 uint64_t op0, op1, op2; 1190 long eax, edx; 1191 long i, eflags; 1192 1193 for(i = 0; i < 2; i++) { 1194 op0 = 0x123456789abcdLL; 1195 eax = i2l(op0 & 0xffffffff); 1196 edx = i2l(op0 >> 32); 1197 if (i == 0) 1198 op1 = 0xfbca765423456LL; 1199 else 1200 op1 = op0; 1201 op2 = 0x6532432432434LL; 1202 asm("cmpxchg8b %2\n" 1203 "pushf\n" 1204 "pop %3\n" 1205 : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags) 1206 : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32))); 1207 printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n", 1208 eax, edx, op1, eflags & CC_Z); 1209 } 1210 } 1211 } 1212 1213 #ifdef TEST_SEGS 1214 /**********************************************/ 1215 /* segmentation tests */ 1216 1217 #include <sys/syscall.h> 1218 #include <unistd.h> 1219 #include <asm/ldt.h> 1220 #include <linux/version.h> 1221 1222 static inline int modify_ldt(int func, void * ptr, unsigned long bytecount) 1223 { 1224 return syscall(__NR_modify_ldt, func, ptr, bytecount); 1225 } 1226 1227 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66) 1228 #define modify_ldt_ldt_s user_desc 1229 #endif 1230 1231 #define MK_SEL(n) (((n) << 3) | 7) 1232 1233 uint8_t seg_data1[4096]; 1234 uint8_t seg_data2[4096]; 1235 1236 #define TEST_LR(op, size, seg, mask)\ 1237 {\ 1238 int res, res2;\ 1239 uint16_t mseg = seg;\ 1240 res = 0x12345678;\ 1241 asm (op " %" size "2, %" size "0\n" \ 1242 "movl $0, %1\n"\ 1243 "jnz 1f\n"\ 1244 "movl $1, %1\n"\ 1245 "1:\n"\ 1246 : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\ 1247 printf(op ": Z=%d %08x\n", res2, res & ~(mask));\ 1248 } 1249 1250 #define TEST_ARPL(op, size, op1, op2)\ 1251 {\ 1252 long a, b, c; \ 1253 a = (op1); \ 1254 b = (op2); \ 1255 asm volatile(op " %" size "3, %" size "0\n"\ 1256 "movl $0,%1\n"\ 1257 "jnz 1f\n"\ 1258 "movl $1,%1\n"\ 1259 "1:\n"\ 1260 : "=r" (a), "=r" (c) : "0" (a), "r" (b)); \ 1261 printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\ 1262 (long)(op1), (long)(op2), a, c);\ 1263 } 1264 1265 /* NOTE: we use Linux modify_ldt syscall */ 1266 void test_segs(void) 1267 { 1268 struct modify_ldt_ldt_s ldt; 1269 long long ldt_table[3]; 1270 int res, res2; 1271 char tmp; 1272 struct { 1273 uint32_t offset; 1274 uint16_t seg; 1275 } __attribute__((__packed__)) segoff; 1276 1277 ldt.entry_number = 1; 1278 ldt.base_addr = (unsigned long)&seg_data1; 1279 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; 1280 ldt.seg_32bit = 1; 1281 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1282 ldt.read_exec_only = 0; 1283 ldt.limit_in_pages = 1; 1284 ldt.seg_not_present = 0; 1285 ldt.useable = 1; 1286 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1287 1288 ldt.entry_number = 2; 1289 ldt.base_addr = (unsigned long)&seg_data2; 1290 ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12; 1291 ldt.seg_32bit = 1; 1292 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1293 ldt.read_exec_only = 0; 1294 ldt.limit_in_pages = 1; 1295 ldt.seg_not_present = 0; 1296 ldt.useable = 1; 1297 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1298 1299 modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ 1300 #if 0 1301 { 1302 int i; 1303 for(i=0;i<3;i++) 1304 printf("%d: %016Lx\n", i, ldt_table[i]); 1305 } 1306 #endif 1307 /* do some tests with fs or gs */ 1308 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); 1309 1310 seg_data1[1] = 0xaa; 1311 seg_data2[1] = 0x55; 1312 1313 asm volatile ("fs movzbl 0x1, %0" : "=r" (res)); 1314 printf("FS[1] = %02x\n", res); 1315 1316 asm volatile ("pushl %%gs\n" 1317 "movl %1, %%gs\n" 1318 "gs movzbl 0x1, %0\n" 1319 "popl %%gs\n" 1320 : "=r" (res) 1321 : "r" (MK_SEL(2))); 1322 printf("GS[1] = %02x\n", res); 1323 1324 /* tests with ds/ss (implicit segment case) */ 1325 tmp = 0xa5; 1326 asm volatile ("pushl %%ebp\n\t" 1327 "pushl %%ds\n\t" 1328 "movl %2, %%ds\n\t" 1329 "movl %3, %%ebp\n\t" 1330 "movzbl 0x1, %0\n\t" 1331 "movzbl (%%ebp), %1\n\t" 1332 "popl %%ds\n\t" 1333 "popl %%ebp\n\t" 1334 : "=r" (res), "=r" (res2) 1335 : "r" (MK_SEL(1)), "r" (&tmp)); 1336 printf("DS[1] = %02x\n", res); 1337 printf("SS[tmp] = %02x\n", res2); 1338 1339 segoff.seg = MK_SEL(2); 1340 segoff.offset = 0xabcdef12; 1341 asm volatile("lfs %2, %0\n\t" 1342 "movl %%fs, %1\n\t" 1343 : "=r" (res), "=g" (res2) 1344 : "m" (segoff)); 1345 printf("FS:reg = %04x:%08x\n", res2, res); 1346 1347 TEST_LR("larw", "w", MK_SEL(2), 0x0100); 1348 TEST_LR("larl", "", MK_SEL(2), 0x0100); 1349 TEST_LR("lslw", "w", MK_SEL(2), 0); 1350 TEST_LR("lsll", "", MK_SEL(2), 0); 1351 1352 TEST_LR("larw", "w", 0xfff8, 0); 1353 TEST_LR("larl", "", 0xfff8, 0); 1354 TEST_LR("lslw", "w", 0xfff8, 0); 1355 TEST_LR("lsll", "", 0xfff8, 0); 1356 1357 TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1); 1358 TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3); 1359 TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1); 1360 } 1361 1362 /* 16 bit code test */ 1363 extern char code16_start, code16_end; 1364 extern char code16_func1; 1365 extern char code16_func2; 1366 extern char code16_func3; 1367 1368 void test_code16(void) 1369 { 1370 struct modify_ldt_ldt_s ldt; 1371 int res, res2; 1372 1373 /* build a code segment */ 1374 ldt.entry_number = 1; 1375 ldt.base_addr = (unsigned long)&code16_start; 1376 ldt.limit = &code16_end - &code16_start; 1377 ldt.seg_32bit = 0; 1378 ldt.contents = MODIFY_LDT_CONTENTS_CODE; 1379 ldt.read_exec_only = 0; 1380 ldt.limit_in_pages = 0; 1381 ldt.seg_not_present = 0; 1382 ldt.useable = 1; 1383 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1384 1385 /* call the first function */ 1386 asm volatile ("lcall %1, %2" 1387 : "=a" (res) 1388 : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc"); 1389 printf("func1() = 0x%08x\n", res); 1390 asm volatile ("lcall %2, %3" 1391 : "=a" (res), "=c" (res2) 1392 : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc"); 1393 printf("func2() = 0x%08x spdec=%d\n", res, res2); 1394 asm volatile ("lcall %1, %2" 1395 : "=a" (res) 1396 : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc"); 1397 printf("func3() = 0x%08x\n", res); 1398 } 1399 #endif 1400 1401 #if defined(__x86_64__) 1402 asm(".globl func_lret\n" 1403 "func_lret:\n" 1404 "movl $0x87654641, %eax\n" 1405 "lretq\n"); 1406 #else 1407 asm(".globl func_lret\n" 1408 "func_lret:\n" 1409 "movl $0x87654321, %eax\n" 1410 "lret\n" 1411 1412 ".globl func_iret\n" 1413 "func_iret:\n" 1414 "movl $0xabcd4321, %eax\n" 1415 "iret\n"); 1416 #endif 1417 1418 extern char func_lret; 1419 extern char func_iret; 1420 1421 void test_misc(void) 1422 { 1423 char table[256]; 1424 long res, i; 1425 1426 for(i=0;i<256;i++) table[i] = 256 - i; 1427 res = 0x12345678; 1428 asm ("xlat" : "=a" (res) : "b" (table), "0" (res)); 1429 printf("xlat: EAX=" FMTLX "\n", res); 1430 1431 #if defined(__x86_64__) 1432 #if 0 1433 { 1434 /* XXX: see if Intel Core2 and AMD64 behavior really 1435 differ. Here we implemented the Intel way which is not 1436 compatible yet with QEMU. */ 1437 static struct QEMU_PACKED { 1438 uint64_t offset; 1439 uint16_t seg; 1440 } desc; 1441 long cs_sel; 1442 1443 asm volatile ("mov %%cs, %0" : "=r" (cs_sel)); 1444 1445 asm volatile ("push %1\n" 1446 "call func_lret\n" 1447 : "=a" (res) 1448 : "r" (cs_sel) : "memory", "cc"); 1449 printf("func_lret=" FMTLX "\n", res); 1450 1451 desc.offset = (long)&func_lret; 1452 desc.seg = cs_sel; 1453 1454 asm volatile ("xor %%rax, %%rax\n" 1455 "rex64 lcall *(%%rcx)\n" 1456 : "=a" (res) 1457 : "c" (&desc) 1458 : "memory", "cc"); 1459 printf("func_lret2=" FMTLX "\n", res); 1460 1461 asm volatile ("push %2\n" 1462 "mov $ 1f, %%rax\n" 1463 "push %%rax\n" 1464 "rex64 ljmp *(%%rcx)\n" 1465 "1:\n" 1466 : "=a" (res) 1467 : "c" (&desc), "b" (cs_sel) 1468 : "memory", "cc"); 1469 printf("func_lret3=" FMTLX "\n", res); 1470 } 1471 #endif 1472 #else 1473 asm volatile ("push %%cs ; call %1" 1474 : "=a" (res) 1475 : "m" (func_lret): "memory", "cc"); 1476 printf("func_lret=" FMTLX "\n", res); 1477 1478 asm volatile ("pushf ; push %%cs ; call %1" 1479 : "=a" (res) 1480 : "m" (func_iret): "memory", "cc"); 1481 printf("func_iret=" FMTLX "\n", res); 1482 #endif 1483 1484 #if defined(__x86_64__) 1485 /* specific popl test */ 1486 asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0" 1487 : "=g" (res)); 1488 printf("popl esp=" FMTLX "\n", res); 1489 #else 1490 /* specific popl test */ 1491 asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0" 1492 : "=g" (res)); 1493 printf("popl esp=" FMTLX "\n", res); 1494 1495 /* specific popw test */ 1496 asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0" 1497 : "=g" (res)); 1498 printf("popw esp=" FMTLX "\n", res); 1499 #endif 1500 } 1501 1502 uint8_t str_buffer[4096]; 1503 1504 #define TEST_STRING1(OP, size, DF, REP)\ 1505 {\ 1506 long esi, edi, eax, ecx, eflags;\ 1507 \ 1508 esi = (long)(str_buffer + sizeof(str_buffer) / 2);\ 1509 edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\ 1510 eax = i2l(0x12345678);\ 1511 ecx = 17;\ 1512 \ 1513 asm volatile ("push $0\n\t"\ 1514 "popf\n\t"\ 1515 DF "\n\t"\ 1516 REP #OP size "\n\t"\ 1517 "cld\n\t"\ 1518 "pushf\n\t"\ 1519 "pop %4\n\t"\ 1520 : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\ 1521 : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\ 1522 printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\ 1523 REP #OP size, esi, edi, eax, ecx,\ 1524 (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\ 1525 } 1526 1527 #define TEST_STRING(OP, REP)\ 1528 TEST_STRING1(OP, "b", "", REP);\ 1529 TEST_STRING1(OP, "w", "", REP);\ 1530 TEST_STRING1(OP, "l", "", REP);\ 1531 X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\ 1532 TEST_STRING1(OP, "b", "std", REP);\ 1533 TEST_STRING1(OP, "w", "std", REP);\ 1534 TEST_STRING1(OP, "l", "std", REP);\ 1535 X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP)) 1536 1537 void test_string(void) 1538 { 1539 int i; 1540 for(i = 0;i < sizeof(str_buffer); i++) 1541 str_buffer[i] = i + 0x56; 1542 TEST_STRING(stos, ""); 1543 TEST_STRING(stos, "rep "); 1544 TEST_STRING(lods, ""); /* to verify stos */ 1545 TEST_STRING(lods, "rep "); 1546 TEST_STRING(movs, ""); 1547 TEST_STRING(movs, "rep "); 1548 TEST_STRING(lods, ""); /* to verify stos */ 1549 1550 /* XXX: better tests */ 1551 TEST_STRING(scas, ""); 1552 TEST_STRING(scas, "repz "); 1553 TEST_STRING(scas, "repnz "); 1554 TEST_STRING(cmps, ""); 1555 TEST_STRING(cmps, "repz "); 1556 TEST_STRING(cmps, "repnz "); 1557 } 1558 1559 #ifdef TEST_VM86 1560 /* VM86 test */ 1561 1562 static inline void set_bit(uint8_t *a, unsigned int bit) 1563 { 1564 a[bit / 8] |= (1 << (bit % 8)); 1565 } 1566 1567 static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) 1568 { 1569 return (uint8_t *)((seg << 4) + (reg & 0xffff)); 1570 } 1571 1572 static inline void pushw(struct vm86_regs *r, int val) 1573 { 1574 r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); 1575 *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; 1576 } 1577 1578 static inline int vm86(int func, struct vm86plus_struct *v86) 1579 { 1580 return syscall(__NR_vm86, func, v86); 1581 } 1582 1583 extern char vm86_code_start; 1584 extern char vm86_code_end; 1585 1586 #define VM86_CODE_CS 0x100 1587 #define VM86_CODE_IP 0x100 1588 1589 void test_vm86(void) 1590 { 1591 struct vm86plus_struct ctx; 1592 struct vm86_regs *r; 1593 uint8_t *vm86_mem; 1594 int seg, ret; 1595 1596 vm86_mem = mmap((void *)0x00000000, 0x110000, 1597 PROT_WRITE | PROT_READ | PROT_EXEC, 1598 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 1599 if (vm86_mem == MAP_FAILED) { 1600 printf("ERROR: could not map vm86 memory"); 1601 return; 1602 } 1603 memset(&ctx, 0, sizeof(ctx)); 1604 1605 /* init basic registers */ 1606 r = &ctx.regs; 1607 r->eip = VM86_CODE_IP; 1608 r->esp = 0xfffe; 1609 seg = VM86_CODE_CS; 1610 r->cs = seg; 1611 r->ss = seg; 1612 r->ds = seg; 1613 r->es = seg; 1614 r->fs = seg; 1615 r->gs = seg; 1616 r->eflags = VIF_MASK; 1617 1618 /* move code to proper address. We use the same layout as a .com 1619 dos program. */ 1620 memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP, 1621 &vm86_code_start, &vm86_code_end - &vm86_code_start); 1622 1623 /* mark int 0x21 as being emulated */ 1624 set_bit((uint8_t *)&ctx.int_revectored, 0x21); 1625 1626 for(;;) { 1627 ret = vm86(VM86_ENTER, &ctx); 1628 switch(VM86_TYPE(ret)) { 1629 case VM86_INTx: 1630 { 1631 int int_num, ah, v; 1632 1633 int_num = VM86_ARG(ret); 1634 if (int_num != 0x21) 1635 goto unknown_int; 1636 ah = (r->eax >> 8) & 0xff; 1637 switch(ah) { 1638 case 0x00: /* exit */ 1639 goto the_end; 1640 case 0x02: /* write char */ 1641 { 1642 uint8_t c = r->edx; 1643 putchar(c); 1644 } 1645 break; 1646 case 0x09: /* write string */ 1647 { 1648 uint8_t c, *ptr; 1649 ptr = seg_to_linear(r->ds, r->edx); 1650 for(;;) { 1651 c = *ptr++; 1652 if (c == '$') 1653 break; 1654 putchar(c); 1655 } 1656 r->eax = (r->eax & ~0xff) | '$'; 1657 } 1658 break; 1659 case 0xff: /* extension: write eflags number in edx */ 1660 v = (int)r->edx; 1661 #ifndef LINUX_VM86_IOPL_FIX 1662 v &= ~0x3000; 1663 #endif 1664 printf("%08x\n", v); 1665 break; 1666 default: 1667 unknown_int: 1668 printf("unsupported int 0x%02x\n", int_num); 1669 goto the_end; 1670 } 1671 } 1672 break; 1673 case VM86_SIGNAL: 1674 /* a signal came, we just ignore that */ 1675 break; 1676 case VM86_STI: 1677 break; 1678 default: 1679 printf("ERROR: unhandled vm86 return code (0x%x)\n", ret); 1680 goto the_end; 1681 } 1682 } 1683 the_end: 1684 printf("VM86 end\n"); 1685 munmap(vm86_mem, 0x110000); 1686 } 1687 #endif 1688 1689 /* exception tests */ 1690 #if defined(__i386__) && !defined(REG_EAX) 1691 #define REG_EAX EAX 1692 #define REG_EBX EBX 1693 #define REG_ECX ECX 1694 #define REG_EDX EDX 1695 #define REG_ESI ESI 1696 #define REG_EDI EDI 1697 #define REG_EBP EBP 1698 #define REG_ESP ESP 1699 #define REG_EIP EIP 1700 #define REG_EFL EFL 1701 #define REG_TRAPNO TRAPNO 1702 #define REG_ERR ERR 1703 #endif 1704 1705 #if defined(__x86_64__) 1706 #define REG_EIP REG_RIP 1707 #endif 1708 1709 jmp_buf jmp_env; 1710 int v1; 1711 int tab[2]; 1712 1713 void sig_handler(int sig, siginfo_t *info, void *puc) 1714 { 1715 ucontext_t *uc = puc; 1716 1717 printf("si_signo=%d si_errno=%d si_code=%d", 1718 info->si_signo, info->si_errno, info->si_code); 1719 printf(" si_addr=0x%08lx", 1720 (unsigned long)info->si_addr); 1721 printf("\n"); 1722 1723 printf("trapno=" FMTLX " err=" FMTLX, 1724 (long)uc->uc_mcontext.gregs[REG_TRAPNO], 1725 (long)uc->uc_mcontext.gregs[REG_ERR]); 1726 printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]); 1727 printf("\n"); 1728 longjmp(jmp_env, 1); 1729 } 1730 1731 void test_exceptions(void) 1732 { 1733 struct sigaction act; 1734 volatile int val; 1735 1736 act.sa_sigaction = sig_handler; 1737 sigemptyset(&act.sa_mask); 1738 act.sa_flags = SA_SIGINFO | SA_NODEFER; 1739 sigaction(SIGFPE, &act, NULL); 1740 sigaction(SIGILL, &act, NULL); 1741 sigaction(SIGSEGV, &act, NULL); 1742 sigaction(SIGBUS, &act, NULL); 1743 sigaction(SIGTRAP, &act, NULL); 1744 1745 /* test division by zero reporting */ 1746 printf("DIVZ exception:\n"); 1747 if (setjmp(jmp_env) == 0) { 1748 /* now divide by zero */ 1749 v1 = 0; 1750 v1 = 2 / v1; 1751 } 1752 1753 #if !defined(__x86_64__) 1754 printf("BOUND exception:\n"); 1755 if (setjmp(jmp_env) == 0) { 1756 /* bound exception */ 1757 tab[0] = 1; 1758 tab[1] = 10; 1759 asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0])); 1760 } 1761 #endif 1762 1763 #ifdef TEST_SEGS 1764 printf("segment exceptions:\n"); 1765 if (setjmp(jmp_env) == 0) { 1766 /* load an invalid segment */ 1767 asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1)); 1768 } 1769 if (setjmp(jmp_env) == 0) { 1770 /* null data segment is valid */ 1771 asm volatile ("movl %0, %%fs" : : "r" (3)); 1772 /* null stack segment */ 1773 asm volatile ("movl %0, %%ss" : : "r" (3)); 1774 } 1775 1776 { 1777 struct modify_ldt_ldt_s ldt; 1778 ldt.entry_number = 1; 1779 ldt.base_addr = (unsigned long)&seg_data1; 1780 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; 1781 ldt.seg_32bit = 1; 1782 ldt.contents = MODIFY_LDT_CONTENTS_DATA; 1783 ldt.read_exec_only = 0; 1784 ldt.limit_in_pages = 1; 1785 ldt.seg_not_present = 1; 1786 ldt.useable = 1; 1787 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ 1788 1789 if (setjmp(jmp_env) == 0) { 1790 /* segment not present */ 1791 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); 1792 } 1793 } 1794 #endif 1795 1796 /* test SEGV reporting */ 1797 printf("PF exception:\n"); 1798 if (setjmp(jmp_env) == 0) { 1799 val = 1; 1800 /* we add a nop to test a weird PC retrieval case */ 1801 asm volatile ("nop"); 1802 /* now store in an invalid address */ 1803 *(char *)0x1234 = 1; 1804 } 1805 1806 /* test SEGV reporting */ 1807 printf("PF exception:\n"); 1808 if (setjmp(jmp_env) == 0) { 1809 val = 1; 1810 /* read from an invalid address */ 1811 v1 = *(char *)0x1234; 1812 } 1813 1814 /* test illegal instruction reporting */ 1815 printf("UD2 exception:\n"); 1816 if (setjmp(jmp_env) == 0) { 1817 /* now execute an invalid instruction */ 1818 asm volatile("ud2"); 1819 } 1820 printf("lock nop exception:\n"); 1821 if (setjmp(jmp_env) == 0) { 1822 /* now execute an invalid instruction */ 1823 asm volatile(".byte 0xf0, 0x90"); 1824 } 1825 1826 printf("INT exception:\n"); 1827 if (setjmp(jmp_env) == 0) { 1828 asm volatile ("int $0xfd"); 1829 } 1830 if (setjmp(jmp_env) == 0) { 1831 asm volatile ("int $0x01"); 1832 } 1833 if (setjmp(jmp_env) == 0) { 1834 asm volatile (".byte 0xcd, 0x03"); 1835 } 1836 if (setjmp(jmp_env) == 0) { 1837 asm volatile ("int $0x04"); 1838 } 1839 if (setjmp(jmp_env) == 0) { 1840 asm volatile ("int $0x05"); 1841 } 1842 1843 printf("INT3 exception:\n"); 1844 if (setjmp(jmp_env) == 0) { 1845 asm volatile ("int3"); 1846 } 1847 1848 printf("CLI exception:\n"); 1849 if (setjmp(jmp_env) == 0) { 1850 asm volatile ("cli"); 1851 } 1852 1853 printf("STI exception:\n"); 1854 if (setjmp(jmp_env) == 0) { 1855 asm volatile ("cli"); 1856 } 1857 1858 #if !defined(__x86_64__) 1859 printf("INTO exception:\n"); 1860 if (setjmp(jmp_env) == 0) { 1861 /* overflow exception */ 1862 asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff)); 1863 } 1864 #endif 1865 1866 printf("OUTB exception:\n"); 1867 if (setjmp(jmp_env) == 0) { 1868 asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0)); 1869 } 1870 1871 printf("INB exception:\n"); 1872 if (setjmp(jmp_env) == 0) { 1873 asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321)); 1874 } 1875 1876 printf("REP OUTSB exception:\n"); 1877 if (setjmp(jmp_env) == 0) { 1878 asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1)); 1879 } 1880 1881 printf("REP INSB exception:\n"); 1882 if (setjmp(jmp_env) == 0) { 1883 asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1)); 1884 } 1885 1886 printf("HLT exception:\n"); 1887 if (setjmp(jmp_env) == 0) { 1888 asm volatile ("hlt"); 1889 } 1890 1891 printf("single step exception:\n"); 1892 val = 0; 1893 if (setjmp(jmp_env) == 0) { 1894 asm volatile ("pushf\n" 1895 "orl $0x00100, (%%esp)\n" 1896 "popf\n" 1897 "movl $0xabcd, %0\n" 1898 "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory"); 1899 } 1900 printf("val=0x%x\n", val); 1901 } 1902 1903 #if !defined(__x86_64__) 1904 /* specific precise single step test */ 1905 void sig_trap_handler(int sig, siginfo_t *info, void *puc) 1906 { 1907 ucontext_t *uc = puc; 1908 printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]); 1909 } 1910 1911 const uint8_t sstep_buf1[4] = { 1, 2, 3, 4}; 1912 uint8_t sstep_buf2[4]; 1913 1914 void test_single_step(void) 1915 { 1916 struct sigaction act; 1917 volatile int val; 1918 int i; 1919 1920 val = 0; 1921 act.sa_sigaction = sig_trap_handler; 1922 sigemptyset(&act.sa_mask); 1923 act.sa_flags = SA_SIGINFO; 1924 sigaction(SIGTRAP, &act, NULL); 1925 asm volatile ("pushf\n" 1926 "orl $0x00100, (%%esp)\n" 1927 "popf\n" 1928 "movl $0xabcd, %0\n" 1929 1930 /* jmp test */ 1931 "movl $3, %%ecx\n" 1932 "1:\n" 1933 "addl $1, %0\n" 1934 "decl %%ecx\n" 1935 "jnz 1b\n" 1936 1937 /* movsb: the single step should stop at each movsb iteration */ 1938 "movl $sstep_buf1, %%esi\n" 1939 "movl $sstep_buf2, %%edi\n" 1940 "movl $0, %%ecx\n" 1941 "rep movsb\n" 1942 "movl $3, %%ecx\n" 1943 "rep movsb\n" 1944 "movl $1, %%ecx\n" 1945 "rep movsb\n" 1946 1947 /* cmpsb: the single step should stop at each cmpsb iteration */ 1948 "movl $sstep_buf1, %%esi\n" 1949 "movl $sstep_buf2, %%edi\n" 1950 "movl $0, %%ecx\n" 1951 "rep cmpsb\n" 1952 "movl $4, %%ecx\n" 1953 "rep cmpsb\n" 1954 1955 /* getpid() syscall: single step should skip one 1956 instruction */ 1957 "movl $20, %%eax\n" 1958 "int $0x80\n" 1959 "movl $0, %%eax\n" 1960 1961 /* when modifying SS, trace is not done on the next 1962 instruction */ 1963 "movl %%ss, %%ecx\n" 1964 "movl %%ecx, %%ss\n" 1965 "addl $1, %0\n" 1966 "movl $1, %%eax\n" 1967 "movl %%ecx, %%ss\n" 1968 "jmp 1f\n" 1969 "addl $1, %0\n" 1970 "1:\n" 1971 "movl $1, %%eax\n" 1972 "pushl %%ecx\n" 1973 "popl %%ss\n" 1974 "addl $1, %0\n" 1975 "movl $1, %%eax\n" 1976 1977 "pushf\n" 1978 "andl $~0x00100, (%%esp)\n" 1979 "popf\n" 1980 : "=m" (val) 1981 : 1982 : "cc", "memory", "eax", "ecx", "esi", "edi"); 1983 printf("val=%d\n", val); 1984 for(i = 0; i < 4; i++) 1985 printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]); 1986 } 1987 1988 /* self modifying code test */ 1989 uint8_t code[] = { 1990 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */ 1991 0xc3, /* ret */ 1992 }; 1993 1994 asm(".section \".data_x\",\"awx\"\n" 1995 "smc_code2:\n" 1996 "movl 4(%esp), %eax\n" 1997 "movl %eax, smc_patch_addr2 + 1\n" 1998 "nop\n" 1999 "nop\n" 2000 "nop\n" 2001 "nop\n" 2002 "nop\n" 2003 "nop\n" 2004 "nop\n" 2005 "nop\n" 2006 "smc_patch_addr2:\n" 2007 "movl $1, %eax\n" 2008 "ret\n" 2009 ".previous\n" 2010 ); 2011 2012 typedef int FuncType(void); 2013 extern int smc_code2(int); 2014 void test_self_modifying_code(void) 2015 { 2016 int i; 2017 printf("self modifying code:\n"); 2018 printf("func1 = 0x%x\n", ((FuncType *)code)()); 2019 for(i = 2; i <= 4; i++) { 2020 code[1] = i; 2021 printf("func%d = 0x%x\n", i, ((FuncType *)code)()); 2022 } 2023 2024 /* more difficult test : the modified code is just after the 2025 modifying instruction. It is forbidden in Intel specs, but it 2026 is used by old DOS programs */ 2027 for(i = 2; i <= 4; i++) { 2028 printf("smc_code2(%d) = %d\n", i, smc_code2(i)); 2029 } 2030 } 2031 #endif 2032 2033 long enter_stack[4096]; 2034 2035 #if defined(__x86_64__) 2036 #define RSP "%%rsp" 2037 #define RBP "%%rbp" 2038 #else 2039 #define RSP "%%esp" 2040 #define RBP "%%ebp" 2041 #endif 2042 2043 #if !defined(__x86_64__) 2044 /* causes an infinite loop, disable it for now. */ 2045 #define TEST_ENTER(size, stack_type, level) 2046 #else 2047 #define TEST_ENTER(size, stack_type, level)\ 2048 {\ 2049 long esp_save, esp_val, ebp_val, ebp_save, i;\ 2050 stack_type *ptr, *stack_end, *stack_ptr;\ 2051 memset(enter_stack, 0, sizeof(enter_stack));\ 2052 stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\ 2053 ebp_val = (long)stack_ptr;\ 2054 for(i=1;i<=32;i++)\ 2055 *--stack_ptr = i;\ 2056 esp_val = (long)stack_ptr;\ 2057 asm("mov " RSP ", %[esp_save]\n"\ 2058 "mov " RBP ", %[ebp_save]\n"\ 2059 "mov %[esp_val], " RSP "\n"\ 2060 "mov %[ebp_val], " RBP "\n"\ 2061 "enter" size " $8, $" #level "\n"\ 2062 "mov " RSP ", %[esp_val]\n"\ 2063 "mov " RBP ", %[ebp_val]\n"\ 2064 "mov %[esp_save], " RSP "\n"\ 2065 "mov %[ebp_save], " RBP "\n"\ 2066 : [esp_save] "=r" (esp_save),\ 2067 [ebp_save] "=r" (ebp_save),\ 2068 [esp_val] "=r" (esp_val),\ 2069 [ebp_val] "=r" (ebp_val)\ 2070 : "[esp_val]" (esp_val),\ 2071 "[ebp_val]" (ebp_val));\ 2072 printf("level=%d:\n", level);\ 2073 printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\ 2074 printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\ 2075 for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\ 2076 printf(FMTLX "\n", (long)ptr[0]);\ 2077 } 2078 #endif 2079 2080 static void test_enter(void) 2081 { 2082 #if defined(__x86_64__) 2083 TEST_ENTER("q", uint64_t, 0); 2084 TEST_ENTER("q", uint64_t, 1); 2085 TEST_ENTER("q", uint64_t, 2); 2086 TEST_ENTER("q", uint64_t, 31); 2087 #else 2088 TEST_ENTER("l", uint32_t, 0); 2089 TEST_ENTER("l", uint32_t, 1); 2090 TEST_ENTER("l", uint32_t, 2); 2091 TEST_ENTER("l", uint32_t, 31); 2092 #endif 2093 2094 TEST_ENTER("w", uint16_t, 0); 2095 TEST_ENTER("w", uint16_t, 1); 2096 TEST_ENTER("w", uint16_t, 2); 2097 TEST_ENTER("w", uint16_t, 31); 2098 } 2099 2100 #define TEST_CONV_RAX(op)\ 2101 {\ 2102 unsigned long a, r;\ 2103 a = i2l(0x8234a6f8);\ 2104 r = a;\ 2105 asm volatile(#op : "=a" (r) : "0" (r));\ 2106 printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\ 2107 } 2108 2109 #define TEST_CONV_RAX_RDX(op)\ 2110 {\ 2111 unsigned long a, d, r, rh; \ 2112 a = i2l(0x8234a6f8);\ 2113 d = i2l(0x8345a1f2);\ 2114 r = a;\ 2115 rh = d;\ 2116 asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh)); \ 2117 printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh); \ 2118 } 2119 2120 void test_conv(void) 2121 { 2122 TEST_CONV_RAX(cbw); 2123 TEST_CONV_RAX(cwde); 2124 #if defined(__x86_64__) 2125 TEST_CONV_RAX(cdqe); 2126 #endif 2127 2128 TEST_CONV_RAX_RDX(cwd); 2129 TEST_CONV_RAX_RDX(cdq); 2130 #if defined(__x86_64__) 2131 TEST_CONV_RAX_RDX(cqo); 2132 #endif 2133 2134 { 2135 unsigned long a, r; 2136 a = i2l(0x12345678); 2137 asm volatile("bswapl %k0" : "=r" (r) : "0" (a)); 2138 printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r); 2139 } 2140 #if defined(__x86_64__) 2141 { 2142 unsigned long a, r; 2143 a = i2l(0x12345678); 2144 asm volatile("bswapq %0" : "=r" (r) : "0" (a)); 2145 printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r); 2146 } 2147 #endif 2148 } 2149 2150 extern void *__start_initcall; 2151 extern void *__stop_initcall; 2152 2153 2154 int main(int argc, char **argv) 2155 { 2156 void **ptr; 2157 void (*func)(void); 2158 2159 ptr = &__start_initcall; 2160 while (ptr != &__stop_initcall) { 2161 func = *ptr++; 2162 func(); 2163 } 2164 test_bsx(); 2165 test_mul(); 2166 test_jcc(); 2167 test_loop(); 2168 test_floats(); 2169 #if !defined(__x86_64__) 2170 test_bcd(); 2171 #endif 2172 test_xchg(); 2173 test_string(); 2174 test_misc(); 2175 test_lea(); 2176 #ifdef TEST_SEGS 2177 test_segs(); 2178 test_code16(); 2179 #endif 2180 #ifdef TEST_VM86 2181 test_vm86(); 2182 #endif 2183 #if !defined(__x86_64__) 2184 test_exceptions(); 2185 test_self_modifying_code(); 2186 test_single_step(); 2187 #endif 2188 test_enter(); 2189 test_conv(); 2190 return 0; 2191 } 2192