reduce CPU dependencies from fetchdecode module
This commit is contained in:
parent
778c0c6fed
commit
596b3b6eb8
@ -26,13 +26,6 @@
|
||||
|
||||
#include "decoder/decoder.h"
|
||||
|
||||
#define BX_16BIT_REG_IP (BX_GENERAL_REGISTERS)
|
||||
#define BX_32BIT_REG_EIP (BX_GENERAL_REGISTERS)
|
||||
#define BX_64BIT_REG_RIP (BX_GENERAL_REGISTERS)
|
||||
|
||||
#define BX_TMP_REGISTER (BX_GENERAL_REGISTERS+1)
|
||||
#define BX_NIL_REGISTER (BX_GENERAL_REGISTERS+2)
|
||||
|
||||
#if defined(NEED_CPU_REG_SHORTCUTS)
|
||||
|
||||
/* WARNING:
|
||||
@ -475,14 +468,12 @@ class BX_CPU_C;
|
||||
class BX_MEM_C;
|
||||
class bxInstruction_c;
|
||||
|
||||
typedef void BX_INSF_TYPE;
|
||||
|
||||
// <TAG-TYPE-EXECUTEPTR-START>
|
||||
#if BX_USE_CPU_SMF
|
||||
typedef BX_INSF_TYPE (BX_CPP_AttrRegparmN(1) *BxExecutePtr_tR)(bxInstruction_c *);
|
||||
//typedef BX_INSF_TYPE (BX_CPP_AttrRegparmN(1) *BxExecutePtr_tR)(bxInstruction_c *);
|
||||
typedef void (BX_CPP_AttrRegparmN(1) *BxRepIterationPtr_tR)(bxInstruction_c *);
|
||||
#else
|
||||
typedef BX_INSF_TYPE (BX_CPU_C::*BxExecutePtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
|
||||
//typedef BX_INSF_TYPE (BX_CPU_C::*BxExecutePtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
|
||||
typedef void (BX_CPU_C::*BxRepIterationPtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
|
||||
#endif
|
||||
// <TAG-TYPE-EXECUTEPTR-END>
|
||||
|
@ -238,6 +238,13 @@ enum BxRegs64 {
|
||||
# define BX_GENERAL_REGISTERS 8
|
||||
#endif
|
||||
|
||||
const unsigned BX_16BIT_REG_IP = (BX_GENERAL_REGISTERS),
|
||||
BX_32BIT_REG_EIP = (BX_GENERAL_REGISTERS),
|
||||
BX_64BIT_REG_RIP = (BX_GENERAL_REGISTERS);
|
||||
|
||||
const unsigned BX_TMP_REGISTER = (BX_GENERAL_REGISTERS+1);
|
||||
const unsigned BX_NIL_REGISTER = (BX_GENERAL_REGISTERS+2);
|
||||
|
||||
enum OpmaskRegs {
|
||||
BX_REG_OPMASK_K0,
|
||||
BX_REG_OPMASK_K1,
|
||||
@ -249,5 +256,35 @@ enum OpmaskRegs {
|
||||
BX_REG_OPMASK_K7
|
||||
};
|
||||
|
||||
// AVX Registers
|
||||
enum bx_avx_vector_length {
|
||||
BX_NO_VL,
|
||||
BX_VL128 = 1,
|
||||
BX_VL256 = 2,
|
||||
BX_VL512 = 4,
|
||||
};
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
# define BX_VLMAX BX_VL512
|
||||
#else
|
||||
# if BX_SUPPORT_AVX
|
||||
# define BX_VLMAX BX_VL256
|
||||
# else
|
||||
# define BX_VLMAX BX_VL128
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
# define BX_XMM_REGISTERS 32
|
||||
#else
|
||||
# if BX_SUPPORT_X86_64
|
||||
# define BX_XMM_REGISTERS 16
|
||||
# else
|
||||
# define BX_XMM_REGISTERS 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
const unsigned BX_VECTOR_TMP_REGISTER = (BX_XMM_REGISTERS);
|
||||
|
||||
#endif // BX_X86_DECODER_H
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
|
||||
#include "fetchdecode.h"
|
||||
|
||||
extern int fetchDecode32(const Bit8u *fetchPtr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
extern int fetchDecode32(const Bit8u *fetchPtr, bx_bool is_32, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
#if BX_SUPPORT_X86_64
|
||||
extern int fetchDecode64(const Bit8u *fetchPtr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
extern int fetchDecode64(const Bit8u *fetchPtr, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
#endif
|
||||
|
||||
// table of all Bochs opcodes
|
||||
@ -603,22 +603,14 @@ char* disasm(char *disbufptr, const bxInstruction_c *i, bx_address cs_base, bx_a
|
||||
|
||||
char* disasm(const Bit8u *opcode, bool is_32, bool is_64, char *disbufptr, bxInstruction_c *i, bx_address cs_base, bx_address rip)
|
||||
{
|
||||
Bit32u fetchModeMask = BX_FETCH_MODE_SSE_OK |
|
||||
BX_FETCH_MODE_AVX_OK |
|
||||
BX_FETCH_MODE_OPMASK_OK |
|
||||
BX_FETCH_MODE_EVEX_OK;
|
||||
|
||||
if (is_64) fetchModeMask |= BX_FETCH_MODE_IS64_MASK;
|
||||
else if (is_32) fetchModeMask |= BX_FETCH_MODE_IS32_MASK;
|
||||
|
||||
int ret;
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (is_64)
|
||||
ret = fetchDecode64(opcode, fetchModeMask, BX_CPU(0)->is_cpu_extension_supported(BX_ISA_ALT_MOV_CR8), i, 16);
|
||||
ret = fetchDecode64(opcode, BX_CPU(0)->is_cpu_extension_supported(BX_ISA_ALT_MOV_CR8), i, 16);
|
||||
else
|
||||
#endif
|
||||
ret = fetchDecode32(opcode, fetchModeMask, BX_CPU(0)->is_cpu_extension_supported(BX_ISA_ALT_MOV_CR8), i, 16);
|
||||
ret = fetchDecode32(opcode, is_32, BX_CPU(0)->is_cpu_extension_supported(BX_ISA_ALT_MOV_CR8), i, 16);
|
||||
|
||||
if (ret < 0)
|
||||
sprintf(disbufptr, "decode failed");
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "bochs.h"
|
||||
#include "../cpu.h"
|
||||
|
||||
#include "decoder.h"
|
||||
#include "instr.h"
|
||||
|
||||
#define LOG_THIS genlog->
|
||||
|
||||
///////////////////////////
|
||||
@ -67,6 +70,13 @@ struct BxOpcodeDecodeDescriptor32 {
|
||||
const BxOpcodeInfo_t *opcode_table;
|
||||
};
|
||||
|
||||
// table of all Bochs opcodes
|
||||
bxIAOpcodeTable BxOpcodesTable[] = {
|
||||
#define bx_define_opcode(a, b, c, d, s1, s2, s3, s4, e) { b, c, { s1, s2, s3, s4 }, e },
|
||||
#include "ia_opcodes.def"
|
||||
};
|
||||
#undef bx_define_opcode
|
||||
|
||||
// Some info on the opcodes at {0F A6} and {0F A7}
|
||||
//
|
||||
// On 386 steps A0-B0:
|
||||
@ -1193,13 +1203,6 @@ static unsigned sreg_mod1or2_base32[8] = {
|
||||
BX_SEG_REG_DS
|
||||
};
|
||||
|
||||
// table of all Bochs opcodes
|
||||
bxIAOpcodeTable BxOpcodesTable[] = {
|
||||
#define bx_define_opcode(a, b, c, d, s1, s2, s3, s4, e) { b, c, { s1, s2, s3, s4 }, e },
|
||||
#include "ia_opcodes.def"
|
||||
};
|
||||
#undef bx_define_opcode
|
||||
|
||||
extern const Bit8u *decodeModrm32(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, unsigned mod, unsigned nnn, unsigned rm);
|
||||
extern const Bit8u *parseModrm32(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, struct bx_modrm *modrm);
|
||||
extern int decodeImmediate32(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, unsigned imm_mode, unsigned imm_mode2);
|
||||
@ -2494,204 +2497,6 @@ int decoder_ud32(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, unsign
|
||||
return BX_IA_ERROR;
|
||||
}
|
||||
|
||||
int fetchDecode32(const Bit8u *iptr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage)
|
||||
{
|
||||
if (remainingInPage > 15) remainingInPage = 15;
|
||||
|
||||
unsigned remain = remainingInPage; // remain must be at least 1
|
||||
unsigned b1;
|
||||
int ia_opcode = BX_IA_ERROR;
|
||||
unsigned seg_override = BX_SEG_REG_NULL;
|
||||
bx_bool is_32, os_32, lock = 0;
|
||||
unsigned sse_prefix = SSE_PREFIX_NONE;
|
||||
|
||||
os_32 = is_32 = fetchModeMask & BX_FETCH_MODE_IS32_MASK;
|
||||
|
||||
i->init(/*os32*/ is_32, /*as32*/ is_32,
|
||||
/*os64*/ 0, /*as64*/ 0);
|
||||
|
||||
fetch_b1:
|
||||
b1 = *iptr++;
|
||||
remain--;
|
||||
|
||||
switch (b1) {
|
||||
case 0x0f: // 2-byte escape
|
||||
if (remain != 0) {
|
||||
remain--;
|
||||
b1 = 0x100 | *iptr++;
|
||||
break;
|
||||
}
|
||||
return(-1);
|
||||
case 0x66: // OpSize
|
||||
os_32 = !is_32;
|
||||
if(!sse_prefix) sse_prefix = SSE_PREFIX_66;
|
||||
i->setOs32B(os_32);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0x67: // AddrSize
|
||||
i->setAs32B(!is_32);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0xf2: // REPNE/REPNZ
|
||||
case 0xf3: // REP/REPE/REPZ
|
||||
sse_prefix = (b1 & 3) ^ 1;
|
||||
i->setLockRepUsed(b1 & 3);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0x26: // ES:
|
||||
case 0x2e: // CS:
|
||||
case 0x36: // SS:
|
||||
case 0x3e: // DS:
|
||||
seg_override = (b1 >> 3) & 3;
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0x64: // FS:
|
||||
case 0x65: // GS:
|
||||
seg_override = (b1 & 0xf);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0xf0: // LOCK:
|
||||
lock = 1;
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (b1 == 0x138 || b1 == 0x13a) {
|
||||
if (remain == 0)
|
||||
return(-1);
|
||||
if (b1 == 0x138) b1 = 0x200 | *iptr++;
|
||||
else b1 = 0x300 | *iptr++;
|
||||
remain--;
|
||||
}
|
||||
#endif
|
||||
|
||||
i->setSeg(BX_SEG_REG_DS); // default segment is DS:
|
||||
|
||||
i->modRMForm.Id = 0;
|
||||
|
||||
BxOpcodeDecodeDescriptor32 *decode_descriptor = &decode32_descriptor[b1];
|
||||
ia_opcode = decode_descriptor->decode_method(iptr, remain, i, b1, sse_prefix, decode_descriptor->opcode_table);
|
||||
if (ia_opcode < 0)
|
||||
return(-1);
|
||||
|
||||
i->setILen(remainingInPage - remain);
|
||||
i->setIaOpcode(ia_opcode);
|
||||
|
||||
// assign memory segment override
|
||||
if (! BX_NULL_SEG_REG(seg_override))
|
||||
i->setSeg(seg_override);
|
||||
|
||||
if (! i->modC0()) {
|
||||
i->execute1 = BxOpcodesTable[ia_opcode].execute1;
|
||||
i->handlers.execute2 = BxOpcodesTable[ia_opcode].execute2;
|
||||
|
||||
if (ia_opcode == BX_IA_MOV_Op32_GdEd) {
|
||||
if (i->seg() == BX_SEG_REG_SS)
|
||||
i->execute1 = &BX_CPU_C::MOV32S_GdEdM;
|
||||
}
|
||||
if (ia_opcode == BX_IA_MOV_Op32_EdGd) {
|
||||
if (i->seg() == BX_SEG_REG_SS)
|
||||
i->execute1 = &BX_CPU_C::MOV32S_EdGdM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i->execute1 = BxOpcodesTable[ia_opcode].execute2;
|
||||
i->handlers.execute2 = NULL;
|
||||
}
|
||||
|
||||
BX_ASSERT(i->execute1);
|
||||
|
||||
Bit32u op_flags = BxOpcodesTable[ia_opcode].opflags;
|
||||
|
||||
if (lock) {
|
||||
i->setLock();
|
||||
// lock prefix not allowed or destination operand is not memory
|
||||
if (i->modC0() || !(op_flags & BX_LOCKABLE)) {
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (handle_lock_cr0 && (ia_opcode == BX_IA_MOV_CR0Rd || ia_opcode == BX_IA_MOV_RdCR0)) {
|
||||
if (ia_opcode == BX_IA_MOV_CR0Rd)
|
||||
i->setSrcReg(0, 8); // extend CR0 -> CR8
|
||||
if (ia_opcode == BX_IA_MOV_RdCR0)
|
||||
i->setSrcReg(1, 8); // extend CR0 -> CR8
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// replace execution function with undefined-opcode
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
if ((op_flags & BX_PREPARE_EVEX) != 0 && i->getEvexb()) {
|
||||
if (! i->modC0()) {
|
||||
if ((op_flags & BX_PREPARE_EVEX_NO_BROADCAST) == BX_PREPARE_EVEX_NO_BROADCAST) {
|
||||
// BX_DEBUG(("%s: broadcast is not supported for this instruction", i->getIaOpcodeNameShort()));
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((op_flags & BX_PREPARE_EVEX_NO_SAE) == BX_PREPARE_EVEX_NO_SAE) {
|
||||
// BX_DEBUG(("%s: EVEX.b in reg form is not allowed for instructions which cannot cause floating point exception", i->getIaOpcodeNameShort()));
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_SSE_OK)) {
|
||||
if (op_flags & BX_PREPARE_SSE) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoSSE;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#if BX_SUPPORT_AVX
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_AVX_OK)) {
|
||||
if (op_flags & BX_PREPARE_AVX) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoAVX;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#if BX_SUPPORT_EVEX
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_OPMASK_OK)) {
|
||||
if (op_flags & BX_PREPARE_OPMASK) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoOpMask;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_EVEX_OK)) {
|
||||
if (op_flags & BX_PREPARE_EVEX) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoEVEX;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((op_flags & BX_TRACE_END) != 0 || i->execute1 == &BX_CPU_C::BxError)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
Bit16u WalkOpcodeTables(const BxExtOpcodeInfo_t *OpcodeInfoPtr, Bit16u &attr, bx_bool is_64, unsigned modrm, unsigned sse_prefix, unsigned osize, unsigned vex_vl, bx_bool vex_w)
|
||||
{
|
||||
// Parse mod-nnn-rm and related bytes
|
||||
@ -2805,6 +2610,210 @@ Bit16u WalkOpcodeTables(const BxExtOpcodeInfo_t *OpcodeInfoPtr, Bit16u &attr, bx
|
||||
return (ia_opcode);
|
||||
}
|
||||
|
||||
int fetchDecode32(const Bit8u *iptr, bx_bool is_32, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage)
|
||||
{
|
||||
if (remainingInPage > 15) remainingInPage = 15;
|
||||
|
||||
unsigned remain = remainingInPage; // remain must be at least 1
|
||||
unsigned b1;
|
||||
int ia_opcode = BX_IA_ERROR;
|
||||
unsigned seg_override = BX_SEG_REG_NULL;
|
||||
bx_bool os_32 = is_32, lock = 0;
|
||||
unsigned sse_prefix = SSE_PREFIX_NONE;
|
||||
|
||||
i->init(/*os32*/ is_32, /*as32*/ is_32,
|
||||
/*os64*/ 0, /*as64*/ 0);
|
||||
|
||||
fetch_b1:
|
||||
b1 = *iptr++;
|
||||
remain--;
|
||||
|
||||
switch (b1) {
|
||||
case 0x0f: // 2-byte escape
|
||||
if (remain != 0) {
|
||||
remain--;
|
||||
b1 = 0x100 | *iptr++;
|
||||
break;
|
||||
}
|
||||
return(-1);
|
||||
case 0x66: // OpSize
|
||||
os_32 = !is_32;
|
||||
if(!sse_prefix) sse_prefix = SSE_PREFIX_66;
|
||||
i->setOs32B(os_32);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0x67: // AddrSize
|
||||
i->setAs32B(!is_32);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0xf2: // REPNE/REPNZ
|
||||
case 0xf3: // REP/REPE/REPZ
|
||||
sse_prefix = (b1 & 3) ^ 1;
|
||||
i->setLockRepUsed(b1 & 3);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0x26: // ES:
|
||||
case 0x2e: // CS:
|
||||
case 0x36: // SS:
|
||||
case 0x3e: // DS:
|
||||
seg_override = (b1 >> 3) & 3;
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0x64: // FS:
|
||||
case 0x65: // GS:
|
||||
seg_override = (b1 & 0xf);
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
case 0xf0: // LOCK:
|
||||
lock = 1;
|
||||
if (remain != 0) {
|
||||
goto fetch_b1;
|
||||
}
|
||||
return(-1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (b1 == 0x138 || b1 == 0x13a) {
|
||||
if (remain == 0)
|
||||
return(-1);
|
||||
if (b1 == 0x138) b1 = 0x200 | *iptr++;
|
||||
else b1 = 0x300 | *iptr++;
|
||||
remain--;
|
||||
}
|
||||
#endif
|
||||
|
||||
i->setSeg(BX_SEG_REG_DS); // default segment is DS:
|
||||
|
||||
i->modRMForm.Id = 0;
|
||||
|
||||
BxOpcodeDecodeDescriptor32 *decode_descriptor = &decode32_descriptor[b1];
|
||||
ia_opcode = decode_descriptor->decode_method(iptr, remain, i, b1, sse_prefix, decode_descriptor->opcode_table);
|
||||
if (ia_opcode < 0)
|
||||
return(-1);
|
||||
|
||||
i->setILen(remainingInPage - remain);
|
||||
i->setIaOpcode(ia_opcode);
|
||||
|
||||
// assign memory segment override
|
||||
if (! BX_NULL_SEG_REG(seg_override))
|
||||
i->setSeg(seg_override);
|
||||
|
||||
Bit32u op_flags = BxOpcodesTable[ia_opcode].opflags;
|
||||
|
||||
if (lock) {
|
||||
i->setLock();
|
||||
// lock prefix not allowed or destination operand is not memory
|
||||
if (i->modC0() || !(op_flags & BX_LOCKABLE)) {
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (handle_lock_cr0 && (ia_opcode == BX_IA_MOV_CR0Rd || ia_opcode == BX_IA_MOV_RdCR0)) {
|
||||
if (ia_opcode == BX_IA_MOV_CR0Rd)
|
||||
i->setSrcReg(0, 8); // extend CR0 -> CR8
|
||||
if (ia_opcode == BX_IA_MOV_RdCR0)
|
||||
i->setSrcReg(1, 8); // extend CR0 -> CR8
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// replace execution function with undefined-opcode
|
||||
i->setIaOpcode(BX_IA_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int assignHandler(bxInstruction_c *i, Bit32u fetchModeMask)
|
||||
{
|
||||
unsigned ia_opcode = i->getIaOpcode();
|
||||
|
||||
if (! i->modC0()) {
|
||||
i->execute1 = BxOpcodesTable[ia_opcode].execute1;
|
||||
i->handlers.execute2 = BxOpcodesTable[ia_opcode].execute2;
|
||||
|
||||
if (ia_opcode == BX_IA_MOV_Op32_GdEd) {
|
||||
if (i->seg() == BX_SEG_REG_SS)
|
||||
i->execute1 = &BX_CPU_C::MOV32S_GdEdM;
|
||||
}
|
||||
if (ia_opcode == BX_IA_MOV_Op32_EdGd) {
|
||||
if (i->seg() == BX_SEG_REG_SS)
|
||||
i->execute1 = &BX_CPU_C::MOV32S_EdGdM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i->execute1 = BxOpcodesTable[ia_opcode].execute2;
|
||||
i->handlers.execute2 = NULL;
|
||||
}
|
||||
|
||||
BX_ASSERT(i->execute1);
|
||||
|
||||
Bit32u op_flags = BxOpcodesTable[ia_opcode].opflags;
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
if ((op_flags & BX_PREPARE_EVEX) != 0 && i->getEvexb()) {
|
||||
if (! i->modC0()) {
|
||||
if ((op_flags & BX_PREPARE_EVEX_NO_BROADCAST) == BX_PREPARE_EVEX_NO_BROADCAST) {
|
||||
// BX_DEBUG(("%s: broadcast is not supported for this instruction", i->getIaOpcodeNameShort()));
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((op_flags & BX_PREPARE_EVEX_NO_SAE) == BX_PREPARE_EVEX_NO_SAE) {
|
||||
// BX_DEBUG(("%s: EVEX.b in reg form is not allowed for instructions which cannot cause floating point exception", i->getIaOpcodeNameShort()));
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_SSE_OK)) {
|
||||
if (op_flags & BX_PREPARE_SSE) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoSSE;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#if BX_SUPPORT_AVX
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_AVX_OK)) {
|
||||
if (op_flags & BX_PREPARE_AVX) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoAVX;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#if BX_SUPPORT_EVEX
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_OPMASK_OK)) {
|
||||
if (op_flags & BX_PREPARE_OPMASK) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoOpMask;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_EVEX_OK)) {
|
||||
if (op_flags & BX_PREPARE_EVEX) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoEVEX;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((op_flags & BX_TRACE_END) != 0 || i->execute1 == &BX_CPU_C::BxError)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
const char *get_bx_opcode_name(Bit16u ia_opcode)
|
||||
{
|
||||
static const char* BxOpcodeNamesTable[BX_IA_LAST] =
|
||||
|
@ -21,7 +21,9 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "bochs.h"
|
||||
#include "../cpu.h"
|
||||
|
||||
#include "instr.h"
|
||||
#include "decoder.h"
|
||||
|
||||
#define LOG_THIS genlog->
|
||||
|
||||
@ -2319,7 +2321,7 @@ int decodeImmediate64(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, u
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fetchDecode64(const Bit8u *iptr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage)
|
||||
int fetchDecode64(const Bit8u *iptr, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage)
|
||||
{
|
||||
if (remainingInPage > 15) remainingInPage = 15;
|
||||
|
||||
@ -2455,26 +2457,6 @@ fetch_b1:
|
||||
if (! BX_NULL_SEG_REG(seg_override))
|
||||
i->setSeg(seg_override);
|
||||
|
||||
if (! i->modC0()) {
|
||||
i->execute1 = BxOpcodesTable[ia_opcode].execute1;
|
||||
i->handlers.execute2 = BxOpcodesTable[ia_opcode].execute2;
|
||||
|
||||
if (ia_opcode == BX_IA_MOV_GqEq) {
|
||||
if (i->seg() == BX_SEG_REG_SS)
|
||||
i->execute1 = &BX_CPU_C::MOV64S_GqEqM;
|
||||
}
|
||||
if (ia_opcode == BX_IA_MOV_EqGq) {
|
||||
if (i->seg() == BX_SEG_REG_SS)
|
||||
i->execute1 = &BX_CPU_C::MOV64S_EqGqM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i->execute1 = BxOpcodesTable[ia_opcode].execute2;
|
||||
i->handlers.execute2 = NULL;
|
||||
}
|
||||
|
||||
BX_ASSERT(i->execute1);
|
||||
|
||||
Bit32u op_flags = BxOpcodesTable[ia_opcode].opflags;
|
||||
|
||||
if (lock) {
|
||||
@ -2489,59 +2471,11 @@ fetch_b1:
|
||||
}
|
||||
else {
|
||||
// replace execution function with undefined-opcode
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
i->setIaOpcode(BX_IA_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
if ((op_flags & BX_PREPARE_EVEX) != 0 && i->getEvexb()) {
|
||||
if (! i->modC0()) {
|
||||
if ((op_flags & BX_PREPARE_EVEX_NO_BROADCAST) == BX_PREPARE_EVEX_NO_BROADCAST) {
|
||||
BX_DEBUG(("%s: broadcast is not supported for this instruction", i->getIaOpcodeNameShort()));
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((op_flags & BX_PREPARE_EVEX_NO_SAE) == BX_PREPARE_EVEX_NO_SAE) {
|
||||
BX_DEBUG(("%s: EVEX.b in reg form is not allowed for instructions which cannot cause floating point exception", i->getIaOpcodeNameShort()));
|
||||
i->execute1 = &BX_CPU_C::BxError;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_SSE_OK)) {
|
||||
if (op_flags & BX_PREPARE_SSE) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoSSE;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#if BX_SUPPORT_AVX
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_AVX_OK)) {
|
||||
if (op_flags & BX_PREPARE_AVX) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoAVX;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#if BX_SUPPORT_EVEX
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_OPMASK_OK)) {
|
||||
if (op_flags & BX_PREPARE_OPMASK) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoOpMask;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if (! (fetchModeMask & BX_FETCH_MODE_EVEX_OK)) {
|
||||
if (op_flags & BX_PREPARE_EVEX) {
|
||||
if (i->execute1 != &BX_CPU_C::BxError) i->execute1 = &BX_CPU_C::BxNoEVEX;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((op_flags & BX_TRACE_END) != 0 || i->execute1 == &BX_CPU_C::BxError)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,19 @@ extern bx_address bx_asize_mask[];
|
||||
|
||||
const char *get_bx_opcode_name(Bit16u ia_opcode);
|
||||
|
||||
class BX_CPU_C;
|
||||
class bxInstruction_c;
|
||||
|
||||
typedef void BX_INSF_TYPE;
|
||||
|
||||
// <TAG-TYPE-EXECUTEPTR-START>
|
||||
#if BX_USE_CPU_SMF
|
||||
typedef BX_INSF_TYPE (BX_CPP_AttrRegparmN(1) *BxExecutePtr_tR)(bxInstruction_c *);
|
||||
#else
|
||||
typedef BX_INSF_TYPE (BX_CPU_C::*BxExecutePtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
|
||||
#endif
|
||||
// <TAG-TYPE-EXECUTEPTR-END>
|
||||
|
||||
// <TAG-CLASS-INSTRUCTION-START>
|
||||
class bxInstruction_c {
|
||||
public:
|
||||
|
@ -33,10 +33,11 @@
|
||||
|
||||
bxPageWriteStampTable pageWriteStampTable;
|
||||
|
||||
extern int fetchDecode32(const Bit8u *fetchPtr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
extern int fetchDecode32(const Bit8u *fetchPtr, bx_bool is_32, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
#if BX_SUPPORT_X86_64
|
||||
extern int fetchDecode64(const Bit8u *fetchPtr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
extern int fetchDecode64(const Bit8u *fetchPtr, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage);
|
||||
#endif
|
||||
extern int assignHandler(bxInstruction_c *i, Bit32u fetchModeMask);
|
||||
|
||||
void flushICaches(void)
|
||||
{
|
||||
@ -110,10 +111,10 @@ bxICacheEntry_c* BX_CPU_C::serveICacheMiss(Bit32u eipBiased, bx_phy_address pAdd
|
||||
{
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
|
||||
ret = fetchDecode64(fetchPtr, BX_CPU_THIS_PTR fetchModeMask, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage);
|
||||
ret = fetchDecode64(fetchPtr, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage);
|
||||
else
|
||||
#endif
|
||||
ret = fetchDecode32(fetchPtr, BX_CPU_THIS_PTR fetchModeMask, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage);
|
||||
ret = fetchDecode32(fetchPtr, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage);
|
||||
|
||||
if (ret < 0) {
|
||||
// Fetching instruction on segment/page boundary
|
||||
@ -144,6 +145,8 @@ bxICacheEntry_c* BX_CPU_C::serveICacheMiss(Bit32u eipBiased, bx_phy_address pAdd
|
||||
return entry;
|
||||
}
|
||||
|
||||
ret = assignHandler(i, BX_CPU_THIS_PTR fetchModeMask);
|
||||
|
||||
// add instruction to the trace
|
||||
unsigned iLen = i->ilen();
|
||||
entry->tlen++;
|
||||
@ -262,16 +265,18 @@ void BX_CPU_C::boundaryFetch(const Bit8u *fetchPtr, unsigned remainingInPage, bx
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
|
||||
ret = fetchDecode64(fetchBuffer, BX_CPU_THIS_PTR fetchModeMask, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage+fetchBufferLimit);
|
||||
ret = fetchDecode64(fetchBuffer, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage+fetchBufferLimit);
|
||||
else
|
||||
#endif
|
||||
ret = fetchDecode32(fetchBuffer, BX_CPU_THIS_PTR fetchModeMask, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage+fetchBufferLimit);
|
||||
ret = fetchDecode32(fetchBuffer, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ALT_MOV_CR8), i, remainingInPage+fetchBufferLimit);
|
||||
|
||||
if (ret < 0) {
|
||||
BX_INFO(("boundaryFetch #GP(0): failed to complete instruction decoding"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
ret = assignHandler(i, BX_CPU_THIS_PTR fetchModeMask);
|
||||
|
||||
// Restore EIP since we fudged it to start at the 2nd page boundary.
|
||||
RIP = BX_CPU_THIS_PTR prev_rip;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// $Id$
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2003-2014 Stanislav Shwartsman
|
||||
// Copyright (c) 2003-2017 Stanislav Shwartsman
|
||||
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
@ -65,36 +65,6 @@ union bx_xmm_reg_t {
|
||||
|
||||
/* AVX REGISTER */
|
||||
|
||||
enum bx_avx_vector_length {
|
||||
BX_NO_VL,
|
||||
BX_VL128 = 1,
|
||||
BX_VL256 = 2,
|
||||
BX_VL512 = 4,
|
||||
BX_VL1024 = 8 // defined in EVEX but currently #UD in all implementations
|
||||
};
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
# define BX_VLMAX BX_VL512
|
||||
#else
|
||||
# if BX_SUPPORT_AVX
|
||||
# define BX_VLMAX BX_VL256
|
||||
# else
|
||||
# define BX_VLMAX BX_VL128
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_EVEX
|
||||
# define BX_XMM_REGISTERS 32
|
||||
#else
|
||||
# if BX_SUPPORT_X86_64
|
||||
# define BX_XMM_REGISTERS 16
|
||||
# else
|
||||
# define BX_XMM_REGISTERS 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define BX_VECTOR_TMP_REGISTER (BX_XMM_REGISTERS)
|
||||
|
||||
#if BX_SUPPORT_AVX
|
||||
|
||||
typedef
|
||||
|
Loading…
x
Reference in New Issue
Block a user