utility.cc revision 10058
12810Srdreslin@umich.edu/* 212500Snikos.nikoleris@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company 311051Sandreas.hansson@arm.com * Copyright (c) 2011 Advanced Micro Devices, Inc. 411051Sandreas.hansson@arm.com * All rights reserved. 511051Sandreas.hansson@arm.com * 611051Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 711051Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 811051Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 911051Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 1011051Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 1111051Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 1211051Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 1311051Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 1411051Sandreas.hansson@arm.com * 1511051Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 162810Srdreslin@umich.edu * modification, are permitted provided that the following conditions are 172810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 182810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 192810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 202810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 212810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 222810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 232810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 242810Srdreslin@umich.edu * this software without specific prior written permission. 252810Srdreslin@umich.edu * 262810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 282810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 292810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 302810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 312810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 322810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 332810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 342810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 352810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 362810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372810Srdreslin@umich.edu * 382810Srdreslin@umich.edu * Authors: Gabe Black 392810Srdreslin@umich.edu */ 402810Srdreslin@umich.edu 412810Srdreslin@umich.edu#include "arch/x86/interrupts.hh" 4211051Sandreas.hansson@arm.com#include "arch/x86/registers.hh" 4311051Sandreas.hansson@arm.com#include "arch/x86/tlb.hh" 442810Srdreslin@umich.edu#include "arch/x86/utility.hh" 4511051Sandreas.hansson@arm.com#include "arch/x86/x86_traits.hh" 4611051Sandreas.hansson@arm.com#include "cpu/base.hh" 4712349Snikos.nikoleris@arm.com#include "fputils/fp80.h" 482810Srdreslin@umich.edu#include "sim/system.hh" 492810Srdreslin@umich.edu 502810Srdreslin@umich.edunamespace X86ISA { 512810Srdreslin@umich.edu 5211051Sandreas.hansson@arm.comuint64_t 532810Srdreslin@umich.edugetArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) 542810Srdreslin@umich.edu{ 5511051Sandreas.hansson@arm.com if (!FullSystem) { 562810Srdreslin@umich.edu panic("getArgument() only implemented for full system mode.\n"); 5712334Sgabeblack@google.com } else if (fp) { 5811051Sandreas.hansson@arm.com panic("getArgument(): Floating point arguments not implemented\n"); 5911051Sandreas.hansson@arm.com } else if (size != 8) { 6011051Sandreas.hansson@arm.com panic("getArgument(): Can only handle 64-bit arguments.\n"); 6111051Sandreas.hansson@arm.com } 6211288Ssteve.reinhardt@amd.com 6311051Sandreas.hansson@arm.com // The first 6 integer arguments are passed in registers, the rest 6411051Sandreas.hansson@arm.com // are passed on the stack. 6511051Sandreas.hansson@arm.com const int int_reg_map[] = { 6611051Sandreas.hansson@arm.com INTREG_RDI, INTREG_RSI, INTREG_RDX, 6711051Sandreas.hansson@arm.com INTREG_RCX, INTREG_R8, INTREG_R9 6811053Sandreas.hansson@arm.com }; 6911053Sandreas.hansson@arm.com if (number < sizeof(int_reg_map) / sizeof(*int_reg_map)) { 7011051Sandreas.hansson@arm.com return tc->readIntReg(int_reg_map[number]); 7111051Sandreas.hansson@arm.com } else { 7211051Sandreas.hansson@arm.com panic("getArgument(): Don't know how to handle stack arguments.\n"); 7311197Sandreas.hansson@arm.com } 7411197Sandreas.hansson@arm.com} 7511199Sandreas.hansson@arm.com 7611197Sandreas.hansson@arm.comvoid initCPU(ThreadContext *tc, int cpuId) 7712084Sspwilson2@wisc.edu{ 7812084Sspwilson2@wisc.edu // This function is essentially performing a reset. The actual INIT 7911197Sandreas.hansson@arm.com // interrupt does a subset of this, so we'll piggyback on some of its 8011051Sandreas.hansson@arm.com // functionality. 8111051Sandreas.hansson@arm.com InitInterrupt init(0); 8211051Sandreas.hansson@arm.com init.invoke(tc); 8311051Sandreas.hansson@arm.com 8411051Sandreas.hansson@arm.com PCState pc = tc->pcState(); 8511051Sandreas.hansson@arm.com pc.upc(0); 8611051Sandreas.hansson@arm.com pc.nupc(1); 8711051Sandreas.hansson@arm.com tc->pcState(pc); 8811051Sandreas.hansson@arm.com 8911051Sandreas.hansson@arm.com // These next two loops zero internal microcode and implicit registers. 9011051Sandreas.hansson@arm.com // They aren't specified by the ISA but are used internally by M5's 9111051Sandreas.hansson@arm.com // implementation. 9211051Sandreas.hansson@arm.com for (int index = 0; index < NumMicroIntRegs; index++) { 9311051Sandreas.hansson@arm.com tc->setIntReg(INTREG_MICRO(index), 0); 9411051Sandreas.hansson@arm.com } 9511051Sandreas.hansson@arm.com 9611051Sandreas.hansson@arm.com for (int index = 0; index < NumImplicitIntRegs; index++) { 9711051Sandreas.hansson@arm.com tc->setIntReg(INTREG_IMPLICIT(index), 0); 9811051Sandreas.hansson@arm.com } 9911051Sandreas.hansson@arm.com 10011051Sandreas.hansson@arm.com // Set integer register EAX to 0 to indicate that the optional BIST 10111051Sandreas.hansson@arm.com // passed. No BIST actually runs, but software may still check this 10211051Sandreas.hansson@arm.com // register for errors. 10311051Sandreas.hansson@arm.com tc->setIntReg(INTREG_RAX, 0); 10411051Sandreas.hansson@arm.com 10511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR0, 0x0000000060000010ULL); 10611051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CR8, 0); 10711051Sandreas.hansson@arm.com 10811051Sandreas.hansson@arm.com // TODO initialize x87, 64 bit, and 128 bit media state 10911051Sandreas.hansson@arm.com 11011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRRCAP, 0x0508); 11111051Sandreas.hansson@arm.com for (int i = 0; i < 8; i++) { 11211051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_PHYS_BASE(i), 0); 11311051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_PHYS_MASK(i), 0); 11411051Sandreas.hansson@arm.com } 11511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_64K_00000, 0); 11611051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_16K_80000, 0); 11711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_16K_A0000, 0); 11811051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_C0000, 0); 11911051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_C8000, 0); 12011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_D0000, 0); 12111051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_D8000, 0); 12211051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_E0000, 0); 12311051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_E8000, 0); 12411051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_F0000, 0); 12511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MTRR_FIX_4K_F8000, 0); 12611051Sandreas.hansson@arm.com 12711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DEF_TYPE, 0); 12811051Sandreas.hansson@arm.com 12911051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MCG_CAP, 0x104); 13011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MCG_STATUS, 0); 13111051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MCG_CTL, 0); 13211051Sandreas.hansson@arm.com 13311051Sandreas.hansson@arm.com for (int i = 0; i < 5; i++) { 13411051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MC_CTL(i), 0); 13511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MC_STATUS(i), 0); 13611051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MC_ADDR(i), 0); 13711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_MC_MISC(i), 0); 13811051Sandreas.hansson@arm.com } 13911051Sandreas.hansson@arm.com 14011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSC, 0); 14111051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TSC_AUX, 0); 14211051Sandreas.hansson@arm.com 14311051Sandreas.hansson@arm.com for (int i = 0; i < 4; i++) { 14411051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_PERF_EVT_SEL(i), 0); 14511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_PERF_EVT_CTR(i), 0); 14611051Sandreas.hansson@arm.com } 14711051Sandreas.hansson@arm.com 14811051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_STAR, 0); 14911051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_LSTAR, 0); 15011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_CSTAR, 0); 15111601Sandreas.hansson@arm.com 15211601Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SF_MASK, 0); 15311051Sandreas.hansson@arm.com 15411051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_KERNEL_GS_BASE, 0); 15511051Sandreas.hansson@arm.com 15611051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SYSENTER_CS, 0); 15711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SYSENTER_ESP, 0); 15811051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SYSENTER_EIP, 0); 15911051Sandreas.hansson@arm.com 16011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_PAT, 0x0007040600070406ULL); 16111051Sandreas.hansson@arm.com 16211051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SYSCFG, 0x20601); 16311284Sandreas.hansson@arm.com 16411051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IORR_BASE0, 0); 16511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IORR_BASE1, 0); 16611051Sandreas.hansson@arm.com 16711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IORR_MASK0, 0); 16811051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IORR_MASK1, 0); 16911051Sandreas.hansson@arm.com 17011051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TOP_MEM, 0x4000000); 17111284Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_TOP_MEM2, 0x0); 17211284Sandreas.hansson@arm.com 17311284Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_DEBUG_CTL_MSR, 0); 17411284Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_LAST_BRANCH_FROM_IP, 0); 17511051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_LAST_BRANCH_TO_IP, 0); 17611284Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_LAST_EXCEPTION_FROM_IP, 0); 17711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_LAST_EXCEPTION_TO_IP, 0); 17811051Sandreas.hansson@arm.com 17911051Sandreas.hansson@arm.com // Invalidate the caches (this should already be done for us) 18011284Sandreas.hansson@arm.com 18111284Sandreas.hansson@arm.com LocalApicBase lApicBase = 0; 18211284Sandreas.hansson@arm.com lApicBase.base = 0xFEE00000 >> 12; 18311284Sandreas.hansson@arm.com lApicBase.enable = 1; 18411051Sandreas.hansson@arm.com lApicBase.bsp = (cpuId == 0); 18511744Snikos.nikoleris@arm.com tc->setMiscReg(MISCREG_APIC_BASE, lApicBase); 18611051Sandreas.hansson@arm.com 18711051Sandreas.hansson@arm.com Interrupts * interrupts = dynamic_cast<Interrupts *>( 18811051Sandreas.hansson@arm.com tc->getCpuPtr()->getInterruptController()); 18911051Sandreas.hansson@arm.com assert(interrupts); 19011286Sandreas.hansson@arm.com 19111286Sandreas.hansson@arm.com interrupts->setRegNoEffect(APIC_ID, cpuId << 24); 19211286Sandreas.hansson@arm.com 19311051Sandreas.hansson@arm.com interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14); 19411286Sandreas.hansson@arm.com 19511600Sandreas.hansson@arm.com // TODO Set the SMRAM base address (SMBASE) to 0x00030000 19611600Sandreas.hansson@arm.com 19711051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_VM_CR, 0); 19811051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_IGNNE, 0); 19911051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_SMM_CTL, 0); 20011284Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_VM_HSAVE_PA, 0); 20111051Sandreas.hansson@arm.com} 20211051Sandreas.hansson@arm.com 20311051Sandreas.hansson@arm.comvoid startupCPU(ThreadContext *tc, int cpuId) 20411602Sandreas.hansson@arm.com{ 20511051Sandreas.hansson@arm.com if (cpuId == 0 || !FullSystem) { 20611051Sandreas.hansson@arm.com tc->activate(Cycles(0)); 20711284Sandreas.hansson@arm.com } else { 20811051Sandreas.hansson@arm.com // This is an application processor (AP). It should be initialized to 20911284Sandreas.hansson@arm.com // look like only the BIOS POST has run on it and put then put it into 21011602Sandreas.hansson@arm.com // a halted state. 21111051Sandreas.hansson@arm.com tc->suspend(Cycles(0)); 21211051Sandreas.hansson@arm.com } 21311284Sandreas.hansson@arm.com} 21411051Sandreas.hansson@arm.com 21511284Sandreas.hansson@arm.comvoid 21611284Sandreas.hansson@arm.comcopyMiscRegs(ThreadContext *src, ThreadContext *dest) 21711284Sandreas.hansson@arm.com{ 21811051Sandreas.hansson@arm.com // This function assumes no side effects other than TLB invalidation 21911051Sandreas.hansson@arm.com // need to be considered while copying state. That will likely not be 22011051Sandreas.hansson@arm.com // true in the future. 22111284Sandreas.hansson@arm.com for (int i = 0; i < NUM_MISCREGS; ++i) { 22211284Sandreas.hansson@arm.com if ( ( i != MISCREG_CR1 && 22311284Sandreas.hansson@arm.com !(i > MISCREG_CR4 && i < MISCREG_CR8) && 22411284Sandreas.hansson@arm.com !(i > MISCREG_CR8 && i <= MISCREG_CR15) ) == false) { 22511051Sandreas.hansson@arm.com continue; 22611051Sandreas.hansson@arm.com } 22711051Sandreas.hansson@arm.com dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); 22811284Sandreas.hansson@arm.com } 22911284Sandreas.hansson@arm.com 23011284Sandreas.hansson@arm.com // The TSC has to be updated with side-effects if the CPUs in a 23111197Sandreas.hansson@arm.com // CPU switch have different frequencies. 23211601Sandreas.hansson@arm.com dest->setMiscReg(MISCREG_TSC, src->readMiscReg(MISCREG_TSC)); 23311601Sandreas.hansson@arm.com 23411601Sandreas.hansson@arm.com dest->getITBPtr()->flushAll(); 23511601Sandreas.hansson@arm.com dest->getDTBPtr()->flushAll(); 23611601Sandreas.hansson@arm.com} 23711601Sandreas.hansson@arm.com 23811601Sandreas.hansson@arm.comvoid 23911601Sandreas.hansson@arm.comcopyRegs(ThreadContext *src, ThreadContext *dest) 24011197Sandreas.hansson@arm.com{ 24111601Sandreas.hansson@arm.com //copy int regs 24211601Sandreas.hansson@arm.com for (int i = 0; i < NumIntRegs; ++i) 24311601Sandreas.hansson@arm.com dest->setIntRegFlat(i, src->readIntRegFlat(i)); 24411601Sandreas.hansson@arm.com //copy float regs 24511601Sandreas.hansson@arm.com for (int i = 0; i < NumFloatRegs; ++i) 24611601Sandreas.hansson@arm.com dest->setFloatRegBitsFlat(i, src->readFloatRegBitsFlat(i)); 24711601Sandreas.hansson@arm.com //copy condition-code regs 24811051Sandreas.hansson@arm.com for (int i = 0; i < NumCCRegs; ++i) 24911051Sandreas.hansson@arm.com dest->setCCRegFlat(i, src->readCCRegFlat(i)); 25011051Sandreas.hansson@arm.com copyMiscRegs(src, dest); 25111051Sandreas.hansson@arm.com dest->pcState(src->pcState()); 25211051Sandreas.hansson@arm.com} 25311284Sandreas.hansson@arm.com 25411284Sandreas.hansson@arm.comvoid 25511051Sandreas.hansson@arm.comskipFunction(ThreadContext *tc) 25611051Sandreas.hansson@arm.com{ 25711051Sandreas.hansson@arm.com panic("Not implemented for x86\n"); 25811051Sandreas.hansson@arm.com} 25911284Sandreas.hansson@arm.com 26011051Sandreas.hansson@arm.comuint64_t 26111051Sandreas.hansson@arm.comgetRFlags(ThreadContext *tc) 26211602Sandreas.hansson@arm.com{ 26311602Sandreas.hansson@arm.com const uint64_t ncc_flags(tc->readMiscRegNoEffect(MISCREG_RFLAGS)); 26411602Sandreas.hansson@arm.com const uint64_t cc_flags(tc->readCCReg(X86ISA::CCREG_ZAPS)); 26511602Sandreas.hansson@arm.com const uint64_t cfof_bits(tc->readCCReg(X86ISA::CCREG_CFOF)); 26611602Sandreas.hansson@arm.com const uint64_t df_bit(tc->readCCReg(X86ISA::CCREG_DF)); 26711602Sandreas.hansson@arm.com // ecf (PSEUDO(3)) & ezf (PSEUDO(4)) are only visible to 26811602Sandreas.hansson@arm.com // microcode, so we can safely ignore them. 26911602Sandreas.hansson@arm.com 27011602Sandreas.hansson@arm.com // Reconstruct the real rflags state, mask out internal flags, and 27111602Sandreas.hansson@arm.com // make sure reserved bits have the expected values. 27211602Sandreas.hansson@arm.com return ((ncc_flags | cc_flags | cfof_bits | df_bit) & 0x3F7FD5) 27311051Sandreas.hansson@arm.com | 0x2; 27411602Sandreas.hansson@arm.com} 27511197Sandreas.hansson@arm.com 27611744Snikos.nikoleris@arm.comvoid 27711744Snikos.nikoleris@arm.comsetRFlags(ThreadContext *tc, uint64_t val) 27811051Sandreas.hansson@arm.com{ 27911051Sandreas.hansson@arm.com tc->setCCReg(X86ISA::CCREG_ZAPS, val & ccFlagMask); 28011051Sandreas.hansson@arm.com tc->setCCReg(X86ISA::CCREG_CFOF, val & cfofMask); 28111051Sandreas.hansson@arm.com tc->setCCReg(X86ISA::CCREG_DF, val & DFBit); 28211051Sandreas.hansson@arm.com 28311051Sandreas.hansson@arm.com // Internal microcode registers (ECF & EZF) 28411051Sandreas.hansson@arm.com tc->setCCReg(X86ISA::CCREG_ECF, 0); 28511051Sandreas.hansson@arm.com tc->setCCReg(X86ISA::CCREG_EZF, 0); 28611051Sandreas.hansson@arm.com 28711051Sandreas.hansson@arm.com // Update the RFLAGS misc reg with whatever didn't go into the 28811051Sandreas.hansson@arm.com // magic registers. 28911051Sandreas.hansson@arm.com tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); 29011051Sandreas.hansson@arm.com} 29111051Sandreas.hansson@arm.com 29211051Sandreas.hansson@arm.comuint8_t 29311051Sandreas.hansson@arm.comconvX87TagsToXTags(uint16_t ftw) 29411051Sandreas.hansson@arm.com{ 29511051Sandreas.hansson@arm.com uint8_t ftwx(0); 29611051Sandreas.hansson@arm.com for (int i = 0; i < 8; ++i) { 29711051Sandreas.hansson@arm.com // Extract the tag for the current element on the FP stack 29811744Snikos.nikoleris@arm.com const unsigned tag((ftw >> (2 * i)) & 0x3); 29911051Sandreas.hansson@arm.com 30011051Sandreas.hansson@arm.com /* 30111744Snikos.nikoleris@arm.com * Check the type of the current FP element. Valid values are: 30211051Sandreas.hansson@arm.com * 0 == Valid 30311051Sandreas.hansson@arm.com * 1 == Zero 30411051Sandreas.hansson@arm.com * 2 == Special (Nan, unsupported, infinity, denormal) 30511051Sandreas.hansson@arm.com * 3 == Empty 30611199Sandreas.hansson@arm.com */ 30711051Sandreas.hansson@arm.com // The xsave version of the tag word only keeps track of 30811051Sandreas.hansson@arm.com // whether the element is empty or not. Set the corresponding 30911051Sandreas.hansson@arm.com // bit in the ftwx if it's not empty, 31011867Snikos.nikoleris@arm.com if (tag != 0x3) 31111051Sandreas.hansson@arm.com ftwx |= 1 << i; 31211051Sandreas.hansson@arm.com } 31311484Snikos.nikoleris@arm.com 31411051Sandreas.hansson@arm.com return ftwx; 31511051Sandreas.hansson@arm.com} 31611051Sandreas.hansson@arm.com 31711051Sandreas.hansson@arm.comuint16_t 31811051Sandreas.hansson@arm.comconvX87XTagsToTags(uint8_t ftwx) 31911051Sandreas.hansson@arm.com{ 32011051Sandreas.hansson@arm.com uint16_t ftw(0); 32111870Snikos.nikoleris@arm.com for (int i = 0; i < 8; ++i) { 32211051Sandreas.hansson@arm.com const unsigned xtag(((ftwx >> i) & 0x1)); 32311744Snikos.nikoleris@arm.com 32411051Sandreas.hansson@arm.com // The xtag for an x87 stack position is 0 for empty stack positions. 32511051Sandreas.hansson@arm.com if (!xtag) { 32612349Snikos.nikoleris@arm.com // Set the tag word to 3 (empty) for the current element. 32712349Snikos.nikoleris@arm.com ftw |= 0x3 << (2 * i); 32812349Snikos.nikoleris@arm.com } else { 32912349Snikos.nikoleris@arm.com // TODO: We currently assume that non-empty elements are 33012349Snikos.nikoleris@arm.com // valid (0x0), but we should ideally reconstruct the full 33112349Snikos.nikoleris@arm.com // state (valid/zero/special). 33212349Snikos.nikoleris@arm.com } 33312349Snikos.nikoleris@arm.com } 33412349Snikos.nikoleris@arm.com 33511051Sandreas.hansson@arm.com return ftw; 33611199Sandreas.hansson@arm.com} 33711051Sandreas.hansson@arm.com 33811051Sandreas.hansson@arm.comuint16_t 33911051Sandreas.hansson@arm.comgenX87Tags(uint16_t ftw, uint8_t top, int8_t spm) 34011051Sandreas.hansson@arm.com{ 34111051Sandreas.hansson@arm.com const uint8_t new_top((top + spm + 8) % 8); 34211051Sandreas.hansson@arm.com 34311051Sandreas.hansson@arm.com if (spm > 0) { 34411051Sandreas.hansson@arm.com // Removing elements from the stack. Flag the elements as empty. 34511375Sandreas.hansson@arm.com for (int i = top; i != new_top; i = (i + 1 + 8) % 8) 34611375Sandreas.hansson@arm.com ftw |= 0x3 << (2 * i); 34711375Sandreas.hansson@arm.com } else if (spm < 0) { 34811199Sandreas.hansson@arm.com // Adding elements to the stack. Flag the new elements as 34911199Sandreas.hansson@arm.com // valid. We should ideally decode them and "do the right 35011199Sandreas.hansson@arm.com // thing". 35111199Sandreas.hansson@arm.com for (int i = new_top; i != top; i = (i + 1 + 8) % 8) 35211199Sandreas.hansson@arm.com ftw &= ~(0x3 << (2 * i)); 35311199Sandreas.hansson@arm.com } 35411199Sandreas.hansson@arm.com 35511199Sandreas.hansson@arm.com return ftw; 35611199Sandreas.hansson@arm.com} 35711199Sandreas.hansson@arm.com 35811199Sandreas.hansson@arm.comdouble 35911199Sandreas.hansson@arm.comloadFloat80(const void *_mem) 36011199Sandreas.hansson@arm.com{ 36111199Sandreas.hansson@arm.com const fp80_t *fp80((const fp80_t *)_mem); 36211199Sandreas.hansson@arm.com 36311199Sandreas.hansson@arm.com return fp80_cvtd(*fp80); 36411199Sandreas.hansson@arm.com} 36511199Sandreas.hansson@arm.com 36611199Sandreas.hansson@arm.comvoid 36711199Sandreas.hansson@arm.comstoreFloat80(void *_mem, double value) 36811375Sandreas.hansson@arm.com{ 36911199Sandreas.hansson@arm.com fp80_t *fp80((fp80_t *)_mem); 37011199Sandreas.hansson@arm.com 37111051Sandreas.hansson@arm.com *fp80 = fp80_cvfd(value); 37211051Sandreas.hansson@arm.com} 37311051Sandreas.hansson@arm.com 37411051Sandreas.hansson@arm.com} // namespace X86_ISA 37511051Sandreas.hansson@arm.com