Merge branch 'eflags3' of git://github.com/rth7680/qemu

* 'eflags3' of git://github.com/rth7680/qemu: (61 commits)
  target-i386: Use movcond to implement shiftd.
  target-i386: Discard CC_OP computation in set_cc_op also
  target-i386: Use movcond to implement rotate flags.
  target-i386: Use movcond to implement shift flags.
  target-i386: Add CC_OP_CLR
  target-i386: Implement tzcnt and fix lzcnt
  target-i386: Use clz/ctz for bsf/bsr helpers
  target-i386: Implement ADX extension
  target-i386: Implement RORX
  target-i386: Implement SHLX, SARX, SHRX
  target-i386: Implement PDEP, PEXT
  target-i386: Implement MULX
  target-i386: Implement BZHI
  target-i386: Implement BLSR, BLSMSK, BLSI
  target-i386: Implement BEXTR
  target-i386: Implement ANDN
  target-i386: Implement MOVBE
  target-i386: Decode the VEX prefixes
  target-i386: Tidy prefix parsing
  target-i386: Use CC_SRC2 for ADC and SBB
  ...
This commit is contained in:
Blue Swirl 2013-02-23 17:21:41 +00:00
commit f708e736d0
10 changed files with 1890 additions and 1469 deletions

View File

@ -75,243 +75,247 @@ const uint8_t parity_table[256] = {
#endif
static int compute_all_eflags(CPUX86State *env)
static target_ulong compute_all_adcx(target_ulong dst, target_ulong src1,
target_ulong src2)
{
return CC_SRC;
return (src1 & ~CC_C) | (dst * CC_C);
}
static int compute_c_eflags(CPUX86State *env)
static target_ulong compute_all_adox(target_ulong dst, target_ulong src1,
target_ulong src2)
{
return CC_SRC & CC_C;
return (src1 & ~CC_O) | (src2 * CC_O);
}
uint32_t helper_cc_compute_all(CPUX86State *env, int op)
static target_ulong compute_all_adcox(target_ulong dst, target_ulong src1,
target_ulong src2)
{
return (src1 & ~(CC_C | CC_O)) | (dst * CC_C) | (src2 * CC_O);
}
target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1,
target_ulong src2, int op)
{
switch (op) {
default: /* should never happen */
return 0;
case CC_OP_EFLAGS:
return compute_all_eflags(env);
return src1;
case CC_OP_CLR:
return CC_Z;
case CC_OP_MULB:
return compute_all_mulb(env);
return compute_all_mulb(dst, src1);
case CC_OP_MULW:
return compute_all_mulw(env);
return compute_all_mulw(dst, src1);
case CC_OP_MULL:
return compute_all_mull(env);
return compute_all_mull(dst, src1);
case CC_OP_ADDB:
return compute_all_addb(env);
return compute_all_addb(dst, src1);
case CC_OP_ADDW:
return compute_all_addw(env);
return compute_all_addw(dst, src1);
case CC_OP_ADDL:
return compute_all_addl(env);
return compute_all_addl(dst, src1);
case CC_OP_ADCB:
return compute_all_adcb(env);
return compute_all_adcb(dst, src1, src2);
case CC_OP_ADCW:
return compute_all_adcw(env);
return compute_all_adcw(dst, src1, src2);
case CC_OP_ADCL:
return compute_all_adcl(env);
return compute_all_adcl(dst, src1, src2);
case CC_OP_SUBB:
return compute_all_subb(env);
return compute_all_subb(dst, src1);
case CC_OP_SUBW:
return compute_all_subw(env);
return compute_all_subw(dst, src1);
case CC_OP_SUBL:
return compute_all_subl(env);
return compute_all_subl(dst, src1);
case CC_OP_SBBB:
return compute_all_sbbb(env);
return compute_all_sbbb(dst, src1, src2);
case CC_OP_SBBW:
return compute_all_sbbw(env);
return compute_all_sbbw(dst, src1, src2);
case CC_OP_SBBL:
return compute_all_sbbl(env);
return compute_all_sbbl(dst, src1, src2);
case CC_OP_LOGICB:
return compute_all_logicb(env);
return compute_all_logicb(dst, src1);
case CC_OP_LOGICW:
return compute_all_logicw(env);
return compute_all_logicw(dst, src1);
case CC_OP_LOGICL:
return compute_all_logicl(env);
return compute_all_logicl(dst, src1);
case CC_OP_INCB:
return compute_all_incb(env);
return compute_all_incb(dst, src1);
case CC_OP_INCW:
return compute_all_incw(env);
return compute_all_incw(dst, src1);
case CC_OP_INCL:
return compute_all_incl(env);
return compute_all_incl(dst, src1);
case CC_OP_DECB:
return compute_all_decb(env);
return compute_all_decb(dst, src1);
case CC_OP_DECW:
return compute_all_decw(env);
return compute_all_decw(dst, src1);
case CC_OP_DECL:
return compute_all_decl(env);
return compute_all_decl(dst, src1);
case CC_OP_SHLB:
return compute_all_shlb(env);
return compute_all_shlb(dst, src1);
case CC_OP_SHLW:
return compute_all_shlw(env);
return compute_all_shlw(dst, src1);
case CC_OP_SHLL:
return compute_all_shll(env);
return compute_all_shll(dst, src1);
case CC_OP_SARB:
return compute_all_sarb(env);
return compute_all_sarb(dst, src1);
case CC_OP_SARW:
return compute_all_sarw(env);
return compute_all_sarw(dst, src1);
case CC_OP_SARL:
return compute_all_sarl(env);
return compute_all_sarl(dst, src1);
case CC_OP_BMILGB:
return compute_all_bmilgb(dst, src1);
case CC_OP_BMILGW:
return compute_all_bmilgw(dst, src1);
case CC_OP_BMILGL:
return compute_all_bmilgl(dst, src1);
case CC_OP_ADCX:
return compute_all_adcx(dst, src1, src2);
case CC_OP_ADOX:
return compute_all_adox(dst, src1, src2);
case CC_OP_ADCOX:
return compute_all_adcox(dst, src1, src2);
#ifdef TARGET_X86_64
case CC_OP_MULQ:
return compute_all_mulq(env);
return compute_all_mulq(dst, src1);
case CC_OP_ADDQ:
return compute_all_addq(env);
return compute_all_addq(dst, src1);
case CC_OP_ADCQ:
return compute_all_adcq(env);
return compute_all_adcq(dst, src1, src2);
case CC_OP_SUBQ:
return compute_all_subq(env);
return compute_all_subq(dst, src1);
case CC_OP_SBBQ:
return compute_all_sbbq(env);
return compute_all_sbbq(dst, src1, src2);
case CC_OP_LOGICQ:
return compute_all_logicq(env);
return compute_all_logicq(dst, src1);
case CC_OP_INCQ:
return compute_all_incq(env);
return compute_all_incq(dst, src1);
case CC_OP_DECQ:
return compute_all_decq(env);
return compute_all_decq(dst, src1);
case CC_OP_SHLQ:
return compute_all_shlq(env);
return compute_all_shlq(dst, src1);
case CC_OP_SARQ:
return compute_all_sarq(env);
return compute_all_sarq(dst, src1);
case CC_OP_BMILGQ:
return compute_all_bmilgq(dst, src1);
#endif
}
}
uint32_t cpu_cc_compute_all(CPUX86State *env, int op)
{
return helper_cc_compute_all(env, op);
return helper_cc_compute_all(CC_DST, CC_SRC, CC_SRC2, op);
}
uint32_t helper_cc_compute_c(CPUX86State *env, int op)
target_ulong helper_cc_compute_c(target_ulong dst, target_ulong src1,
target_ulong src2, int op)
{
switch (op) {
default: /* should never happen */
case CC_OP_LOGICB:
case CC_OP_LOGICW:
case CC_OP_LOGICL:
case CC_OP_LOGICQ:
case CC_OP_CLR:
return 0;
case CC_OP_EFLAGS:
return compute_c_eflags(env);
case CC_OP_MULB:
return compute_c_mull(env);
case CC_OP_MULW:
return compute_c_mull(env);
case CC_OP_MULL:
return compute_c_mull(env);
case CC_OP_ADDB:
return compute_c_addb(env);
case CC_OP_ADDW:
return compute_c_addw(env);
case CC_OP_ADDL:
return compute_c_addl(env);
case CC_OP_ADCB:
return compute_c_adcb(env);
case CC_OP_ADCW:
return compute_c_adcw(env);
case CC_OP_ADCL:
return compute_c_adcl(env);
case CC_OP_SUBB:
return compute_c_subb(env);
case CC_OP_SUBW:
return compute_c_subw(env);
case CC_OP_SUBL:
return compute_c_subl(env);
case CC_OP_SBBB:
return compute_c_sbbb(env);
case CC_OP_SBBW:
return compute_c_sbbw(env);
case CC_OP_SBBL:
return compute_c_sbbl(env);
case CC_OP_LOGICB:
return compute_c_logicb();
case CC_OP_LOGICW:
return compute_c_logicw();
case CC_OP_LOGICL:
return compute_c_logicl();
case CC_OP_SARB:
case CC_OP_SARW:
case CC_OP_SARL:
case CC_OP_SARQ:
case CC_OP_ADOX:
return src1 & 1;
case CC_OP_INCB:
return compute_c_incl(env);
case CC_OP_INCW:
return compute_c_incl(env);
case CC_OP_INCL:
return compute_c_incl(env);
case CC_OP_INCQ:
case CC_OP_DECB:
return compute_c_incl(env);
case CC_OP_DECW:
return compute_c_incl(env);
case CC_OP_DECL:
return compute_c_incl(env);
case CC_OP_DECQ:
return src1;
case CC_OP_MULB:
case CC_OP_MULW:
case CC_OP_MULL:
case CC_OP_MULQ:
return src1 != 0;
case CC_OP_ADCX:
case CC_OP_ADCOX:
return dst;
case CC_OP_ADDB:
return compute_c_addb(dst, src1);
case CC_OP_ADDW:
return compute_c_addw(dst, src1);
case CC_OP_ADDL:
return compute_c_addl(dst, src1);
case CC_OP_ADCB:
return compute_c_adcb(dst, src1, src2);
case CC_OP_ADCW:
return compute_c_adcw(dst, src1, src2);
case CC_OP_ADCL:
return compute_c_adcl(dst, src1, src2);
case CC_OP_SUBB:
return compute_c_subb(dst, src1);
case CC_OP_SUBW:
return compute_c_subw(dst, src1);
case CC_OP_SUBL:
return compute_c_subl(dst, src1);
case CC_OP_SBBB:
return compute_c_sbbb(dst, src1, src2);
case CC_OP_SBBW:
return compute_c_sbbw(dst, src1, src2);
case CC_OP_SBBL:
return compute_c_sbbl(dst, src1, src2);
case CC_OP_SHLB:
return compute_c_shlb(env);
return compute_c_shlb(dst, src1);
case CC_OP_SHLW:
return compute_c_shlw(env);
return compute_c_shlw(dst, src1);
case CC_OP_SHLL:
return compute_c_shll(env);
return compute_c_shll(dst, src1);
case CC_OP_SARB:
return compute_c_sarl(env);
case CC_OP_SARW:
return compute_c_sarl(env);
case CC_OP_SARL:
return compute_c_sarl(env);
case CC_OP_BMILGB:
return compute_c_bmilgb(dst, src1);
case CC_OP_BMILGW:
return compute_c_bmilgw(dst, src1);
case CC_OP_BMILGL:
return compute_c_bmilgl(dst, src1);
#ifdef TARGET_X86_64
case CC_OP_MULQ:
return compute_c_mull(env);
case CC_OP_ADDQ:
return compute_c_addq(env);
return compute_c_addq(dst, src1);
case CC_OP_ADCQ:
return compute_c_adcq(env);
return compute_c_adcq(dst, src1, src2);
case CC_OP_SUBQ:
return compute_c_subq(env);
return compute_c_subq(dst, src1);
case CC_OP_SBBQ:
return compute_c_sbbq(env);
case CC_OP_LOGICQ:
return compute_c_logicq();
case CC_OP_INCQ:
return compute_c_incl(env);
case CC_OP_DECQ:
return compute_c_incl(env);
return compute_c_sbbq(dst, src1, src2);
case CC_OP_SHLQ:
return compute_c_shlq(env);
case CC_OP_SARQ:
return compute_c_sarl(env);
return compute_c_shlq(dst, src1);
case CC_OP_BMILGQ:
return compute_c_bmilgq(dst, src1);
#endif
}
}
@ -326,7 +330,7 @@ target_ulong helper_read_eflags(CPUX86State *env)
{
uint32_t eflags;
eflags = helper_cc_compute_all(env, CC_OP);
eflags = cpu_cc_compute_all(env, CC_OP);
eflags |= (DF & DF_MASK);
eflags |= env->eflags & ~(VM_MASK | RF_MASK);
return eflags;

View File

@ -18,258 +18,223 @@
*/
#define DATA_BITS (1 << (3 + SHIFT))
#define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1))
#if DATA_BITS == 8
#define SUFFIX b
#define DATA_TYPE uint8_t
#define DATA_MASK 0xff
#elif DATA_BITS == 16
#define SUFFIX w
#define DATA_TYPE uint16_t
#define DATA_MASK 0xffff
#elif DATA_BITS == 32
#define SUFFIX l
#define DATA_TYPE uint32_t
#define DATA_MASK 0xffffffff
#elif DATA_BITS == 64
#define SUFFIX q
#define DATA_TYPE uint64_t
#define DATA_MASK 0xffffffffffffffffULL
#else
#error unhandled operand size
#endif
#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
/* dynamic flags computation */
static int glue(compute_all_add, SUFFIX)(CPUX86State *env)
static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
target_long src1, src2;
DATA_TYPE src2 = dst - src1;
src1 = CC_SRC;
src2 = CC_DST - CC_SRC;
cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
pf = parity_table[(uint8_t)CC_DST];
af = (CC_DST ^ src1 ^ src2) & 0x10;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
cf = dst < src1;
pf = parity_table[(uint8_t)dst];
af = (dst ^ src1 ^ src2) & CC_A;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_add, SUFFIX)(CPUX86State *env)
static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf;
target_long src1;
src1 = CC_SRC;
cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
return cf;
return dst < src1;
}
static int glue(compute_all_adc, SUFFIX)(CPUX86State *env)
static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
DATA_TYPE src3)
{
int cf, pf, af, zf, sf, of;
target_long src1, src2;
DATA_TYPE src2 = dst - src1 - src3;
src1 = CC_SRC;
src2 = CC_DST - CC_SRC - 1;
cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
pf = parity_table[(uint8_t)CC_DST];
af = (CC_DST ^ src1 ^ src2) & 0x10;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
cf = (src3 ? dst <= src1 : dst < src1);
pf = parity_table[(uint8_t)dst];
af = (dst ^ src1 ^ src2) & 0x10;
zf = (dst == 0) << 6;
sf = lshift(dst, 8 - DATA_BITS) & 0x80;
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_adc, SUFFIX)(CPUX86State *env)
static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
DATA_TYPE src3)
{
int cf;
target_long src1;
src1 = CC_SRC;
cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
return cf;
return src3 ? dst <= src1 : dst < src1;
}
static int glue(compute_all_sub, SUFFIX)(CPUX86State *env)
static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
{
int cf, pf, af, zf, sf, of;
target_long src1, src2;
DATA_TYPE src1 = dst + src2;
src1 = CC_DST + CC_SRC;
src2 = CC_SRC;
cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
pf = parity_table[(uint8_t)CC_DST];
af = (CC_DST ^ src1 ^ src2) & 0x10;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
cf = src1 < src2;
pf = parity_table[(uint8_t)dst];
af = (dst ^ src1 ^ src2) & CC_A;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_sub, SUFFIX)(CPUX86State *env)
static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
{
int cf;
target_long src1, src2;
DATA_TYPE src1 = dst + src2;
src1 = CC_DST + CC_SRC;
src2 = CC_SRC;
cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
return cf;
return src1 < src2;
}
static int glue(compute_all_sbb, SUFFIX)(CPUX86State *env)
static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
DATA_TYPE src3)
{
int cf, pf, af, zf, sf, of;
target_long src1, src2;
DATA_TYPE src1 = dst + src2 + src3;
src1 = CC_DST + CC_SRC + 1;
src2 = CC_SRC;
cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
pf = parity_table[(uint8_t)CC_DST];
af = (CC_DST ^ src1 ^ src2) & 0x10;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
cf = (src3 ? src1 <= src2 : src1 < src2);
pf = parity_table[(uint8_t)dst];
af = (dst ^ src1 ^ src2) & 0x10;
zf = (dst == 0) << 6;
sf = lshift(dst, 8 - DATA_BITS) & 0x80;
of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_sbb, SUFFIX)(CPUX86State *env)
static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
DATA_TYPE src3)
{
int cf;
target_long src1, src2;
DATA_TYPE src1 = dst + src2 + src3;
src1 = CC_DST + CC_SRC + 1;
src2 = CC_SRC;
cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
return cf;
return (src3 ? src1 <= src2 : src1 < src2);
}
static int glue(compute_all_logic, SUFFIX)(CPUX86State *env)
static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
cf = 0;
pf = parity_table[(uint8_t)CC_DST];
pf = parity_table[(uint8_t)dst];
af = 0;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = 0;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_logic, SUFFIX)(void)
{
return 0;
}
static int glue(compute_all_inc, SUFFIX)(CPUX86State *env)
static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
target_long src1, src2;
DATA_TYPE src2;
src1 = CC_DST - 1;
cf = src1;
src1 = dst - 1;
src2 = 1;
cf = CC_SRC;
pf = parity_table[(uint8_t)CC_DST];
af = (CC_DST ^ src1 ^ src2) & 0x10;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
pf = parity_table[(uint8_t)dst];
af = (dst ^ src1 ^ src2) & CC_A;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = (dst == SIGN_MASK) * CC_O;
return cf | pf | af | zf | sf | of;
}
#if DATA_BITS == 32
static int glue(compute_c_inc, SUFFIX)(CPUX86State *env)
{
return CC_SRC;
}
#endif
static int glue(compute_all_dec, SUFFIX)(CPUX86State *env)
static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
target_long src1, src2;
DATA_TYPE src2;
src1 = CC_DST + 1;
cf = src1;
src1 = dst + 1;
src2 = 1;
cf = CC_SRC;
pf = parity_table[(uint8_t)CC_DST];
af = (CC_DST ^ src1 ^ src2) & 0x10;
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11;
pf = parity_table[(uint8_t)dst];
af = (dst ^ src1 ^ src2) & CC_A;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = (dst == SIGN_MASK - 1) * CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_all_shl, SUFFIX)(CPUX86State *env)
static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
pf = parity_table[(uint8_t)CC_DST];
cf = (src1 >> (DATA_BITS - 1)) & CC_C;
pf = parity_table[(uint8_t)dst];
af = 0; /* undefined */
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
/* of is defined if shift count == 1 */
of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
/* of is defined iff shift count == 1 */
of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_shl, SUFFIX)(CPUX86State *env)
static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
return (src1 >> (DATA_BITS - 1)) & CC_C;
}
#if DATA_BITS == 32
static int glue(compute_c_sar, SUFFIX)(CPUX86State *env)
{
return CC_SRC & 1;
}
#endif
static int glue(compute_all_sar, SUFFIX)(CPUX86State *env)
static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
cf = CC_SRC & 1;
pf = parity_table[(uint8_t)CC_DST];
cf = src1 & 1;
pf = parity_table[(uint8_t)dst];
af = 0; /* undefined */
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
/* of is defined if shift count == 1 */
of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
/* of is defined iff shift count == 1 */
of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
return cf | pf | af | zf | sf | of;
}
#if DATA_BITS == 32
static int glue(compute_c_mul, SUFFIX)(CPUX86State *env)
{
int cf;
cf = (CC_SRC != 0);
return cf;
}
#endif
/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
CF are modified and it is slower to do that. */
static int glue(compute_all_mul, SUFFIX)(CPUX86State *env)
CF are modified and it is slower to do that. Note as well that we
don't truncate SRC1 for computing carry to DATA_TYPE. */
static int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1)
{
int cf, pf, af, zf, sf, of;
cf = (CC_SRC != 0);
pf = parity_table[(uint8_t)CC_DST];
cf = (src1 != 0);
pf = parity_table[(uint8_t)dst];
af = 0; /* undefined */
zf = ((DATA_TYPE)CC_DST == 0) << 6;
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
of = cf << 11;
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = cf * CC_O;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
int cf, pf, af, zf, sf, of;
cf = (src1 == 0);
pf = 0; /* undefined */
af = 0; /* undefined */
zf = (dst == 0) * CC_Z;
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
of = 0;
return cf | pf | af | zf | sf | of;
}
static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
{
return src1 == 0;
}
#undef DATA_BITS
#undef SIGN_MASK
#undef DATA_TYPE

View File

@ -389,10 +389,15 @@ typedef struct x86_def_t {
CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
CPUID_EXT_HYPERVISOR)
CPUID_EXT_MOVBE | CPUID_EXT_HYPERVISOR)
/* missing:
CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */
CPUID_EXT_PCLMULQDQ, CPUID_EXT_DTES64, CPUID_EXT_DSCPL,
CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2,
CPUID_EXT_CID, CPUID_EXT_FMA, CPUID_EXT_XTPR, CPUID_EXT_PDCM,
CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_SSE41, CPUID_EXT_SSE42,
CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES,
CPUID_EXT_XSAVE, CPUID_EXT_OSXSAVE, CPUID_EXT_AVX,
CPUID_EXT_F16C, CPUID_EXT_RDRAND */
#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
@ -401,7 +406,12 @@ typedef struct x86_def_t {
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
#define TCG_SVM_FEATURES 0
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP)
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP \
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
/* missing:
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
CPUID_7_0_EBX_RDSEED */
/* built-in CPU model definitions
*/

View File

@ -582,7 +582,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPU_INTERRUPT_TPR CPU_INTERRUPT_TGT_INT_3
enum {
typedef enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitly computed, CC_SRC = flags */
@ -636,8 +636,19 @@ enum {
CC_OP_SARL,
CC_OP_SARQ,
CC_OP_BMILGB, /* Z,S via CC_DST, C = SRC==0; O=0; P,A undefined */
CC_OP_BMILGW,
CC_OP_BMILGL,
CC_OP_BMILGQ,
CC_OP_ADCX, /* CC_DST = C, CC_SRC = rest. */
CC_OP_ADOX, /* CC_DST = O, CC_SRC = rest. */
CC_OP_ADCOX, /* CC_DST = C, CC_SRC2 = O, CC_SRC = rest. */
CC_OP_CLR, /* Z set, all other flags clear. */
CC_OP_NB,
};
} CCOp;
typedef struct SegmentCache {
uint32_t selector;
@ -725,8 +736,9 @@ typedef struct CPUX86State {
stored elsewhere */
/* emulator internal eflags handling */
target_ulong cc_src;
target_ulong cc_dst;
target_ulong cc_src;
target_ulong cc_src2;
uint32_t cc_op;
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
uint32_t hflags; /* TB flags, see HF_xxx constants. These flags
@ -764,7 +776,6 @@ typedef struct CPUX86State {
XMMReg xmm_regs[CPU_NB_REGS];
XMMReg xmm_t0;
MMXReg mmx_t0;
target_ulong cc_tmp; /* temporary for rcr/rcl */
/* sysenter registers */
uint32_t sysenter_cs;
@ -1117,9 +1128,10 @@ static inline int cpu_mmu_index (CPUX86State *env)
#define EIP (env->eip)
#define DF (env->df)
#define CC_SRC (env->cc_src)
#define CC_DST (env->cc_dst)
#define CC_OP (env->cc_op)
#define CC_DST (env->cc_dst)
#define CC_SRC (env->cc_src)
#define CC_SRC2 (env->cc_src2)
#define CC_OP (env->cc_op)
/* n must be a constant to be efficient */
static inline target_long lshift(target_long x, int n)

View File

@ -55,7 +55,7 @@ int cpu_x86_support_mca_broadcast(CPUX86State *env)
/***********************************************************/
/* x86 debug */
static const char *cc_op_str[] = {
static const char *cc_op_str[CC_OP_NB] = {
"DYNAMIC",
"EFLAGS",
@ -108,6 +108,17 @@ static const char *cc_op_str[] = {
"SARW",
"SARL",
"SARQ",
"BMILGB",
"BMILGW",
"BMILGL",
"BMILGQ",
"ADCX",
"ADOX",
"ADCOX",
"CLR",
};
static void

View File

@ -1,7 +1,7 @@
#include "exec/def-helper.h"
DEF_HELPER_FLAGS_2(cc_compute_all, TCG_CALL_NO_SE, i32, env, int)
DEF_HELPER_FLAGS_2(cc_compute_c, TCG_CALL_NO_SE, i32, env, int)
DEF_HELPER_FLAGS_4(cc_compute_all, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)
DEF_HELPER_FLAGS_4(cc_compute_c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)
DEF_HELPER_0(lock, void)
DEF_HELPER_0(unlock, void)
@ -19,6 +19,7 @@ DEF_HELPER_2(imulq_EAX_T0, void, env, tl)
DEF_HELPER_3(imulq_T0_T1, tl, env, tl, tl)
DEF_HELPER_2(divq_EAX, void, env, tl)
DEF_HELPER_2(idivq_EAX, void, env, tl)
DEF_HELPER_FLAGS_2(umulh, TCG_CALL_NO_RWG_SE, tl, tl, tl)
#endif
DEF_HELPER_2(aam, void, env, int)
@ -193,9 +194,11 @@ DEF_HELPER_3(fsave, void, env, tl, int)
DEF_HELPER_3(frstor, void, env, tl, int)
DEF_HELPER_3(fxsave, void, env, tl, int)
DEF_HELPER_3(fxrstor, void, env, tl, int)
DEF_HELPER_1(bsf, tl, tl)
DEF_HELPER_1(bsr, tl, tl)
DEF_HELPER_2(lzcnt, tl, tl, int)
DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(ctz, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_2(pdep, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(pext, TCG_CALL_NO_RWG_SE, tl, tl, tl)
/* MMX/SSE */

View File

@ -385,6 +385,13 @@ void helper_mulq_EAX_T0(CPUX86State *env, target_ulong t0)
CC_SRC = r1;
}
target_ulong helper_umulh(target_ulong t0, target_ulong t1)
{
uint64_t h, l;
mulu64(&l, &h, t0, t1);
return h;
}
void helper_imulq_EAX_T0(CPUX86State *env, target_ulong t0)
{
uint64_t r0, r1;
@ -440,45 +447,49 @@ void helper_idivq_EAX(CPUX86State *env, target_ulong t0)
}
#endif
#if TARGET_LONG_BITS == 32
# define ctztl ctz32
# define clztl clz32
#else
# define ctztl ctz64
# define clztl clz64
#endif
/* bit operations */
target_ulong helper_bsf(target_ulong t0)
target_ulong helper_ctz(target_ulong t0)
{
int count;
target_ulong res;
res = t0;
count = 0;
while ((res & 1) == 0) {
count++;
res >>= 1;
}
return count;
return ctztl(t0);
}
target_ulong helper_lzcnt(target_ulong t0, int wordsize)
target_ulong helper_clz(target_ulong t0)
{
int count;
target_ulong res, mask;
if (wordsize > 0 && t0 == 0) {
return wordsize;
}
res = t0;
count = TARGET_LONG_BITS - 1;
mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
while ((res & mask) == 0) {
count--;
res <<= 1;
}
if (wordsize > 0) {
return wordsize - 1 - count;
}
return count;
return clztl(t0);
}
target_ulong helper_bsr(target_ulong t0)
target_ulong helper_pdep(target_ulong src, target_ulong mask)
{
return helper_lzcnt(t0, 0);
target_ulong dest = 0;
int i, o;
for (i = 0; mask != 0; i++) {
o = ctztl(mask);
mask &= mask - 1;
dest |= ((src >> i) & 1) << o;
}
return dest;
}
target_ulong helper_pext(target_ulong src, target_ulong mask)
{
target_ulong dest = 0;
int i, o;
for (o = 0; mask != 0; o++) {
i = ctztl(mask);
mask &= mask - 1;
dest |= ((src >> i) & 1) << o;
}
return dest;
}
#define SHIFT 0

View File

@ -55,7 +55,7 @@ target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0,
count = rclb_table[count];
#endif
if (count) {
eflags = helper_cc_compute_all(env, CC_OP);
eflags = env->cc_src;
t0 &= DATA_MASK;
src = t0;
res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1));
@ -63,11 +63,9 @@ target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0,
res |= t0 >> (DATA_BITS + 1 - count);
}
t0 = res;
env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
env->cc_src = (eflags & ~(CC_C | CC_O)) |
(lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
((src >> (DATA_BITS - count)) & CC_C);
} else {
env->cc_tmp = -1;
}
return t0;
}
@ -86,7 +84,7 @@ target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, target_ulong t0,
count = rclb_table[count];
#endif
if (count) {
eflags = helper_cc_compute_all(env, CC_OP);
eflags = env->cc_src;
t0 &= DATA_MASK;
src = t0;
res = (t0 >> count) |
@ -95,11 +93,9 @@ target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, target_ulong t0,
res |= t0 << (DATA_BITS + 1 - count);
}
t0 = res;
env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
env->cc_src = (eflags & ~(CC_C | CC_O)) |
(lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
((src >> (count - 1)) & CC_C);
} else {
env->cc_tmp = -1;
}
return t0;
}

File diff suppressed because it is too large Load Diff

View File

@ -209,7 +209,7 @@ static inline long i2l(long v)
#define TEST_LEA16(STR)\
{\
asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
: "=wq" (res)\
: "=r" (res)\
: "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
printf("lea %s = %08lx\n", STR, res);\
}
@ -925,7 +925,7 @@ void test_fbcd(double a)
void test_fenv(void)
{
struct QEMU_PACKED {
struct __attribute__((__packed__)) {
uint16_t fpuc;
uint16_t dummy1;
uint16_t fpus;
@ -935,7 +935,7 @@ void test_fenv(void)
uint32_t ignored[4];
long double fpregs[8];
} float_env32;
struct QEMU_PACKED {
struct __attribute__((__packed__)) {
uint16_t fpuc;
uint16_t fpus;
uint16_t fptag;
@ -1280,7 +1280,7 @@ void test_segs(void)
struct {
uint32_t offset;
uint16_t seg;
} QEMU_PACKED segoff;
} __attribute__((__packed__)) segoff;
ldt.entry_number = 1;
ldt.base_addr = (unsigned long)&seg_data1;
@ -1828,7 +1828,7 @@ void test_exceptions(void)
printf("lock nop exception:\n");
if (setjmp(jmp_env) == 0) {
/* now execute an invalid instruction */
asm volatile(".byte 0xf0, 0x90"); /* lock nop */
asm volatile(".byte 0xf0, 0x90");
}
printf("INT exception:\n");