📄 test-i386.c
字号:
/* * x86 CPU test * * Copyright (c) 2003 Fabrice Bellard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include <math.h>#include <signal.h>#include <setjmp.h>#include <errno.h>#include <sys/ucontext.h>#include <sys/mman.h>#if !defined(__x86_64__)#define TEST_VM86#define TEST_SEGS#endif//#define LINUX_VM86_IOPL_FIX//#define TEST_P4_FLAGS#if defined(__x86_64__)#define TEST_SSE#define TEST_CMOV 1#define TEST_FCOMI 1#else//#define TEST_SSE#define TEST_CMOV 0#define TEST_FCOMI 0#endif#if defined(__x86_64__)#define FMT64X "%016lx"#define FMTLX "%016lx"#define X86_64_ONLY(x) x#else#define FMT64X "%016llx"#define FMTLX "%08lx"#define X86_64_ONLY(x)#endif#ifdef TEST_VM86#include <asm/vm86.h>#endif#define xglue(x, y) x ## y#define glue(x, y) xglue(x, y)#define stringify(s) tostring(s)#define tostring(s) #s#define CC_C 0x0001#define CC_P 0x0004#define CC_A 0x0010#define CC_Z 0x0040#define CC_S 0x0080#define CC_O 0x0800#define __init_call __attribute__ ((unused,__section__ ("initcall")))#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)#if defined(__x86_64__)static inline long i2l(long v){ return v | ((v ^ 0xabcd) << 32);}#elsestatic inline long i2l(long v){ return v;}#endif#define OP add#include "test-i386.h"#define OP sub#include "test-i386.h"#define OP xor#include "test-i386.h"#define OP and#include "test-i386.h"#define OP or#include "test-i386.h"#define OP cmp#include "test-i386.h"#define OP adc#define OP_CC#include "test-i386.h"#define OP sbb#define OP_CC#include "test-i386.h"#define OP inc#define OP_CC#define OP1#include "test-i386.h"#define OP dec#define OP_CC#define OP1#include "test-i386.h"#define OP neg#define OP_CC#define OP1#include "test-i386.h"#define OP not#define OP_CC#define OP1#include "test-i386.h"#undef CC_MASK#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)#define OP shl#include "test-i386-shift.h"#define OP shr#include "test-i386-shift.h"#define OP sar#include "test-i386-shift.h"#define OP rol#include "test-i386-shift.h"#define OP ror#include "test-i386-shift.h"#define OP rcr#define OP_CC#include "test-i386-shift.h"#define OP rcl#define OP_CC#include "test-i386-shift.h"#define OP shld#define OP_SHIFTD#define OP_NOBYTE#include "test-i386-shift.h"#define OP shrd#define OP_SHIFTD#define OP_NOBYTE#include "test-i386-shift.h"/* XXX: should be more precise ? */#undef CC_MASK#define CC_MASK (CC_C)#define OP bt#define OP_NOBYTE#include "test-i386-shift.h"#define OP bts#define OP_NOBYTE#include "test-i386-shift.h"#define OP btr#define OP_NOBYTE#include "test-i386-shift.h"#define OP btc#define OP_NOBYTE#include "test-i386-shift.h"/* lea test (modrm support) */#define TEST_LEAQ(STR)\{\ asm("lea " STR ", %0"\ : "=r" (res)\ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ printf("lea %s = " FMTLX "\n", STR, res);\}#define TEST_LEA(STR)\{\ asm("lea " STR ", %0"\ : "=r" (res)\ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ printf("lea %s = " FMTLX "\n", STR, res);\}#define TEST_LEA16(STR)\{\ asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\ : "=wq" (res)\ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ printf("lea %s = %08lx\n", STR, res);\}void test_lea(void){ long eax, ebx, ecx, edx, esi, edi, res; eax = i2l(0x0001); ebx = i2l(0x0002); ecx = i2l(0x0004); edx = i2l(0x0008); esi = i2l(0x0010); edi = i2l(0x0020); TEST_LEA("0x4000"); TEST_LEA("(%%eax)"); TEST_LEA("(%%ebx)"); TEST_LEA("(%%ecx)"); TEST_LEA("(%%edx)"); TEST_LEA("(%%esi)"); TEST_LEA("(%%edi)"); TEST_LEA("0x40(%%eax)"); TEST_LEA("0x40(%%ebx)"); TEST_LEA("0x40(%%ecx)"); TEST_LEA("0x40(%%edx)"); TEST_LEA("0x40(%%esi)"); TEST_LEA("0x40(%%edi)"); TEST_LEA("0x4000(%%eax)"); TEST_LEA("0x4000(%%ebx)"); TEST_LEA("0x4000(%%ecx)"); TEST_LEA("0x4000(%%edx)"); TEST_LEA("0x4000(%%esi)"); TEST_LEA("0x4000(%%edi)"); TEST_LEA("(%%eax, %%ecx)"); TEST_LEA("(%%ebx, %%edx)"); TEST_LEA("(%%ecx, %%ecx)"); TEST_LEA("(%%edx, %%ecx)"); TEST_LEA("(%%esi, %%ecx)"); TEST_LEA("(%%edi, %%ecx)"); TEST_LEA("0x40(%%eax, %%ecx)"); TEST_LEA("0x4000(%%ebx, %%edx)"); TEST_LEA("(%%ecx, %%ecx, 2)"); TEST_LEA("(%%edx, %%ecx, 4)"); TEST_LEA("(%%esi, %%ecx, 8)"); TEST_LEA("(,%%eax, 2)"); TEST_LEA("(,%%ebx, 4)"); TEST_LEA("(,%%ecx, 8)"); TEST_LEA("0x40(,%%eax, 2)"); TEST_LEA("0x40(,%%ebx, 4)"); TEST_LEA("0x40(,%%ecx, 8)"); TEST_LEA("-10(%%ecx, %%ecx, 2)"); TEST_LEA("-10(%%edx, %%ecx, 4)"); TEST_LEA("-10(%%esi, %%ecx, 8)"); TEST_LEA("0x4000(%%ecx, %%ecx, 2)"); TEST_LEA("0x4000(%%edx, %%ecx, 4)"); TEST_LEA("0x4000(%%esi, %%ecx, 8)");#if defined(__x86_64__) TEST_LEAQ("0x4000"); TEST_LEAQ("0x4000(%%rip)"); TEST_LEAQ("(%%rax)"); TEST_LEAQ("(%%rbx)"); TEST_LEAQ("(%%rcx)"); TEST_LEAQ("(%%rdx)"); TEST_LEAQ("(%%rsi)"); TEST_LEAQ("(%%rdi)"); TEST_LEAQ("0x40(%%rax)"); TEST_LEAQ("0x40(%%rbx)"); TEST_LEAQ("0x40(%%rcx)"); TEST_LEAQ("0x40(%%rdx)"); TEST_LEAQ("0x40(%%rsi)"); TEST_LEAQ("0x40(%%rdi)"); TEST_LEAQ("0x4000(%%rax)"); TEST_LEAQ("0x4000(%%rbx)"); TEST_LEAQ("0x4000(%%rcx)"); TEST_LEAQ("0x4000(%%rdx)"); TEST_LEAQ("0x4000(%%rsi)"); TEST_LEAQ("0x4000(%%rdi)"); TEST_LEAQ("(%%rax, %%rcx)"); TEST_LEAQ("(%%rbx, %%rdx)"); TEST_LEAQ("(%%rcx, %%rcx)"); TEST_LEAQ("(%%rdx, %%rcx)"); TEST_LEAQ("(%%rsi, %%rcx)"); TEST_LEAQ("(%%rdi, %%rcx)"); TEST_LEAQ("0x40(%%rax, %%rcx)"); TEST_LEAQ("0x4000(%%rbx, %%rdx)"); TEST_LEAQ("(%%rcx, %%rcx, 2)"); TEST_LEAQ("(%%rdx, %%rcx, 4)"); TEST_LEAQ("(%%rsi, %%rcx, 8)"); TEST_LEAQ("(,%%rax, 2)"); TEST_LEAQ("(,%%rbx, 4)"); TEST_LEAQ("(,%%rcx, 8)"); TEST_LEAQ("0x40(,%%rax, 2)"); TEST_LEAQ("0x40(,%%rbx, 4)"); TEST_LEAQ("0x40(,%%rcx, 8)"); TEST_LEAQ("-10(%%rcx, %%rcx, 2)"); TEST_LEAQ("-10(%%rdx, %%rcx, 4)"); TEST_LEAQ("-10(%%rsi, %%rcx, 8)"); TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)"); TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)"); TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");#else /* limited 16 bit addressing test */ TEST_LEA16("0x4000"); TEST_LEA16("(%%bx)"); TEST_LEA16("(%%si)"); TEST_LEA16("(%%di)"); TEST_LEA16("0x40(%%bx)"); TEST_LEA16("0x40(%%si)"); TEST_LEA16("0x40(%%di)"); TEST_LEA16("0x4000(%%bx)"); TEST_LEA16("0x4000(%%si)"); TEST_LEA16("(%%bx,%%si)"); TEST_LEA16("(%%bx,%%di)"); TEST_LEA16("0x40(%%bx,%%si)"); TEST_LEA16("0x40(%%bx,%%di)"); TEST_LEA16("0x4000(%%bx,%%si)"); TEST_LEA16("0x4000(%%bx,%%di)");#endif}#define TEST_JCC(JCC, v1, v2)\{\ int res;\ asm("movl $1, %0\n\t"\ "cmpl %2, %1\n\t"\ "j" JCC " 1f\n\t"\ "movl $0, %0\n\t"\ "1:\n\t"\ : "=r" (res)\ : "r" (v1), "r" (v2));\ printf("%-10s %d\n", "j" JCC, res);\\ asm("movl $0, %0\n\t"\ "cmpl %2, %1\n\t"\ "set" JCC " %b0\n\t"\ : "=r" (res)\ : "r" (v1), "r" (v2));\ printf("%-10s %d\n", "set" JCC, res);\ if (TEST_CMOV) {\ long val = i2l(1);\ long res = i2l(0x12345678);\X86_64_ONLY(\ asm("cmpl %2, %1\n\t"\ "cmov" JCC "q %3, %0\n\t"\ : "=r" (res)\ : "r" (v1), "r" (v2), "m" (val), "0" (res));\ printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\ asm("cmpl %2, %1\n\t"\ "cmov" JCC "l %k3, %k0\n\t"\ : "=r" (res)\ : "r" (v1), "r" (v2), "m" (val), "0" (res));\ printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\ asm("cmpl %2, %1\n\t"\ "cmov" JCC "w %w3, %w0\n\t"\ : "=r" (res)\ : "r" (v1), "r" (v2), "r" (1), "0" (res));\ printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\ } \}/* various jump tests */void test_jcc(void){ TEST_JCC("ne", 1, 1); TEST_JCC("ne", 1, 0); TEST_JCC("e", 1, 1); TEST_JCC("e", 1, 0); TEST_JCC("l", 1, 1); TEST_JCC("l", 1, 0); TEST_JCC("l", 1, -1); TEST_JCC("le", 1, 1); TEST_JCC("le", 1, 0); TEST_JCC("le", 1, -1); TEST_JCC("ge", 1, 1); TEST_JCC("ge", 1, 0); TEST_JCC("ge", -1, 1); TEST_JCC("g", 1, 1); TEST_JCC("g", 1, 0); TEST_JCC("g", 1, -1); TEST_JCC("b", 1, 1); TEST_JCC("b", 1, 0); TEST_JCC("b", 1, -1); TEST_JCC("be", 1, 1); TEST_JCC("be", 1, 0); TEST_JCC("be", 1, -1); TEST_JCC("ae", 1, 1); TEST_JCC("ae", 1, 0); TEST_JCC("ae", 1, -1); TEST_JCC("a", 1, 1); TEST_JCC("a", 1, 0); TEST_JCC("a", 1, -1); TEST_JCC("p", 1, 1); TEST_JCC("p", 1, 0); TEST_JCC("np", 1, 1); TEST_JCC("np", 1, 0); TEST_JCC("o", 0x7fffffff, 0); TEST_JCC("o", 0x7fffffff, -1); TEST_JCC("no", 0x7fffffff, 0); TEST_JCC("no", 0x7fffffff, -1); TEST_JCC("s", 0, 1); TEST_JCC("s", 0, -1); TEST_JCC("s", 0, 0); TEST_JCC("ns", 0, 1); TEST_JCC("ns", 0, -1); TEST_JCC("ns", 0, 0);}#undef CC_MASK#ifdef TEST_P4_FLAGS#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)#else#define CC_MASK (CC_O | CC_C)#endif#define OP mul#include "test-i386-muldiv.h"#define OP imul#include "test-i386-muldiv.h"void test_imulw2(long op0, long op1) { long res, s1, s0, flags; s0 = op0; s1 = op1; res = s0; flags = 0; asm volatile ("push %4\n\t" "popf\n\t" "imulw %w2, %w0\n\t" "pushf\n\t" "pop %1\n\t" : "=q" (res), "=g" (flags) : "q" (s1), "0" (res), "1" (flags)); printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n", "imulw", s0, s1, res, flags & CC_MASK);}void test_imull2(long op0, long op1) { long res, s1, s0, flags; s0 = op0; s1 = op1; res = s0; flags = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -