From 67f30a171e4cb7fbc3de0e1a1323af0c69db49a2 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sat, 24 Nov 2018 00:53:06 +0300 Subject: [PATCH] x86+bochs: add IDs and accessors for FPU and SSE registers Change-Id: I33146929255337f679ff80152ed4d83106621ffb --- src/core/sal/Register.hpp | 3 +- src/core/sal/bochs/BochsCPU.cc | 145 +++++++++++++++++++++++++++ src/core/sal/bochs/BochsConfig.hpp | 8 +- src/core/sal/x86/X86Architecture.cc | 48 +++++++++ src/core/sal/x86/X86Architecture.hpp | 34 ++++++- 5 files changed, 230 insertions(+), 8 deletions(-) diff --git a/src/core/sal/Register.hpp b/src/core/sal/Register.hpp index 9935d598..daf96082 100644 --- a/src/core/sal/Register.hpp +++ b/src/core/sal/Register.hpp @@ -21,7 +21,8 @@ namespace fail { enum RegisterType { RT_NONE, //!< no classification RT_GP, //!< general purpose - RT_FP, //!< floating point register + RT_FPU, //!< FPU register + RT_VECTOR, //!< vector-unit register RT_IP, //!< program counter / instruction pointer RT_ST, //!< status register RT_CONTROL, //!< control registers diff --git a/src/core/sal/bochs/BochsCPU.cc b/src/core/sal/bochs/BochsCPU.cc index 8514db88..e57a2583 100644 --- a/src/core/sal/bochs/BochsCPU.cc +++ b/src/core/sal/bochs/BochsCPU.cc @@ -41,6 +41,75 @@ regdata_t BochsCPU::getRegisterContent(const Register* reg) const case RID_SS: // untested return static_cast(BX_CPU(m_Id)->sregs[BX_SEG_REG_SS].selector.value); + + // FPU + case RID_FSW: + return BX_CPU(m_Id)->the_i387.swd; + case RID_FCW: + return BX_CPU(m_Id)->the_i387.cwd; + case RID_FTW: + return BX_CPU(m_Id)->the_i387.twd; + case RID_FPR0_LO: + case RID_FPR1_LO: + case RID_FPR2_LO: + case RID_FPR3_LO: + case RID_FPR4_LO: + case RID_FPR5_LO: + case RID_FPR6_LO: + case RID_FPR7_LO: + return BX_CPU(m_Id)->the_i387.st_space[(reg->getId() - RID_FPR0_LO) / 2].fraction; + case RID_FPR0_HI: + case RID_FPR1_HI: + case RID_FPR2_HI: + case RID_FPR3_HI: + case RID_FPR4_HI: + case RID_FPR5_HI: + case RID_FPR6_HI: + case RID_FPR7_HI: + return BX_CPU(m_Id)->the_i387.st_space[(reg->getId() - RID_FPR0_HI) / 2].exp; + + // vector units + case RID_XMM0_LO: + case RID_XMM1_LO: + case RID_XMM2_LO: + case RID_XMM3_LO: + case RID_XMM4_LO: + case RID_XMM5_LO: + case RID_XMM6_LO: + case RID_XMM7_LO: +#ifdef SIM_SUPPORT_64 + case RID_XMM8_LO: + case RID_XMM9_LO: + case RID_XMM10_LO: + case RID_XMM11_LO: + case RID_XMM12_LO: + case RID_XMM13_LO: + case RID_XMM14_LO: + case RID_XMM15_LO: +#endif + return BX_CPU(m_Id)->xmm[(reg->getId() - RID_XMM0_LO) / 2].xmm_s64[0]; + case RID_XMM0_HI: + case RID_XMM1_HI: + case RID_XMM2_HI: + case RID_XMM3_HI: + case RID_XMM4_HI: + case RID_XMM5_HI: + case RID_XMM6_HI: + case RID_XMM7_HI: +#ifdef SIM_SUPPORT_64 + case RID_XMM8_HI: + case RID_XMM9_HI: + case RID_XMM10_HI: + case RID_XMM11_HI: + case RID_XMM12_HI: + case RID_XMM13_HI: + case RID_XMM14_HI: + case RID_XMM15_HI: +#endif + return BX_CPU(m_Id)->xmm[(reg->getId() - RID_XMM0_HI) / 2].xmm_s64[1]; + case RID_MXCSR: + return BX_CPU(m_Id)->mxcsr.mxcsr; + #ifdef SIM_SUPPORT_64 case RID_PC: // program counter return static_cast(BX_CPU(m_Id)->gen_reg[BX_64BIT_REG_RIP].rrx); @@ -115,6 +184,82 @@ void BochsCPU::setRegisterContent(const Register* reg, regdata_t value) break; #endif + // FPU + case RID_FSW: + BX_CPU(m_Id)->the_i387.swd = value; + break; + case RID_FCW: + BX_CPU(m_Id)->the_i387.cwd = value; + break; + case RID_FTW: + BX_CPU(m_Id)->the_i387.twd = value; + break; + case RID_FPR0_LO: + case RID_FPR1_LO: + case RID_FPR2_LO: + case RID_FPR3_LO: + case RID_FPR4_LO: + case RID_FPR5_LO: + case RID_FPR6_LO: + case RID_FPR7_LO: + BX_CPU(m_Id)->the_i387.st_space[(reg->getId() - RID_FPR0_LO) / 2].fraction = value; + break; + case RID_FPR0_HI: + case RID_FPR1_HI: + case RID_FPR2_HI: + case RID_FPR3_HI: + case RID_FPR4_HI: + case RID_FPR5_HI: + case RID_FPR6_HI: + case RID_FPR7_HI: + BX_CPU(m_Id)->the_i387.st_space[(reg->getId() - RID_FPR0_HI) / 2].exp = value; + break; + + // vector units + case RID_XMM0_LO: + case RID_XMM1_LO: + case RID_XMM2_LO: + case RID_XMM3_LO: + case RID_XMM4_LO: + case RID_XMM5_LO: + case RID_XMM6_LO: + case RID_XMM7_LO: +#ifdef SIM_SUPPORT_64 + case RID_XMM8_LO: + case RID_XMM9_LO: + case RID_XMM10_LO: + case RID_XMM11_LO: + case RID_XMM12_LO: + case RID_XMM13_LO: + case RID_XMM14_LO: + case RID_XMM15_LO: +#endif + BX_CPU(m_Id)->xmm[(reg->getId() - RID_XMM0_LO) / 2].xmm_s64[0] = value; + break; + case RID_XMM0_HI: + case RID_XMM1_HI: + case RID_XMM2_HI: + case RID_XMM3_HI: + case RID_XMM4_HI: + case RID_XMM5_HI: + case RID_XMM6_HI: + case RID_XMM7_HI: +#ifdef SIM_SUPPORT_64 + case RID_XMM8_HI: + case RID_XMM9_HI: + case RID_XMM10_HI: + case RID_XMM11_HI: + case RID_XMM12_HI: + case RID_XMM13_HI: + case RID_XMM14_HI: + case RID_XMM15_HI: +#endif + BX_CPU(m_Id)->xmm[(reg->getId() - RID_XMM0_HI) / 2].xmm_s64[1] = value; + break; + case RID_MXCSR: + BX_CPU(m_Id)->mxcsr.mxcsr = value; + break; + #ifdef SIM_SUPPORT_64 case RID_PC: // program counter BX_CPU(m_Id)->gen_reg[BX_64BIT_REG_RIP].rrx = value; diff --git a/src/core/sal/bochs/BochsConfig.hpp b/src/core/sal/bochs/BochsConfig.hpp index 04f37294..5bc8ba1b 100644 --- a/src/core/sal/bochs/BochsConfig.hpp +++ b/src/core/sal/bochs/BochsConfig.hpp @@ -14,11 +14,9 @@ namespace fail { typedef bx_address guest_address_t; //!< the guest memory address type typedef Bit8u* host_address_t; //!< the host memory address type -#if BX_SUPPORT_X86_64 -typedef Bit64u register_data_t; //!< register data type (64 bit) -#else -typedef Bit32u register_data_t; //!< register data type (32 bit) -#endif +//! register data type (64 bit, regardless of BX_SUPPORT_X86_64: FPU and vector +//! registers are that size or larger also for 32-bit machines) +typedef Bit64u register_data_t; typedef int timer_t; //!< type of timer IDs // 'Publish' 64 bit ability (if enabled in Bochs): diff --git a/src/core/sal/x86/X86Architecture.cc b/src/core/sal/x86/X86Architecture.cc index 312ba4e1..c6dfde3c 100644 --- a/src/core/sal/x86/X86Architecture.cc +++ b/src/core/sal/x86/X86Architecture.cc @@ -84,6 +84,54 @@ X86Architecture::X86Architecture() pSSReg->setName("SS"); m_addRegister(pSSReg, RT_SEGMENT); + // FPU registers + Register *fpureg; + fpureg = new Register(RID_FSW, 16); + fpureg->setName("FSW"); + m_addRegister(fpureg, RT_FPU); + fpureg = new Register(RID_FCW, 16); + fpureg->setName("FCW"); + m_addRegister(fpureg, RT_FPU); + fpureg = new Register(RID_FTW, 16); + fpureg->setName("FTW"); + m_addRegister(fpureg, RT_FPU); + std::stringstream ss; + for (int i = 0; i < 8; ++i) { + fpureg = new Register(RID_FPR0_LO + i * 2, 64); + ss.str(""); + ss << "FPR" << i << "_LO"; + fpureg->setName(ss.str()); + m_addRegister(fpureg, RT_FPU); + + fpureg = new Register(RID_FPR0_HI + i * 2, 16); + ss.str(""); + ss << "FPR" << i << "_HI"; + fpureg->setName(ss.str()); + m_addRegister(fpureg, RT_FPU); + } + + // XMM registers (SSE) + fpureg = new Register(RID_MXCSR, 16); // in fact MXCSR has 32 bits, but only 0-15 are defined as of SSE3 + fpureg->setName("MXCSR"); + m_addRegister(fpureg, RT_VECTOR); +#ifdef SIM_SUPPORT_64 + for (int i = 0; i < 16; ++i) { +#else + for (int i = 0; i < 8; ++i) { +#endif + fpureg = new Register(RID_XMM0_LO + i * 2, 64); + ss.str(""); + ss << "XMM" << i << "_LO"; + fpureg->setName(ss.str()); + m_addRegister(fpureg, RT_VECTOR); + + fpureg = new Register(RID_XMM0_HI + i * 2, 64); + ss.str(""); + ss << "XMM" << i << "_HI"; + fpureg->setName(ss.str()); + m_addRegister(fpureg, RT_VECTOR); + } + // Registers used for extended tracing: size_t ids[] = {RID_CAX, RID_CBX, RID_CCX, RID_CDX, RID_CSI, RID_CDI, RID_CSP, RID_CBP, RID_FLAGS}; for (size_t i = 0; i < sizeof(ids)/sizeof(*ids); ++i) { diff --git a/src/core/sal/x86/X86Architecture.hpp b/src/core/sal/x86/X86Architecture.hpp index c28fa79c..3edec05d 100644 --- a/src/core/sal/x86/X86Architecture.hpp +++ b/src/core/sal/x86/X86Architecture.hpp @@ -67,9 +67,39 @@ enum SegmentRegisterId { RID_CS = RID_LAST_FLAGS_ID, RID_DS, RID_ES, RID_FS, * \enum ControlRegisterId * Symbolic identifier to access the control register. */ -enum ControlRegisterId { RID_CR0 = RID_LAST_SEGMENT_ID, RID_CR1, RID_CR2, RID_CR3, RID_CR4 }; +enum ControlRegisterId { RID_CR0 = RID_LAST_SEGMENT_ID, RID_CR1, RID_CR2, RID_CR3, RID_CR4, RID_LAST_CR_ID }; + +/** + * \enum FPURegisterId + * Symbolic identifier to access FPU registers. + */ +enum FPURegisterId { + RID_FSW = RID_LAST_CR_ID, RID_FCW, RID_FTW, + /* FPRi_LO is fraction (64 bit), FPRi_HI is exponent (16 bit), total 80 bits */ + RID_FPR0_LO, RID_FPR0_HI, RID_FPR1_LO, RID_FPR1_HI, RID_FPR2_LO, RID_FPR2_HI, RID_FPR3_LO, RID_FPR3_HI, + RID_FPR4_LO, RID_FPR4_HI, RID_FPR5_LO, RID_FPR5_HI, RID_FPR6_LO, RID_FPR6_HI, RID_FPR7_LO, RID_FPR7_HI, + /* MMXi = RID_FPRi_LO */ + RID_MMX0 = RID_FPR0_LO, RID_MMX1 = RID_FPR1_LO, RID_MMX2 = RID_FPR2_LO, RID_MMX3 = RID_FPR3_LO, + RID_MMX4 = RID_FPR4_LO, RID_MMX5 = RID_FPR5_LO, RID_MMX6 = RID_FPR6_LO, RID_MMX7 = RID_FPR7_LO, + RID_MMXDUMMY = RID_FPR7_HI, RID_LAST_FP_ID +}; + +/** + * \enum VectorRegisterId + * Symbolic identifier to access vector-unit registers (SSE, AVX, ...). + */ +enum VectorRegisterId { + /* low / high 64 bits */ + RID_XMM0_LO = RID_LAST_FP_ID, RID_XMM0_HI, RID_XMM1_LO, RID_XMM1_HI, RID_XMM2_LO, RID_XMM2_HI, RID_XMM3_LO, RID_XMM3_HI, + RID_XMM4_LO, RID_XMM4_HI, RID_XMM5_LO, RID_XMM5_HI, RID_XMM6_LO, RID_XMM6_HI, RID_XMM7_LO, RID_XMM7_HI, +#ifdef SIM_SUPPORT_64 + RID_XMM8_LO, RID_XMM8_HI, RID_XMM9_LO, RID_XMM9_HI, RID_XMM10_LO, RID_XMM10_HI, RID_XMM11_LO, RID_XMM11_HI, + RID_XMM12_LO, RID_XMM12_HI, RID_XMM13_LO, RID_XMM13_HI, RID_XMM14_LO, RID_XMM14_HI, RID_XMM15_LO, RID_XMM15_HI, +#endif + RID_MXCSR, /* MXCSR_MASK? */ + RID_LAST_VECTOR_ID +}; -// TODO FPU stuff (FSW, FCW, FTW; FPR0-7; MMX0-7; XMM0-15; MXCSR) // TODO GDTR, LDTR, IDTR, TR6+7, DR0-7, TR, MSR* } // end-of-namespace: fail