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