implemented ADCX/ADOX instructions from rev013 of arch extensions published by Intel

This commit is contained in:
Stanislav Shwartsman 2012-07-12 14:51:54 +00:00
parent 82c65076cc
commit 5d66e8450e
21 changed files with 171 additions and 6 deletions

View File

@ -225,6 +225,10 @@ cpu: cpuid_limit_winnt=0
# Select MOVBE Intel(R) Atom instruction support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# ADX:
# Select ADCX/ADOX instructions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# XSAVE:
# Select XSAVE extensions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.

View File

@ -4,6 +4,8 @@ Changes after 2.5.1 release:
- Implemented EPT A/D extensions support.
Bochs is fully aligned with the latest published revision of
Intel Architecture Manual (revision 043) now.
- Implemented ADX (ADCX/ADOX) instructions support, the feature can
be enabled using .bochsrc CPUID option.
- Another 10% CPU emulation speedup with even more optimal lazy flags
handling and stack access optimizations
- Support for AMD's SVM hardware emulation in Bochs CPU, to enable

View File

@ -40,6 +40,7 @@ cpuid
sse4a
aes
movbe
adx
xsave
xsaveopt
svm

View File

@ -512,6 +512,10 @@ void bx_init_options()
"movbe", "Support for MOVBE instruction",
"Support for MOVBE instruction",
0);
new bx_param_bool_c(cpuid_param,
"adx", "Support for ADX instructions",
"Support for ADCX/ADOX instructions",
0);
new bx_param_bool_c(cpuid_param,
"aes", "Support for AES instruction set",
"Support for AES instruction set",
@ -2529,6 +2533,10 @@ static int parse_line_formatted(const char *context, int num_params, char *param
if (parse_param_bool(params[i], 6, BXPN_CPUID_MOVBE) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
}
} else if (!strncmp(params[i], "adx=", 4)) {
if (parse_param_bool(params[i], 4, BXPN_CPUID_ADX) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
}
} else if (!strncmp(params[i], "sep=", 4)) {
if (parse_param_bool(params[i], 4, BXPN_CPUID_SEP) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
@ -3511,7 +3519,7 @@ int bx_write_configuration(const char *rc, int overwrite)
SIM->get_param_enum(BXPN_CPUID_APIC)->get_selected());
#endif
#if BX_CPU_LEVEL >= 6
fprintf(fp, ", sse=%s, sse4a=%d, sep=%d, aes=%d, xsave=%d, xsaveopt=%d, movbe=%d, smep=%d",
fprintf(fp, ", sse=%s, sse4a=%d, sep=%d, aes=%d, xsave=%d, xsaveopt=%d, movbe=%d, adx=%d, smep=%d",
SIM->get_param_enum(BXPN_CPUID_SSE)->get_selected(),
SIM->get_param_bool(BXPN_CPUID_SSE4A)->get(),
SIM->get_param_bool(BXPN_CPUID_SEP)->get(),
@ -3519,6 +3527,7 @@ int bx_write_configuration(const char *rc, int overwrite)
SIM->get_param_bool(BXPN_CPUID_XSAVE)->get(),
SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get(),
SIM->get_param_bool(BXPN_CPUID_MOVBE)->get(),
SIM->get_param_bool(BXPN_CPUID_ADX)->get(),
SIM->get_param_bool(BXPN_CPUID_SMEP)->get());
#if BX_SUPPORT_AVX
fprintf(fp, ", avx=%d, avx_f16c=%d, avx_fma=%d, bmi=%d, xop=%d, tbm=%d, fma4=%d",

View File

@ -243,3 +243,31 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PDEP_GdEdBdR(bxInstruction_c *i)
}
#endif
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADCX_GdEdR(bxInstruction_c *i)
{
Bit32u op1_32 = BX_READ_32BIT_REG(i->nnn());
Bit32u op2_32 = BX_READ_32BIT_REG(i->rm());
Bit32u sum_32 = op1_32 + op2_32 + getB_CF();
BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
Bit32u carry_out = ADD_COUT_VEC(op1_32, op2_32, sum_32);
set_CF(carry_out >> 31);
BX_NEXT_INSTR(i);
}
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADOX_GdEdR(bxInstruction_c *i)
{
Bit32u op1_32 = BX_READ_32BIT_REG(i->nnn());
Bit32u op2_32 = BX_READ_32BIT_REG(i->rm());
Bit32u sum_32 = op1_32 + op2_32 + getB_OF();
BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
Bit32u overflow = GET_ADD_OVERFLOW(op1_32, op2_32, sum_32, 0x80000000);
set_OF(!!overflow);
BX_NEXT_INSTR(i);
}

View File

@ -251,3 +251,31 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PDEP_GqEqBqR(bxInstruction_c *i)
}
#endif
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADCX_GqEqR(bxInstruction_c *i)
{
Bit64u op1_64 = BX_READ_64BIT_REG(i->nnn());
Bit64u op2_64 = BX_READ_64BIT_REG(i->rm());
Bit64u sum_64 = op1_64 + op2_64 + getB_CF();
BX_WRITE_64BIT_REG(i->nnn(), sum_64);
Bit64u carry_out = ADD_COUT_VEC(op1_64, op2_64, sum_64);
set_CF(carry_out >> 63);
BX_NEXT_INSTR(i);
}
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADOX_GqEqR(bxInstruction_c *i)
{
Bit64u op1_64 = BX_READ_64BIT_REG(i->nnn());
Bit64u op2_64 = BX_READ_64BIT_REG(i->rm());
Bit64u sum_64 = op1_64 + op2_64 + getB_OF();
BX_WRITE_64BIT_REG(i->nnn(), sum_64);
Bit64u overflow = GET_ADD_OVERFLOW(op1_64, op2_64, sum_64, BX_CONST64(0x8000000000000000));
set_OF(!!overflow);
BX_NEXT_INSTR(i);
}

View File

@ -3240,6 +3240,13 @@ public: // for now...
BX_SMF BX_INSF_TYPE POPCNT_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#endif
BX_SMF BX_INSF_TYPE ADCX_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF BX_INSF_TYPE ADOX_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#if BX_SUPPORT_X86_64
BX_SMF BX_INSF_TYPE ADCX_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF BX_INSF_TYPE ADOX_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#endif
#if BX_SUPPORT_X86_64
// 64 bit extensions
BX_SMF BX_INSF_TYPE ADD_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);

View File

@ -116,6 +116,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
#define BX_ISA_XOP (BX_CONST64(1) << 37) /* XOP instruction (AMD) */
#define BX_ISA_TBM (BX_CONST64(1) << 38) /* TBM instruction (AMD) */
#define BX_ISA_SVM (BX_CONST64(1) << 39) /* SVM instruction (AMD) */
#define BX_ISA_ADX (BX_CONST64(1) << 40) /* ADCX/ADOX instruction */
// cpuid non-ISA features
#define BX_CPU_DEBUG_EXTENSIONS (1 << 0) /* Debug Extensions support */

View File

@ -955,6 +955,28 @@ static const BxOpcodeInfo_t BxOpcodeGroupOsize0f38f1[BX_SUPPORT_X86_64 + 2] = {
#endif
};
static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f6d[3] = {
/* 66 */ { 0, BX_IA_ADCX_GdEd },
/* F3 */ { 0, BX_IA_ADOX_GdEd },
/* F2 */ { 0, BX_IA_ERROR }
};
#if BX_SUPPORT_X86_64
static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f6q[3] = {
/* 66 */ { 0, BX_IA_ADCX_GqEq },
/* F3 */ { 0, BX_IA_ADOX_GqEq },
/* F2 */ { 0, BX_IA_ERROR }
};
#endif
static const BxOpcodeInfo_t BxOpcodeGroupOsize0f38f6[BX_SUPPORT_X86_64 + 2] = {
/* 16 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f38f6d },
/* 32 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f38f6d },
#if BX_SUPPORT_X86_64
/* 64 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f38f6q },
#endif
};
static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3a0f[3] = {
/* 66 */ { 0, BX_IA_PALIGNR_VdqWdqIb },
/* F3 */ { 0, BX_IA_ERROR },
@ -1211,7 +1233,7 @@ static const BxOpcodeInfo_t BxOpcode3ByteTable0f38[256] = {
/* F3 */ { 0, BX_IA_ERROR },
/* F4 */ { 0, BX_IA_ERROR },
/* F5 */ { 0, BX_IA_ERROR },
/* F6 */ { 0, BX_IA_ERROR },
/* F6 */ { BxOSizeGrp, BX_IA_ERROR, BxOpcodeGroupOsize0f38f6 },
/* F7 */ { 0, BX_IA_ERROR },
/* F8 */ { 0, BX_IA_ERROR },
/* F9 */ { 0, BX_IA_ERROR },

View File

@ -782,6 +782,17 @@ void bx_generic_cpuid_t::init_isa_extensions_bitmask(void)
}
}
static bx_bool adx_enabled = SIM->get_param_bool(BXPN_CPUID_ADX)->get();
if (adx_enabled) {
features_bitmask |= BX_ISA_ADX;
// ADX required 3-byte opcode (SSS3E support or more)
if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
BX_PANIC(("PANIC: ADX support requires SSSE3 or higher !"));
return;
}
}
#if BX_SUPPORT_X86_64
static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get();
if (x86_64_enabled) {

View File

@ -2121,3 +2121,11 @@ bx_define_opcode(BX_IA_EXTRQ_VdqUq, &BX_CPU_C::BxError, &BX_CPU_C::EXTRQ_VdqUq,
bx_define_opcode(BX_IA_INSERTQ_VdqUqIbIb, &BX_CPU_C::BxError, &BX_CPU_C::INSERTQ_VdqUqIbIb, BX_ISA_SSE4A, BX_PREPARE_SSE)
bx_define_opcode(BX_IA_INSERTQ_VdqUdq, &BX_CPU_C::BxError, &BX_CPU_C::INSERTQ_VdqUdq, BX_ISA_SSE4A, BX_PREPARE_SSE)
// SSE4A
// ADCX/ADOX
bx_define_opcode(BX_IA_ADCX_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::ADCX_GdEdR, BX_ISA_ADX, 0)
bx_define_opcode(BX_IA_ADOX_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::ADOX_GdEdR, BX_ISA_ADX, 0)
#if BX_SUPPORT_X86_64
bx_define_opcode(BX_IA_ADCX_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ADCX_GqEqR, BX_ISA_ADX, 0)
bx_define_opcode(BX_IA_ADOX_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ADOX_GqEqR, BX_ISA_ADX, 0)
#endif

View File

@ -55,6 +55,8 @@ typedef struct {
#define SUB_COUT_VEC(op1, op2, result) \
(((~(op1)) & (op2)) | ((~((op1) ^ (op2))) & (result)))
#define GET_ADD_OVERFLOW(op1, op2, result, mask) \
((((op1) ^ (result)) & ((op2) ^ (result))) & (mask))
// *******************
// OSZAPC

View File

@ -281,9 +281,6 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSSWD_VdqHdqWdqVIbR(bxInstruct
BX_NEXT_INSTR(i);
}
#define GET_ADD_OVERFLOW(op1, op2, result, mask) \
((((op1) ^ (result)) & ((op2) ^ (result))) & (mask))
BX_CPP_INLINE Bit64s add_saturate64(Bit64s a, Bit64s b)
{
Bit64s r = a + b;

View File

@ -1029,6 +1029,25 @@ static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f38f1[4] = {
/* F2 */ { GR64BIT(crc32) } // SSE4.2
};
static BxDisasmOpcodeTable_t BxDisasmGrpOs64B_adcx[3] = {
/* 16 */ { 0, &Ia_adcx_Gd_Ed },
/* 32 */ { 0, &Ia_adcx_Gd_Ed },
/* 64 */ { 0, &Ia_adcx_Gq_Eq },
};
static BxDisasmOpcodeTable_t BxDisasmGrpOs64B_adox[3] = {
/* 16 */ { 0, &Ia_adox_Gd_Ed },
/* 32 */ { 0, &Ia_adox_Gd_Ed },
/* 64 */ { 0, &Ia_adox_Gq_Eq },
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f38f6[4] = {
/* -- */ { 0, &Ia_Invalid },
/* 66 */ { GR64BIT(adcx) },
/* F3 */ { GR64BIT(adox) },
/* F2 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3a0f[4] = {
/* -- */ { 0, &Ia_palignr_Pq_Qq_Ib }, // SSSE3
/* 66 */ { 0, &Ia_palignr_Vdq_Wdq_Ib },
@ -1354,7 +1373,7 @@ static BxDisasmOpcodeTable_t BxDisasm3ByteOpTable0f38[256] = {
/* F3 */ { 0, &Ia_Invalid },
/* F4 */ { 0, &Ia_Invalid },
/* F5 */ { 0, &Ia_Invalid },
/* F6 */ { 0, &Ia_Invalid },
/* F6 */ { GRPSSE(0f38f6) },
/* F7 */ { 0, &Ia_Invalid },
/* F8 */ { 0, &Ia_Invalid },
/* F9 */ { 0, &Ia_Invalid },

View File

@ -79,6 +79,7 @@
#define IA_XOP (BX_CONST64(1) << 37) /* XOP instruction (AMD) */
#define IA_TBM (BX_CONST64(1) << 38) /* TBM instruction (AMD) */
#define IA_SVM (BX_CONST64(1) << 39) /* SVM instruction (AMD) */
#define IA_ADX (BX_CONST64(1) << 40) /* ADCX/ADOX instruction */
/* general purpose bit register */
enum {

View File

@ -44,6 +44,8 @@ Ia_adcw_Ew_Gw = { "adc", "adcw", Ew, Gw, XX, XX, 0 },
Ia_adcw_Ew_Iw = { "adc", "adcw", Ew, Iw, XX, XX, 0 },
Ia_adcw_Ew_sIb = { "adc", "adcw", Ew, sIbw, XX, XX, 0 },
Ia_adcw_Gw_Ew = { "adc", "adcw", Gw, Ew, XX, XX, 0 },
Ia_adcx_Gd_Ed = { "adcx", "adcxd", Gd, Ed, XX, XX, IA_ADX },
Ia_adcx_Gq_Eq = { "adcx", "adcxq", Gq, Eq, XX, XX, IA_ADX },
Ia_addb_AL_Ib = { "add", "addb", AL_Reg, Ib, XX, XX, 0 },
Ia_addb_Eb_Gb = { "add", "addb", Eb, Gb, XX, XX, 0 },
Ia_addb_Eb_Ib = { "add", "addb", Eb, Ib, XX, XX, 0 },
@ -69,6 +71,8 @@ Ia_addw_Ew_Gw = { "add", "addw", Ew, Gw, XX, XX, 0 },
Ia_addw_Ew_Iw = { "add", "addw", Ew, Iw, XX, XX, 0 },
Ia_addw_Ew_sIb = { "add", "addw", Ew, sIbw, XX, XX, 0 },
Ia_addw_Gw_Ew = { "add", "addw", Gw, Ew, XX, XX, 0 },
Ia_adox_Gd_Ed = { "adox", "adoxd", Gd, Ed, XX, XX, IA_ADX },
Ia_adox_Gq_Eq = { "adox", "adoxq", Gq, Eq, XX, XX, IA_ADX },
Ia_aesdec_Vdq_Wdq = { "aesdec", "aesdec", Vdq, Wdq, XX, XX, IA_AES_PCLMULQDQ },
Ia_aesdeclast_Vdq_Wdq = { "aesdeclast", "aesdeclast", Vdq, Wdq, XX, XX, IA_AES_PCLMULQDQ },
Ia_aesenc_Vdq_Wdq = { "aesenc", "aesenc", Vdq, Wdq, XX, XX, IA_AES_PCLMULQDQ },

View File

@ -3063,6 +3063,11 @@ This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
Select MOVBE Intel(R) Atom instruction support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
</para>
<para><command>adx</command></para>
<para>
Select ADCX/ADOX instructions support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
</para>
<para><command>xsave</command></para>
<para>
Select XSAVE extensions support.

View File

@ -255,6 +255,11 @@ movbe:
Select MOVBE Intel(R) Atom instruction support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
adx:
Select ADCX/ADOX instructions support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
xsave:
Select XSAVE extensions support.

View File

@ -505,3 +505,11 @@ Bochs CPU configurability - go over all CPUID feature extensions and see how and
Enables CPUID[0x80000001].ECX[8] flag.
Set if PREFETCHW implemented as real HW prefetch.
Uarch only. Has no effect for Bochs.
60. ISA Feature: ADX
Enables CPUID[0x00000007].EBX[19] flag.
Enables ADCX/ADOX instructions (will #UD otherwise).
Dependency: SSSE3 (3-byte opcodes)

View File

@ -1191,6 +1191,8 @@ void bx_init_hardware()
BX_INFO((" AES support: %s", aes_enabled?"yes":"no"));
bx_bool movbe_enabled = SIM->get_param_bool(BXPN_CPUID_MOVBE)->get();
BX_INFO((" MOVBE support: %s", movbe_enabled?"yes":"no"));
bx_bool adx_enabled = SIM->get_param_bool(BXPN_CPUID_ADX)->get();
BX_INFO((" ADX support: %s", adx_enabled?"yes":"no"));
#if BX_SUPPORT_X86_64
bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get();
BX_INFO((" x86-64 support: %s", x86_64_enabled?"yes":"no"));

View File

@ -54,6 +54,7 @@
#define BXPN_CPUID_SSE4A "cpuid.sse4a"
#define BXPN_CPUID_AES "cpuid.aes"
#define BXPN_CPUID_MOVBE "cpuid.movbe"
#define BXPN_CPUID_ADX "cpuid.adx"
#define BXPN_CPUID_SEP "cpuid.sep"
#define BXPN_CPUID_XSAVE "cpuid.xsave"
#define BXPN_CPUID_XSAVEOPT "cpuid.xsaveopt"