📄 test-i386.c
字号:
asm volatile ("push %4\n\t" "popf\n\t" "imull %k2, %k0\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", "imull", s0, s1, res, flags & CC_MASK);}#if defined(__x86_64__)void test_imulq2(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" "imulq %2, %0\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", "imulq", s0, s1, res, flags & CC_MASK);}#endif#define TEST_IMUL_IM(size, rsize, op0, op1)\{\ long res, flags, s1;\ flags = 0;\ res = 0;\ s1 = op1;\ asm volatile ("push %3\n\t"\ "popf\n\t"\ "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \ "pushf\n\t"\ "pop %1\n\t"\ : "=r" (res), "=g" (flags)\ : "r" (s1), "1" (flags), "0" (res));\ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\ "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\}#undef CC_MASK#define CC_MASK (0)#define OP div#include "test-i386-muldiv.h"#define OP idiv#include "test-i386-muldiv.h"void test_mul(void){ test_imulb(0x1234561d, 4); test_imulb(3, -4); test_imulb(0x80, 0x80); test_imulb(0x10, 0x10); test_imulw(0, 0x1234001d, 45); test_imulw(0, 23, -45); test_imulw(0, 0x8000, 0x8000); test_imulw(0, 0x100, 0x100); test_imull(0, 0x1234001d, 45); test_imull(0, 23, -45); test_imull(0, 0x80000000, 0x80000000); test_imull(0, 0x10000, 0x10000); test_mulb(0x1234561d, 4); test_mulb(3, -4); test_mulb(0x80, 0x80); test_mulb(0x10, 0x10); test_mulw(0, 0x1234001d, 45); test_mulw(0, 23, -45); test_mulw(0, 0x8000, 0x8000); test_mulw(0, 0x100, 0x100); test_mull(0, 0x1234001d, 45); test_mull(0, 23, -45); test_mull(0, 0x80000000, 0x80000000); test_mull(0, 0x10000, 0x10000); test_imulw2(0x1234001d, 45); test_imulw2(23, -45); test_imulw2(0x8000, 0x8000); test_imulw2(0x100, 0x100); test_imull2(0x1234001d, 45); test_imull2(23, -45); test_imull2(0x80000000, 0x80000000); test_imull2(0x10000, 0x10000); TEST_IMUL_IM("w", "w", 45, 0x1234); TEST_IMUL_IM("w", "w", -45, 23); TEST_IMUL_IM("w", "w", 0x8000, 0x80000000); TEST_IMUL_IM("w", "w", 0x7fff, 0x1000); TEST_IMUL_IM("l", "k", 45, 0x1234); TEST_IMUL_IM("l", "k", -45, 23); TEST_IMUL_IM("l", "k", 0x8000, 0x80000000); TEST_IMUL_IM("l", "k", 0x7fff, 0x1000); test_idivb(0x12341678, 0x127e); test_idivb(0x43210123, -5); test_idivb(0x12340004, -1); test_idivw(0, 0x12345678, 12347); test_idivw(0, -23223, -45); test_idivw(0, 0x12348000, -1); test_idivw(0x12343, 0x12345678, 0x81238567); test_idivl(0, 0x12345678, 12347); test_idivl(0, -233223, -45); test_idivl(0, 0x80000000, -1); test_idivl(0x12343, 0x12345678, 0x81234567); test_divb(0x12341678, 0x127e); test_divb(0x43210123, -5); test_divb(0x12340004, -1); test_divw(0, 0x12345678, 12347); test_divw(0, -23223, -45); test_divw(0, 0x12348000, -1); test_divw(0x12343, 0x12345678, 0x81238567); test_divl(0, 0x12345678, 12347); test_divl(0, -233223, -45); test_divl(0, 0x80000000, -1); test_divl(0x12343, 0x12345678, 0x81234567);#if defined(__x86_64__) test_imulq(0, 0x1234001d1234001d, 45); test_imulq(0, 23, -45); test_imulq(0, 0x8000000000000000, 0x8000000000000000); test_imulq(0, 0x100000000, 0x100000000); test_mulq(0, 0x1234001d1234001d, 45); test_mulq(0, 23, -45); test_mulq(0, 0x8000000000000000, 0x8000000000000000); test_mulq(0, 0x100000000, 0x100000000); test_imulq2(0x1234001d1234001d, 45); test_imulq2(23, -45); test_imulq2(0x8000000000000000, 0x8000000000000000); test_imulq2(0x100000000, 0x100000000); TEST_IMUL_IM("q", "", 45, 0x12341234); TEST_IMUL_IM("q", "", -45, 23); TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000); TEST_IMUL_IM("q", "", 0x7fff, 0x10000000); test_idivq(0, 0x12345678abcdef, 12347); test_idivq(0, -233223, -45); test_idivq(0, 0x8000000000000000, -1); test_idivq(0x12343, 0x12345678, 0x81234567); test_divq(0, 0x12345678abcdef, 12347); test_divq(0, -233223, -45); test_divq(0, 0x8000000000000000, -1); test_divq(0x12343, 0x12345678, 0x81234567);#endif}#define TEST_BSX(op, size, op0)\{\ long res, val, resz;\ val = op0;\ asm("xor %1, %1\n"\ "mov $0x12345678, %0\n"\ #op " %" size "2, %" size "0 ; setz %b1" \ : "=r" (res), "=q" (resz)\ : "g" (val));\ printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\}void test_bsx(void){ TEST_BSX(bsrw, "w", 0); TEST_BSX(bsrw, "w", 0x12340128); TEST_BSX(bsfw, "w", 0); TEST_BSX(bsfw, "w", 0x12340128); TEST_BSX(bsrl, "k", 0); TEST_BSX(bsrl, "k", 0x00340128); TEST_BSX(bsfl, "k", 0); TEST_BSX(bsfl, "k", 0x00340128);#if defined(__x86_64__) TEST_BSX(bsrq, "", 0); TEST_BSX(bsrq, "", 0x003401281234); TEST_BSX(bsfq, "", 0); TEST_BSX(bsfq, "", 0x003401281234);#endif}/**********************************************/union float64u { double d; uint64_t l;};union float64u q_nan = { .l = 0xFFF8000000000000 };union float64u s_nan = { .l = 0xFFF0000000000000 };void test_fops(double a, double b){ printf("a=%f b=%f a+b=%f\n", a, b, a + b); printf("a=%f b=%f a-b=%f\n", a, b, a - b); printf("a=%f b=%f a*b=%f\n", a, b, a * b); printf("a=%f b=%f a/b=%f\n", a, b, a / b); printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b)); printf("a=%f sqrt(a)=%f\n", a, sqrt(a)); printf("a=%f sin(a)=%f\n", a, sin(a)); printf("a=%f cos(a)=%f\n", a, cos(a)); printf("a=%f tan(a)=%f\n", a, tan(a)); printf("a=%f log(a)=%f\n", a, log(a)); printf("a=%f exp(a)=%f\n", a, exp(a)); printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b)); /* just to test some op combining */ printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a))); printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a))); printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));}void fpu_clear_exceptions(void){ struct __attribute__((packed)) { uint16_t fpuc; uint16_t dummy1; uint16_t fpus; uint16_t dummy2; uint16_t fptag; uint16_t dummy3; uint32_t ignored[4]; long double fpregs[8]; } float_env32; asm volatile ("fnstenv %0\n" : : "m" (float_env32)); float_env32.fpus &= ~0x7f; asm volatile ("fldenv %0\n" : : "m" (float_env32));}/* XXX: display exception bits when supported */#define FPUS_EMASK 0x0000//#define FPUS_EMASK 0x007fvoid test_fcmp(double a, double b){ long eflags, fpus; fpu_clear_exceptions(); asm("fcom %2\n" "fstsw %%ax\n" : "=a" (fpus) : "t" (a), "u" (b)); printf("fcom(%f %f)=%04lx \n", a, b, fpus & (0x4500 | FPUS_EMASK)); fpu_clear_exceptions(); asm("fucom %2\n" "fstsw %%ax\n" : "=a" (fpus) : "t" (a), "u" (b)); printf("fucom(%f %f)=%04lx\n", a, b, fpus & (0x4500 | FPUS_EMASK)); if (TEST_FCOMI) { /* test f(u)comi instruction */ fpu_clear_exceptions(); asm("fcomi %3, %2\n" "fstsw %%ax\n" "pushf\n" "pop %0\n" : "=r" (eflags), "=a" (fpus) : "t" (a), "u" (b)); printf("fcomi(%f %f)=%04lx %02lx\n", a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); fpu_clear_exceptions(); asm("fucomi %3, %2\n" "fstsw %%ax\n" "pushf\n" "pop %0\n" : "=r" (eflags), "=a" (fpus) : "t" (a), "u" (b)); printf("fucomi(%f %f)=%04lx %02lx\n", a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); } fpu_clear_exceptions();}void test_fcvt(double a){ float fa; long double la; int16_t fpuc; int i; int64_t lla; int ia; int16_t wa; double ra; fa = a; la = a; printf("(float)%f = %f\n", a, fa); printf("(long double)%f = %Lf\n", a, la); printf("a=" FMT64X "\n", *(uint64_t *)&a); printf("la=" FMT64X " %04x\n", *(uint64_t *)&la, *(unsigned short *)((char *)(&la) + 8)); /* test all roundings */ asm volatile ("fstcw %0" : "=m" (fpuc)); for(i=0;i<4;i++) { asm volatile ("fldcw %0" : : "m" ((fpuc & ~0x0c00) | (i << 10))); asm volatile ("fist %0" : "=m" (wa) : "t" (a)); asm volatile ("fistl %0" : "=m" (ia) : "t" (a)); asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st"); asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a)); asm volatile ("fldcw %0" : : "m" (fpuc)); printf("(short)a = %d\n", wa); printf("(int)a = %d\n", ia); printf("(int64_t)a = " FMT64X "\n", lla); printf("rint(a) = %f\n", ra); }}#define TEST(N) \ asm("fld" #N : "=t" (a)); \ printf("fld" #N "= %f\n", a);void test_fconst(void){ double a; TEST(1); TEST(l2t); TEST(l2e); TEST(pi); TEST(lg2); TEST(ln2); TEST(z);}void test_fbcd(double a){ unsigned short bcd[5]; double b; asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st"); asm("fbld %1" : "=t" (b) : "m" (bcd[0])); printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);}#define TEST_ENV(env, save, restore)\{\ memset((env), 0xaa, sizeof(*(env)));\ for(i=0;i<5;i++)\ asm volatile ("fldl %0" : : "m" (dtab[i]));\ asm volatile (save " %0\n" : : "m" (*(env)));\ asm volatile (restore " %0\n": : "m" (*(env)));\ for(i=0;i<5;i++)\ asm volatile ("fstpl %0" : "=m" (rtab[i]));\ for(i=0;i<5;i++)\ printf("res[%d]=%f\n", i, rtab[i]);\ printf("fpuc=%04x fpus=%04x fptag=%04x\n",\ (env)->fpuc,\ (env)->fpus & 0xff00,\ (env)->fptag);\}void test_fenv(void){ struct __attribute__((packed)) { uint16_t fpuc; uint16_t dummy1; uint16_t fpus; uint16_t dummy2; uint16_t fptag; uint16_t dummy3; uint32_t ignored[4]; long double fpregs[8]; } float_env32; struct __attribute__((packed)) { uint16_t fpuc; uint16_t fpus; uint16_t fptag; uint16_t ignored[4]; long double fpregs[8]; } float_env16; double dtab[8]; double rtab[8]; int i; for(i=0;i<8;i++) dtab[i] = i + 1; TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); TEST_ENV(&float_env32, "fnstenv", "fldenv"); TEST_ENV(&float_env32, "fnsave", "frstor"); /* test for ffree */ for(i=0;i<5;i++) asm volatile ("fldl %0" : : "m" (dtab[i])); asm volatile("ffree %st(2)"); asm volatile ("fnstenv %0\n" : : "m" (float_env32)); asm volatile ("fninit"); printf("fptag=%04x\n", float_env32.fptag);}#define TEST_FCMOV(a, b, eflags, CC)\{\ double res;\ asm("push %3\n"\ "popf\n"\ "fcmov" CC " %2, %0\n"\ : "=t" (res)\ : "0" (a), "u" (b), "g" (eflags));\ printf("fcmov%s eflags=0x%04lx-> %f\n", \ CC, (long)eflags, res);\}void test_fcmov(void){ double a, b; long eflags, i; a = 1.0; b = 2.0; for(i = 0; i < 4; i++) { eflags = 0; if (i & 1) eflags |= CC_C; if (i & 2) eflags |= CC_Z; TEST_FCMOV(a, b, eflags, "b"); TEST_FCMOV(a, b, eflags, "e"); TEST_FCMOV(a, b, eflags, "be"); TEST_FCMOV(a, b, eflags, "nb"); TEST_FCMOV(a, b, eflags, "ne"); TEST_FCMOV(a, b, eflags, "nbe"); } TEST_FCMOV(a, b, 0, "u"); TEST_FCMOV(a, b, CC_P, "u"); TEST_FCMOV(a, b, 0, "nu"); TEST_FCMOV(a, b, CC_P, "nu");}void test_floats(void){ test_fops(2, 3); test_fops(1.4, -5); test_fcmp(2, -1); test_fcmp(2, 2); test_fcmp(2, 3); test_fcmp(2, q_nan.d); test_fcmp(q_nan.d, -1); test_fcvt(0.5); test_fcvt(-0.5); test_fcvt(1.0/7.0); test_fcvt(-1.0/9.0); test_fcvt(32768); test_fcvt(-1e20); test_fconst(); test_fbcd(1234567890123456); test_fbcd(-123451234567890); test_fenv(); if (TEST_CMOV) { test_fcmov(); }}/**********************************************/#if !defined(__x86_64__)#define TEST_BCD(op, op0, cc_in, cc_mask)\{\ int res, flags;\ res = op0;\ flags = cc_in;\ asm ("push %3\n\t"\ "popf\n\t"\ #op "\n\t"\ "pushf\n\t"\ "pop %1\n\t"\ : "=a" (res), "=g" (flags)\ : "0" (res), "1" (flags));\ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\ #op, op0, res, cc_in, flags & cc_mask);\}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -