X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Farch%2Fx86%2Futility.cc;h=cf30723487bb03eefb3b49f047e405b02b054ae2;hb=68127ca3da543db0c2f3d131d2b3f3525a35ec50;hp=3df948986d503dbcd1489c2402da57011dad2f48;hpb=d06064c38613662dfbf68a701052278b4018de8c;p=gem5.git diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 3df948986..cf3072348 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -44,6 +44,7 @@ #include "arch/x86/utility.hh" #include "arch/x86/x86_traits.hh" #include "cpu/base.hh" +#include "fputils/fp80.h" #include "sim/system.hh" namespace X86ISA { @@ -51,8 +52,23 @@ namespace X86ISA { uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) { - panic("getArgument() not implemented for x86!\n"); - M5_DUMMY_RETURN + if (fp) { + panic("getArgument(): Floating point arguments not implemented\n"); + } else if (size != 8) { + panic("getArgument(): Can only handle 64-bit arguments.\n"); + } + + // The first 6 integer arguments are passed in registers, the rest + // are passed on the stack. + const int int_reg_map[] = { + INTREG_RDI, INTREG_RSI, INTREG_RDX, + INTREG_RCX, INTREG_R8, INTREG_R9 + }; + if (number < sizeof(int_reg_map) / sizeof(*int_reg_map)) { + return tc->readIntReg(int_reg_map[number]); + } else { + panic("getArgument(): Don't know how to handle stack arguments.\n"); + } } void initCPU(ThreadContext *tc, int cpuId) @@ -167,7 +183,7 @@ void initCPU(ThreadContext *tc, int cpuId) tc->setMiscReg(MISCREG_APIC_BASE, lApicBase); Interrupts * interrupts = dynamic_cast( - tc->getCpuPtr()->getInterruptController()); + tc->getCpuPtr()->getInterruptController(0)); assert(interrupts); interrupts->setRegNoEffect(APIC_ID, cpuId << 24); @@ -185,12 +201,12 @@ void initCPU(ThreadContext *tc, int cpuId) void startupCPU(ThreadContext *tc, int cpuId) { if (cpuId == 0 || !FullSystem) { - tc->activate(Cycles(0)); + tc->activate(); } else { // This is an application processor (AP). It should be initialized to // look like only the BIOS POST has run on it and put then put it into // a halted state. - tc->suspend(Cycles(0)); + tc->suspend(); } } @@ -201,11 +217,9 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) // need to be considered while copying state. That will likely not be // true in the future. for (int i = 0; i < NUM_MISCREGS; ++i) { - if ( ( i != MISCREG_CR1 && - !(i > MISCREG_CR4 && i < MISCREG_CR8) && - !(i > MISCREG_CR8 && i <= MISCREG_CR15) ) == false) { + if (!isValidMiscReg(i)) continue; - } + dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); } @@ -222,10 +236,13 @@ copyRegs(ThreadContext *src, ThreadContext *dest) { //copy int regs for (int i = 0; i < NumIntRegs; ++i) - dest->setIntReg(i, src->readIntReg(i)); + dest->setIntRegFlat(i, src->readIntRegFlat(i)); //copy float regs for (int i = 0; i < NumFloatRegs; ++i) - dest->setFloatRegBits(i, src->readFloatRegBits(i)); + dest->setFloatRegBitsFlat(i, src->readFloatRegBitsFlat(i)); + //copy condition-code regs + for (int i = 0; i < NumCCRegs; ++i) + dest->setCCRegFlat(i, src->readCCRegFlat(i)); copyMiscRegs(src, dest); dest->pcState(src->pcState()); } @@ -240,9 +257,9 @@ uint64_t getRFlags(ThreadContext *tc) { const uint64_t ncc_flags(tc->readMiscRegNoEffect(MISCREG_RFLAGS)); - const uint64_t cc_flags(tc->readIntReg(X86ISA::INTREG_PSEUDO(0))); - const uint64_t cfof_bits(tc->readIntReg(X86ISA::INTREG_PSEUDO(1))); - const uint64_t df_bit(tc->readIntReg(X86ISA::INTREG_PSEUDO(2))); + const uint64_t cc_flags(tc->readCCReg(X86ISA::CCREG_ZAPS)); + const uint64_t cfof_bits(tc->readCCReg(X86ISA::CCREG_CFOF)); + const uint64_t df_bit(tc->readCCReg(X86ISA::CCREG_DF)); // ecf (PSEUDO(3)) & ezf (PSEUDO(4)) are only visible to // microcode, so we can safely ignore them. @@ -255,19 +272,65 @@ getRFlags(ThreadContext *tc) void setRFlags(ThreadContext *tc, uint64_t val) { - tc->setIntReg(X86ISA::INTREG_PSEUDO(0), val & ccFlagMask); - tc->setIntReg(X86ISA::INTREG_PSEUDO(1), val & cfofMask); - tc->setIntReg(X86ISA::INTREG_PSEUDO(2), val & DFBit); + tc->setCCReg(X86ISA::CCREG_ZAPS, val & ccFlagMask); + tc->setCCReg(X86ISA::CCREG_CFOF, val & cfofMask); + tc->setCCReg(X86ISA::CCREG_DF, val & DFBit); // Internal microcode registers (ECF & EZF) - tc->setIntReg(X86ISA::INTREG_PSEUDO(3), 0); - tc->setIntReg(X86ISA::INTREG_PSEUDO(4), 0); + tc->setCCReg(X86ISA::CCREG_ECF, 0); + tc->setCCReg(X86ISA::CCREG_EZF, 0); // Update the RFLAGS misc reg with whatever didn't go into the // magic registers. tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); } +uint8_t +convX87TagsToXTags(uint16_t ftw) +{ + uint8_t ftwx(0); + for (int i = 0; i < 8; ++i) { + // Extract the tag for the current element on the FP stack + const unsigned tag((ftw >> (2 * i)) & 0x3); + + /* + * Check the type of the current FP element. Valid values are: + * 0 == Valid + * 1 == Zero + * 2 == Special (Nan, unsupported, infinity, denormal) + * 3 == Empty + */ + // The xsave version of the tag word only keeps track of + // whether the element is empty or not. Set the corresponding + // bit in the ftwx if it's not empty, + if (tag != 0x3) + ftwx |= 1 << i; + } + + return ftwx; +} + +uint16_t +convX87XTagsToTags(uint8_t ftwx) +{ + uint16_t ftw(0); + for (int i = 0; i < 8; ++i) { + const unsigned xtag(((ftwx >> i) & 0x1)); + + // The xtag for an x87 stack position is 0 for empty stack positions. + if (!xtag) { + // Set the tag word to 3 (empty) for the current element. + ftw |= 0x3 << (2 * i); + } else { + // TODO: We currently assume that non-empty elements are + // valid (0x0), but we should ideally reconstruct the full + // state (valid/zero/special). + } + } + + return ftw; +} + uint16_t genX87Tags(uint16_t ftw, uint8_t top, int8_t spm) { @@ -288,4 +351,20 @@ genX87Tags(uint16_t ftw, uint8_t top, int8_t spm) return ftw; } +double +loadFloat80(const void *_mem) +{ + const fp80_t *fp80((const fp80_t *)_mem); + + return fp80_cvtd(*fp80); +} + +void +storeFloat80(void *_mem, double value) +{ + fp80_t *fp80((fp80_t *)_mem); + + *fp80 = fp80_cvfd(value); +} + } // namespace X86_ISA