qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

test-i386.c (58180B)


      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 }