isa.cc revision 6336:25635830e33c
12686Sksewell@umich.edu/* 22100SN/A * Copyright (c) 2009 The Regents of The University of Michigan 32022SN/A * All rights reserved. 42022SN/A * 52043SN/A * Redistribution and use in source and binary forms, with or without 62024SN/A * modification, are permitted provided that the following conditions are 72024SN/A * met: redistributions of source code must retain the above copyright 82043SN/A * notice, this list of conditions and the following disclaimer; 92686Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 102024SN/A * notice, this list of conditions and the following disclaimer in the 112022SN/A * documentation and/or other materials provided with the distribution; 122083SN/A * neither the name of the copyright holders nor the names of its 132686Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 142101SN/A * this software without specific prior written permission. 152043SN/A * 162043SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172101SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182101SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192686Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202686Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212101SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222101SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232101SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242046SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252686Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262686Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272686Sksewell@umich.edu * 282470SN/A * Authors: Gabe Black 292686Sksewell@umich.edu */ 302686Sksewell@umich.edu 312686Sksewell@umich.edu#include "arch/x86/floatregs.hh" 322686Sksewell@umich.edu#include "arch/x86/isa.hh" 332686Sksewell@umich.edu#include "arch/x86/tlb.hh" 342686Sksewell@umich.edu#include "cpu/base.hh" 352470SN/A#include "cpu/thread_context.hh" 362241SN/A#include "sim/serialize.hh" 372101SN/A 382495SN/Anamespace X86ISA 392495SN/A{ 402495SN/A 412101SN/Avoid 422495SN/AISA::updateHandyM5Reg(Efer efer, CR0 cr0, 432495SN/A SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags) 442495SN/A{ 452101SN/A HandyM5Reg m5reg; 462101SN/A if (efer.lma) { 472495SN/A m5reg.mode = LongMode; 482495SN/A if (csAttr.longMode) 492495SN/A m5reg.submode = SixtyFourBitMode; 502495SN/A else 512495SN/A m5reg.submode = CompatabilityMode; 522495SN/A } else { 532495SN/A m5reg.mode = LegacyMode; 542495SN/A if (cr0.pe) { 552495SN/A if (rflags.vm) 562495SN/A m5reg.submode = Virtual8086Mode; 572495SN/A else 582495SN/A m5reg.submode = ProtectedMode; 592495SN/A } else { 602101SN/A m5reg.submode = RealMode; 612101SN/A } 622101SN/A } 632101SN/A m5reg.cpl = csAttr.dpl; 642101SN/A m5reg.paging = cr0.pg; 652101SN/A m5reg.prot = cr0.pe; 662101SN/A 672101SN/A // Compute the default and alternate operand size. 682101SN/A if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) { 692101SN/A m5reg.defOp = 2; 702495SN/A m5reg.altOp = 1; 712495SN/A } else { 722495SN/A m5reg.defOp = 1; 732495SN/A m5reg.altOp = 2; 742495SN/A } 752495SN/A 762495SN/A // Compute the default and alternate address size. 772495SN/A if (m5reg.submode == SixtyFourBitMode) { 782495SN/A m5reg.defAddr = 3; 792495SN/A m5reg.altAddr = 2; 802495SN/A } else if (csAttr.defaultSize) { 812495SN/A m5reg.defAddr = 2; 822495SN/A m5reg.altAddr = 1; 832495SN/A } else { 842495SN/A m5reg.defAddr = 1; 852043SN/A m5reg.altAddr = 2; 862043SN/A } 872025SN/A 882043SN/A // Compute the stack size 892686Sksewell@umich.edu if (m5reg.submode == SixtyFourBitMode) { 902686Sksewell@umich.edu m5reg.stack = 3; 912123SN/A } else if (ssAttr.defaultSize) { 922101SN/A m5reg.stack = 2; 932686Sksewell@umich.edu } else { 942686Sksewell@umich.edu m5reg.stack = 1; 952101SN/A } 962042SN/A 972101SN/A regVal[MISCREG_M5_REG] = m5reg; 982686Sksewell@umich.edu} 992686Sksewell@umich.edu 1002686Sksewell@umich.eduvoid 1012686Sksewell@umich.eduISA::clear() 1022101SN/A{ 1032101SN/A // Blank everything. 0 might not be an appropriate value for some things, 1042042SN/A // but it is for most. 1052101SN/A memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); 1062686Sksewell@umich.edu regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16); 1072686Sksewell@umich.edu regVal[MISCREG_DR7] = 1 << 10; 1082686Sksewell@umich.edu} 1092686Sksewell@umich.edu 1102101SN/AMiscReg 1112083SN/AISA::readMiscRegNoEffect(int miscReg) 1122686Sksewell@umich.edu{ 1132686Sksewell@umich.edu // Make sure we're not dealing with an illegal control register. 1142101SN/A // Instructions should filter out these indexes, and nothing else should 1152043SN/A // attempt to read them directly. 1162025SN/A assert( miscReg != MISCREG_CR1 && 1172043SN/A !(miscReg > MISCREG_CR4 && 1182686Sksewell@umich.edu miscReg < MISCREG_CR8) && 1192616SN/A !(miscReg > MISCREG_CR8 && 1202616SN/A miscReg <= MISCREG_CR15)); 1212616SN/A 1222616SN/A return regVal[miscReg]; 1232101SN/A} 1242083SN/A 1252025SN/AMiscReg 1262043SN/AISA::readMiscReg(int miscReg, ThreadContext * tc) 1272686Sksewell@umich.edu{ 1282686Sksewell@umich.edu if (miscReg == MISCREG_TSC) { 1292686Sksewell@umich.edu return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); 1302686Sksewell@umich.edu } 1312025SN/A return readMiscRegNoEffect(miscReg); 1322686Sksewell@umich.edu} 1332101SN/A 1342616SN/Avoid 1352616SN/AISA::setMiscRegNoEffect(int miscReg, MiscReg val) 1362101SN/A{ 1372101SN/A // Make sure we're not dealing with an illegal control register. 1382616SN/A // Instructions should filter out these indexes, and nothing else should 1392616SN/A // attempt to write to them directly. 1402101SN/A assert( miscReg != MISCREG_CR1 && 1412101SN/A !(miscReg > MISCREG_CR4 && 1422084SN/A miscReg < MISCREG_CR8) && 1432025SN/A !(miscReg > MISCREG_CR8 && 1442495SN/A miscReg <= MISCREG_CR15)); 1452495SN/A regVal[miscReg] = val; 1462495SN/A} 1472616SN/A 1482495SN/Avoid 1492616SN/AISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc) 1502495SN/A{ 1512495SN/A MiscReg newVal = val; 1522495SN/A switch(miscReg) 1532495SN/A { 1542495SN/A case MISCREG_CR0: 1552495SN/A { 1562101SN/A CR0 toggled = regVal[miscReg] ^ val; 1572043SN/A CR0 newCR0 = val; 1582025SN/A Efer efer = regVal[MISCREG_EFER]; 1592495SN/A if (toggled.pg && efer.lme) { 1602495SN/A if (newCR0.pg) { 1612495SN/A //Turning on long mode 1622495SN/A efer.lma = 1; 1632495SN/A regVal[MISCREG_EFER] = efer; 1642495SN/A } else { 1652101SN/A //Turning off long mode 1662084SN/A efer.lma = 0; 1672024SN/A regVal[MISCREG_EFER] = efer; 1682043SN/A } 1692239SN/A } 1702239SN/A if (toggled.pg) { 1712101SN/A tc->getITBPtr()->invalidateAll(); 1722101SN/A tc->getDTBPtr()->invalidateAll(); 1732101SN/A } 1742101SN/A //This must always be 1. 1752101SN/A newCR0.et = 1; 1762101SN/A newVal = newCR0; 1772043SN/A updateHandyM5Reg(regVal[MISCREG_EFER], 1782043SN/A newCR0, 1792025SN/A regVal[MISCREG_CS_ATTR], 1802043SN/A regVal[MISCREG_SS_ATTR], 1812043SN/A regVal[MISCREG_RFLAGS]); 1822101SN/A } 1832101SN/A break; 1842101SN/A case MISCREG_CR2: 1852686Sksewell@umich.edu break; 1862686Sksewell@umich.edu case MISCREG_CR3: 1872101SN/A tc->getITBPtr()->invalidateNonGlobal(); 1882043SN/A tc->getDTBPtr()->invalidateNonGlobal(); 1892025SN/A break; 1902043SN/A case MISCREG_CR4: 1912239SN/A { 1922101SN/A CR4 toggled = regVal[miscReg] ^ val; 1932104SN/A if (toggled.pae || toggled.pse || toggled.pge) { 1942101SN/A tc->getITBPtr()->invalidateAll(); 1952101SN/A tc->getDTBPtr()->invalidateAll(); 1962101SN/A } 1972101SN/A } 1982101SN/A break; 1992043SN/A case MISCREG_CR8: 2002043SN/A break; 2012043SN/A case MISCREG_CS_ATTR: 2022101SN/A { 2032686Sksewell@umich.edu SegAttr toggled = regVal[miscReg] ^ val; 2042686Sksewell@umich.edu SegAttr newCSAttr = val; 2052686Sksewell@umich.edu if (toggled.longMode) { 2062686Sksewell@umich.edu if (newCSAttr.longMode) { 2072686Sksewell@umich.edu regVal[MISCREG_ES_EFF_BASE] = 0; 2082686Sksewell@umich.edu regVal[MISCREG_CS_EFF_BASE] = 0; 2092686Sksewell@umich.edu regVal[MISCREG_SS_EFF_BASE] = 0; 2102101SN/A regVal[MISCREG_DS_EFF_BASE] = 0; 2112043SN/A } else { 2122043SN/A regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; 2132043SN/A regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; 2142101SN/A regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; 2152101SN/A regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; 2162101SN/A } 2172043SN/A } 2182043SN/A updateHandyM5Reg(regVal[MISCREG_EFER], 2192043SN/A regVal[MISCREG_CR0], 2202123SN/A newCSAttr, 2212239SN/A regVal[MISCREG_SS_ATTR], 2222686Sksewell@umich.edu regVal[MISCREG_RFLAGS]); 2232686Sksewell@umich.edu } 2242043SN/A break; 2252043SN/A case MISCREG_SS_ATTR: 2262100SN/A updateHandyM5Reg(regVal[MISCREG_EFER], 2272686Sksewell@umich.edu regVal[MISCREG_CR0], 2282686Sksewell@umich.edu regVal[MISCREG_CS_ATTR], 2292686Sksewell@umich.edu val, 2302686Sksewell@umich.edu regVal[MISCREG_RFLAGS]); 2312239SN/A break; 2322686Sksewell@umich.edu // These segments always actually use their bases, or in other words 2332686Sksewell@umich.edu // their effective bases must stay equal to their actual bases. 2342043SN/A case MISCREG_FS_BASE: 2352084SN/A case MISCREG_GS_BASE: 2362024SN/A case MISCREG_HS_BASE: 2372101SN/A case MISCREG_TSL_BASE: 2382686Sksewell@umich.edu case MISCREG_TSG_BASE: 2392239SN/A case MISCREG_TR_BASE: 2402239SN/A case MISCREG_IDTR_BASE: 2412239SN/A regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val; 2422495SN/A break; 2432495SN/A // These segments ignore their bases in 64 bit mode. 2442495SN/A // their effective bases must stay equal to their actual bases. 2452495SN/A case MISCREG_ES_BASE: 2462495SN/A case MISCREG_CS_BASE: 2472495SN/A case MISCREG_SS_BASE: 2482495SN/A case MISCREG_DS_BASE: 2492495SN/A { 2502084SN/A Efer efer = regVal[MISCREG_EFER]; 2512084SN/A SegAttr csAttr = regVal[MISCREG_CS_ATTR]; 2522024SN/A if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode. 2532101SN/A regVal[MISCREG_SEG_EFF_BASE(miscReg - 2542101SN/A MISCREG_SEG_BASE_BASE)] = val; 2552101SN/A } 2562101SN/A break; 2572686Sksewell@umich.edu case MISCREG_TSC: 2582686Sksewell@umich.edu regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); 2592686Sksewell@umich.edu return; 2602686Sksewell@umich.edu case MISCREG_DR0: 2612052SN/A case MISCREG_DR1: 2622686Sksewell@umich.edu case MISCREG_DR2: 2632686Sksewell@umich.edu case MISCREG_DR3: 2642686Sksewell@umich.edu /* These should eventually set up breakpoints. */ 2652101SN/A break; 2662101SN/A case MISCREG_DR4: 2672686Sksewell@umich.edu miscReg = MISCREG_DR6; 2682686Sksewell@umich.edu /* Fall through to have the same effects as DR6. */ 2692101SN/A case MISCREG_DR6: 2702101SN/A { 2712686Sksewell@umich.edu DR6 dr6 = regVal[MISCREG_DR6]; 2722686Sksewell@umich.edu DR6 newDR6 = val; 2732686Sksewell@umich.edu dr6.b0 = newDR6.b0; 2742686Sksewell@umich.edu dr6.b1 = newDR6.b1; 2752686Sksewell@umich.edu dr6.b2 = newDR6.b2; 2762686Sksewell@umich.edu dr6.b3 = newDR6.b3; 2772101SN/A dr6.bd = newDR6.bd; 2782101SN/A dr6.bs = newDR6.bs; 2792686Sksewell@umich.edu dr6.bt = newDR6.bt; 2802027SN/A newVal = dr6; 2812686Sksewell@umich.edu } 2822686Sksewell@umich.edu break; 2832686Sksewell@umich.edu case MISCREG_DR5: 2842101SN/A miscReg = MISCREG_DR7; 2852101SN/A /* Fall through to have the same effects as DR7. */ 2862101SN/A case MISCREG_DR7: 2872101SN/A { 2882101SN/A DR7 dr7 = regVal[MISCREG_DR7]; 2892686Sksewell@umich.edu DR7 newDR7 = val; 2902686Sksewell@umich.edu dr7.l0 = newDR7.l0; 2912686Sksewell@umich.edu dr7.g0 = newDR7.g0; 2922686Sksewell@umich.edu if (dr7.l0 || dr7.g0) { 2932686Sksewell@umich.edu panic("Debug register breakpoints not implemented.\n"); 2942101SN/A } else { 2952101SN/A /* Disable breakpoint 0. */ 2962101SN/A } 2972101SN/A dr7.l1 = newDR7.l1; 2982101SN/A dr7.g1 = newDR7.g1; 2992101SN/A if (dr7.l1 || dr7.g1) { 3002043SN/A panic("Debug register breakpoints not implemented.\n"); 3012027SN/A } else { 3022101SN/A /* Disable breakpoint 1. */ 3032101SN/A } 3042041SN/A dr7.l2 = newDR7.l2; 3052101SN/A dr7.g2 = newDR7.g2; 3062101SN/A if (dr7.l2 || dr7.g2) { 3072686Sksewell@umich.edu panic("Debug register breakpoints not implemented.\n"); 3082573SN/A } else { 3092495SN/A /* Disable breakpoint 2. */ 3102495SN/A } 3112573SN/A dr7.l3 = newDR7.l3; 3122573SN/A dr7.g3 = newDR7.g3; 3132573SN/A if (dr7.l3 || dr7.g3) { 3142616SN/A panic("Debug register breakpoints not implemented.\n"); 3152573SN/A } else { 3162573SN/A /* Disable breakpoint 3. */ 3172616SN/A } 3182573SN/A dr7.gd = newDR7.gd; 3192573SN/A dr7.rw0 = newDR7.rw0; 3202616SN/A dr7.len0 = newDR7.len0; 3212573SN/A dr7.rw1 = newDR7.rw1; 3222573SN/A dr7.len1 = newDR7.len1; 3232616SN/A dr7.rw2 = newDR7.rw2; 3242573SN/A dr7.len2 = newDR7.len2; 3252573SN/A dr7.rw3 = newDR7.rw3; 3262616SN/A dr7.len3 = newDR7.len3; 3272573SN/A } 3282573SN/A break; 3292686Sksewell@umich.edu case MISCREG_M5_REG: 3302573SN/A // Writing anything to the m5reg with side effects makes it update 3312573SN/A // based on the current values of the relevant registers. The actual 3322573SN/A // value written is discarded. 3332686Sksewell@umich.edu updateHandyM5Reg(regVal[MISCREG_EFER], 3342686Sksewell@umich.edu regVal[MISCREG_CR0], 3352686Sksewell@umich.edu regVal[MISCREG_CS_ATTR], 3362686Sksewell@umich.edu regVal[MISCREG_SS_ATTR], 3372573SN/A regVal[MISCREG_RFLAGS]); 3382573SN/A return; 3392573SN/A default: 3402573SN/A break; 3412616SN/A } 3422616SN/A setMiscRegNoEffect(miscReg, newVal); 3432616SN/A} 3442573SN/A 3452573SN/Avoid 3462573SN/AISA::serialize(EventManager *em, std::ostream & os) 3472616SN/A{ 3482573SN/A SERIALIZE_ARRAY(regVal, NumMiscRegs); 3492616SN/A} 3502573SN/A 3512616SN/Avoid 3522573SN/AISA::unserialize(EventManager *em, Checkpoint * cp, 3532573SN/A const std::string & section) 3542573SN/A{ 3552616SN/A UNSERIALIZE_ARRAY(regVal, NumMiscRegs); 3562573SN/A} 3572616SN/A 3582573SN/Aint 3592616SN/AISA::flattenIntIndex(int reg) 3602573SN/A{ 3612573SN/A //If we need to fold over the index to match byte semantics, do that. 3622573SN/A //Otherwise, just strip off any extra bits and pass it through. 3632573SN/A if (reg & (1 << 6)) 3642616SN/A return (reg & (~(1 << 6) - 0x4)); 3652573SN/A else 3662573SN/A return (reg & ~(1 << 6)); 3672573SN/A} 3682495SN/A 3692616SN/Aint 3702495SN/AISA::flattenFloatIndex(int reg) 3712495SN/A{ 3722686Sksewell@umich.edu if (reg >= NUM_FLOATREGS) { 3732686Sksewell@umich.edu int top = readMiscRegNoEffect(MISCREG_X87_TOP); 3742686Sksewell@umich.edu reg = FLOATREG_STACK(reg - NUM_FLOATREGS, top); 3752686Sksewell@umich.edu } 3762686Sksewell@umich.edu return reg; 3772686Sksewell@umich.edu} 3782686Sksewell@umich.edu 3792101SN/A} 3802101SN/A