X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Farch%2Fx86%2Futility.cc;h=cf30723487bb03eefb3b49f047e405b02b054ae2;hb=68127ca3da543db0c2f3d131d2b3f3525a35ec50;hp=756e9d526f17083f4b01bef26246dd2a24dbaa21;hpb=c69d48f007d2521fdbea52a0a7a95cfc4a547174;p=gem5.git diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 756e9d526..cf3072348 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2011 Advanced Micro Devices, Inc. * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -37,17 +38,13 @@ * Authors: Gabe Black */ -#include "config/full_system.hh" - -#if FULL_SYSTEM #include "arch/x86/interrupts.hh" -#endif -#include "arch/x86/regs/int.hh" -#include "arch/x86/regs/misc.hh" -#include "arch/x86/regs/segment.hh" +#include "arch/x86/registers.hh" +#include "arch/x86/tlb.hh" #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 { @@ -55,15 +52,25 @@ namespace X86ISA { uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) { -#if FULL_SYSTEM - panic("getArgument() not implemented for x86!\n"); -#else - panic("getArgument() only implemented for FULL_SYSTEM\n"); - M5_DUMMY_RETURN -#endif + 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"); + } } -# if FULL_SYSTEM void initCPU(ThreadContext *tc, int cpuId) { // This function is essentially performing a reset. The actual INIT @@ -176,14 +183,12 @@ 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); interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14); - - interrupts->setClock(tc->getCpuPtr()->ticks(16)); // TODO Set the SMRAM base address (SMBASE) to 0x00030000 @@ -193,46 +198,52 @@ void initCPU(ThreadContext *tc, int cpuId) tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0); } -#endif - void startupCPU(ThreadContext *tc, int cpuId) { -#if FULL_SYSTEM - if (cpuId == 0) { - tc->activate(0); + if (cpuId == 0 || !FullSystem) { + 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(0); + tc->suspend(); } -#else - tc->activate(0); -#endif } void copyMiscRegs(ThreadContext *src, ThreadContext *dest) { - warn("copyMiscRegs is naively implemented for x86\n"); + // This function assumes no side effects other than TLB invalidation + // 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)); } + + // The TSC has to be updated with side-effects if the CPUs in a + // CPU switch have different frequencies. + dest->setMiscReg(MISCREG_TSC, src->readMiscReg(MISCREG_TSC)); + + dest->getITBPtr()->flushAll(); + dest->getDTBPtr()->flushAll(); } void copyRegs(ThreadContext *src, ThreadContext *dest) { - panic("copyRegs not implemented for x86!\n"); //copy int regs + for (int i = 0; i < NumIntRegs; ++i) + dest->setIntRegFlat(i, src->readIntRegFlat(i)); //copy float regs + for (int i = 0; i < NumFloatRegs; ++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()); } @@ -242,5 +253,118 @@ skipFunction(ThreadContext *tc) panic("Not implemented for x86\n"); } +uint64_t +getRFlags(ThreadContext *tc) +{ + const uint64_t ncc_flags(tc->readMiscRegNoEffect(MISCREG_RFLAGS)); + 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. + + // Reconstruct the real rflags state, mask out internal flags, and + // make sure reserved bits have the expected values. + return ((ncc_flags | cc_flags | cfof_bits | df_bit) & 0x3F7FD5) + | 0x2; +} + +void +setRFlags(ThreadContext *tc, uint64_t val) +{ + 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->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) +{ + const uint8_t new_top((top + spm + 8) % 8); + + if (spm > 0) { + // Removing elements from the stack. Flag the elements as empty. + for (int i = top; i != new_top; i = (i + 1 + 8) % 8) + ftw |= 0x3 << (2 * i); + } else if (spm < 0) { + // Adding elements to the stack. Flag the new elements as + // valid. We should ideally decode them and "do the right + // thing". + for (int i = new_top; i != top; i = (i + 1 + 8) % 8) + ftw &= ~(0x3 << (2 * i)); + } + + 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