isa.cc revision 12406
12SN/A/*
21762SN/A * Copyright (c) 2009 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Gabe Black
292SN/A */
302SN/A
312439SN/A#include "arch/x86/isa.hh"
322984Sgblack@eecs.umich.edu
33146SN/A#include "arch/x86/decoder.hh"
34146SN/A#include "arch/x86/tlb.hh"
35146SN/A#include "cpu/base.hh"
36146SN/A#include "cpu/thread_context.hh"
37146SN/A#include "params/X86ISA.hh"
38146SN/A#include "sim/serialize.hh"
391717SN/A
40146SN/Anamespace X86ISA
411717SN/A{
42146SN/A
431977SN/Avoid
442623SN/AISA::updateHandyM5Reg(Efer efer, CR0 cr0,
452683Sktlim@umich.edu                      SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags,
461717SN/A                      ThreadContext *tc)
47146SN/A{
482683Sktlim@umich.edu    HandyM5Reg m5reg = 0;
493348Sbinkertn@umich.edu    if (efer.lma) {
502683Sktlim@umich.edu        m5reg.mode = LongMode;
512036SN/A        if (csAttr.longMode)
52146SN/A            m5reg.submode = SixtyFourBitMode;
5356SN/A        else
5456SN/A            m5reg.submode = CompatabilityMode;
5556SN/A    } else {
56695SN/A        m5reg.mode = LegacyMode;
572901Ssaidi@eecs.umich.edu        if (cr0.pe) {
582SN/A            if (rflags.vm)
591858SN/A                m5reg.submode = Virtual8086Mode;
603565Sgblack@eecs.umich.edu            else
613565Sgblack@eecs.umich.edu                m5reg.submode = ProtectedMode;
622171SN/A        } else {
632170SN/A            m5reg.submode = RealMode;
643562Sgblack@eecs.umich.edu        }
65146SN/A    }
662462SN/A    m5reg.cpl = csAttr.dpl;
67146SN/A    m5reg.paging = cr0.pg;
682SN/A    m5reg.prot = cr0.pe;
692SN/A
702449SN/A    // Compute the default and alternate operand size.
711355SN/A    if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) {
722623SN/A        m5reg.defOp = 2;
733402Sktlim@umich.edu        m5reg.altOp = 1;
74224SN/A    } else {
751858SN/A        m5reg.defOp = 1;
762683Sktlim@umich.edu        m5reg.altOp = 2;
772420SN/A    }
782683Sktlim@umich.edu
793402Sktlim@umich.edu    // Compute the default and alternate address size.
802420SN/A    if (m5reg.submode == SixtyFourBitMode) {
812SN/A        m5reg.defAddr = 3;
822683Sktlim@umich.edu        m5reg.altAddr = 2;
832672Sktlim@umich.edu    } else if (csAttr.defaultSize) {
842683Sktlim@umich.edu        m5reg.defAddr = 2;
852SN/A        m5reg.altAddr = 1;
862SN/A    } else {
87334SN/A        m5reg.defAddr = 1;
88140SN/A        m5reg.altAddr = 2;
89334SN/A    }
902SN/A
912SN/A    // Compute the stack size
922SN/A    if (m5reg.submode == SixtyFourBitMode) {
932680Sktlim@umich.edu        m5reg.stack = 3;
942SN/A    } else if (ssAttr.defaultSize) {
952SN/A        m5reg.stack = 2;
962623SN/A    } else {
972SN/A        m5reg.stack = 1;
982SN/A    }
992SN/A
100180SN/A    regVal[MISCREG_M5_REG] = m5reg;
1012623SN/A    if (tc)
102393SN/A        tc->getDecoderPtr()->setM5Reg(m5reg);
103393SN/A}
104393SN/A
105393SN/Avoid
106384SN/AISA::clear()
107384SN/A{
108393SN/A    // Blank everything. 0 might not be an appropriate value for some things,
1092623SN/A    // but it is for most.
110393SN/A    memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
111393SN/A    regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16);
112393SN/A    regVal[MISCREG_DR7] = 1 << 10;
113393SN/A}
114384SN/A
115189SN/AISA::ISA(Params *p)
116189SN/A    : SimObject(p)
1172623SN/A{
1182SN/A    clear();
119729SN/A}
120334SN/A
1212SN/Aconst X86ISAParams *
1222SN/AISA::params() const
1232SN/A{
1242SN/A    return dynamic_cast<const Params *>(_params);
1252SN/A}
1262SN/A
1272SN/AMiscReg
1282SN/AISA::readMiscRegNoEffect(int miscReg) const
1292SN/A{
1302SN/A    // Make sure we're not dealing with an illegal control register.
1312SN/A    // Instructions should filter out these indexes, and nothing else should
1322SN/A    // attempt to read them directly.
1331001SN/A    assert(isValidMiscReg(miscReg));
1341001SN/A
1351001SN/A    return regVal[miscReg];
1361001SN/A}
1371001SN/A
1382SN/AMiscReg
1392SN/AISA::readMiscReg(int miscReg, ThreadContext * tc)
1402SN/A{
1412SN/A    if (miscReg == MISCREG_TSC) {
1422SN/A        return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle();
1432SN/A    }
1442SN/A
1452SN/A    if (miscReg == MISCREG_FSW) {
1462SN/A        MiscReg fsw = regVal[MISCREG_FSW];
1472SN/A        MiscReg top = regVal[MISCREG_X87_TOP];
1482SN/A        return insertBits(fsw, 11, 13, top);
1492SN/A    }
1502SN/A
1512SN/A    return readMiscRegNoEffect(miscReg);
1522SN/A}
1532SN/A
1542SN/Avoid
1552390SN/AISA::setMiscRegNoEffect(int miscReg, MiscReg val)
1562390SN/A{
1572390SN/A    // Make sure we're not dealing with an illegal control register.
1582390SN/A    // Instructions should filter out these indexes, and nothing else should
1592390SN/A    // attempt to write to them directly.
1602390SN/A    assert(isValidMiscReg(miscReg));
1612390SN/A
1622390SN/A    HandyM5Reg m5Reg = regVal[MISCREG_M5_REG];
1632390SN/A    int reg_width = 64;
1642390SN/A    switch (miscReg) {
1652390SN/A      case MISCREG_X87_TOP:
1662390SN/A        reg_width = 3;
167385SN/A        break;
1682SN/A      case MISCREG_FTW:
1692SN/A        reg_width = 8;
1702SN/A        break;
1712623SN/A      case MISCREG_FSW:
172334SN/A      case MISCREG_FCW:
1732361SN/A      case MISCREG_FOP:
1742623SN/A        reg_width = 16;
175334SN/A        break;
176334SN/A      case MISCREG_MXCSR:
177334SN/A        reg_width = 32;
1782623SN/A        break;
1792SN/A      case MISCREG_FISEG:
180921SN/A      case MISCREG_FOSEG:
1812915Sktlim@umich.edu        if (m5Reg.submode != SixtyFourBitMode)
1822915Sktlim@umich.edu            reg_width = 16;
1832683Sktlim@umich.edu        break;
1842SN/A      case MISCREG_FIOFF:
1852SN/A      case MISCREG_FOOFF:
1862SN/A        if (m5Reg.submode != SixtyFourBitMode)
1872623SN/A            reg_width = 32;
1882SN/A        break;
189921SN/A      default:
1902915Sktlim@umich.edu        break;
1912915Sktlim@umich.edu    }
1922SN/A
1932SN/A    regVal[miscReg] = val & mask(reg_width);
1942SN/A}
1952SN/A
1962SN/Avoid
1972SN/AISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
1982SN/A{
199595SN/A    MiscReg newVal = val;
2002623SN/A    switch(miscReg)
201595SN/A    {
2022390SN/A      case MISCREG_CR0:
2031080SN/A        {
2041080SN/A            CR0 toggled = regVal[miscReg] ^ val;
2051080SN/A            CR0 newCR0 = val;
2061080SN/A            Efer efer = regVal[MISCREG_EFER];
2071080SN/A            if (toggled.pg && efer.lme) {
2081080SN/A                if (newCR0.pg) {
2091080SN/A                    //Turning on long mode
2101121SN/A                    efer.lma = 1;
2112107SN/A                    regVal[MISCREG_EFER] = efer;
2121089SN/A                } else {
2131089SN/A                    //Turning off long mode
2141080SN/A                    efer.lma = 0;
2151080SN/A                    regVal[MISCREG_EFER] = efer;
2161080SN/A                }
2171080SN/A            }
218595SN/A            if (toggled.pg) {
2192623SN/A                dynamic_cast<TLB *>(tc->getITBPtr())->flushAll();
2202683Sktlim@umich.edu                dynamic_cast<TLB *>(tc->getDTBPtr())->flushAll();
221595SN/A            }
2222090SN/A            //This must always be 1.
2232683Sktlim@umich.edu            newCR0.et = 1;
2242683Sktlim@umich.edu            newVal = newCR0;
225595SN/A            updateHandyM5Reg(regVal[MISCREG_EFER],
2262205SN/A                             newCR0,
2272205SN/A                             regVal[MISCREG_CS_ATTR],
2282683Sktlim@umich.edu                             regVal[MISCREG_SS_ATTR],
2292683Sktlim@umich.edu                             regVal[MISCREG_RFLAGS],
230595SN/A                             tc);
231595SN/A        }
2322390SN/A        break;
2332423SN/A      case MISCREG_CR2:
2342390SN/A        break;
235595SN/A      case MISCREG_CR3:
236595SN/A        dynamic_cast<TLB *>(tc->getITBPtr())->flushNonGlobal();
237595SN/A        dynamic_cast<TLB *>(tc->getDTBPtr())->flushNonGlobal();
2382623SN/A        break;
239595SN/A      case MISCREG_CR4:
2402390SN/A        {
2411080SN/A            CR4 toggled = regVal[miscReg] ^ val;
242595SN/A            if (toggled.pae || toggled.pse || toggled.pge) {
2431080SN/A                dynamic_cast<TLB *>(tc->getITBPtr())->flushAll();
2441080SN/A                dynamic_cast<TLB *>(tc->getDTBPtr())->flushAll();
245595SN/A            }
2462683Sktlim@umich.edu        }
2471080SN/A        break;
2481080SN/A      case MISCREG_CR8:
2491080SN/A        break;
2501121SN/A      case MISCREG_CS_ATTR:
2512107SN/A        {
2521089SN/A            SegAttr toggled = regVal[miscReg] ^ val;
2531080SN/A            SegAttr newCSAttr = val;
2541089SN/A            if (toggled.longMode) {
2551080SN/A                if (newCSAttr.longMode) {
2561080SN/A                    regVal[MISCREG_ES_EFF_BASE] = 0;
2571080SN/A                    regVal[MISCREG_CS_EFF_BASE] = 0;
258595SN/A                    regVal[MISCREG_SS_EFF_BASE] = 0;
2592683Sktlim@umich.edu                    regVal[MISCREG_DS_EFF_BASE] = 0;
2601080SN/A                } else {
2612090SN/A                    regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
2621080SN/A                    regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
263595SN/A                    regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
2642683Sktlim@umich.edu                    regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
2652683Sktlim@umich.edu                }
266595SN/A            }
2672683Sktlim@umich.edu            updateHandyM5Reg(regVal[MISCREG_EFER],
2681098SN/A                             regVal[MISCREG_CR0],
2691098SN/A                             newCSAttr,
2701098SN/A                             regVal[MISCREG_SS_ATTR],
2712683Sktlim@umich.edu                             regVal[MISCREG_RFLAGS],
2721098SN/A                             tc);
2731098SN/A        }
2741098SN/A        break;
2752012SN/A      case MISCREG_SS_ATTR:
2761098SN/A        updateHandyM5Reg(regVal[MISCREG_EFER],
2771098SN/A                         regVal[MISCREG_CR0],
278595SN/A                         regVal[MISCREG_CS_ATTR],
2792205SN/A                         val,
2802205SN/A                         regVal[MISCREG_RFLAGS],
2812205SN/A                         tc);
282595SN/A        break;
2832390SN/A      // These segments always actually use their bases, or in other words
2842420SN/A      // their effective bases must stay equal to their actual bases.
2852423SN/A      case MISCREG_FS_BASE:
2862390SN/A      case MISCREG_GS_BASE:
287595SN/A      case MISCREG_HS_BASE:
288595SN/A      case MISCREG_TSL_BASE:
2891858SN/A      case MISCREG_TSG_BASE:
2902SN/A      case MISCREG_TR_BASE:
2912623SN/A      case MISCREG_IDTR_BASE:
2922SN/A        regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val;
2932680Sktlim@umich.edu        break;
2942SN/A      // These segments ignore their bases in 64 bit mode.
2952SN/A      // their effective bases must stay equal to their actual bases.
2962SN/A      case MISCREG_ES_BASE:
2971858SN/A      case MISCREG_CS_BASE:
2982SN/A      case MISCREG_SS_BASE:
2992623SN/A      case MISCREG_DS_BASE:
3002SN/A        {
3012SN/A            Efer efer = regVal[MISCREG_EFER];
3022SN/A            SegAttr csAttr = regVal[MISCREG_CS_ATTR];
3032683Sktlim@umich.edu            if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode.
3042SN/A                regVal[MISCREG_SEG_EFF_BASE(miscReg -
3052683Sktlim@umich.edu                        MISCREG_SEG_BASE_BASE)] = val;
3062SN/A        }
3072SN/A        break;
3082SN/A      case MISCREG_TSC:
3092SN/A        regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle();
3102SN/A        return;
3112623SN/A      case MISCREG_DR0:
3122SN/A      case MISCREG_DR1:
3131858SN/A      case MISCREG_DR2:
3143521Sgblack@eecs.umich.edu      case MISCREG_DR3:
3153520Sgblack@eecs.umich.edu        /* These should eventually set up breakpoints. */
3162SN/A        break;
3173520Sgblack@eecs.umich.edu      case MISCREG_DR4:
3183633Sktlim@umich.edu        miscReg = MISCREG_DR6;
3193521Sgblack@eecs.umich.edu        M5_FALLTHROUGH;
3203520Sgblack@eecs.umich.edu      case MISCREG_DR6:
3212SN/A        {
3222SN/A            DR6 dr6 = regVal[MISCREG_DR6];
3232SN/A            DR6 newDR6 = val;
3242623SN/A            dr6.b0 = newDR6.b0;
3252SN/A            dr6.b1 = newDR6.b1;
3262623SN/A            dr6.b2 = newDR6.b2;
3272623SN/A            dr6.b3 = newDR6.b3;
3282662Sstever@eecs.umich.edu            dr6.bd = newDR6.bd;
3292623SN/A            dr6.bs = newDR6.bs;
3302623SN/A            dr6.bt = newDR6.bt;
3313093Sksewell@umich.edu            newVal = dr6;
3323093Sksewell@umich.edu        }
3333093Sksewell@umich.edu        break;
3343093Sksewell@umich.edu      case MISCREG_DR5:
3352741Sksewell@umich.edu        miscReg = MISCREG_DR7;
3362741Sksewell@umich.edu        M5_FALLTHROUGH;
3372741Sksewell@umich.edu      case MISCREG_DR7:
3382623SN/A        {
3392683Sktlim@umich.edu            DR7 dr7 = regVal[MISCREG_DR7];
3402683Sktlim@umich.edu            DR7 newDR7 = val;
3412683Sktlim@umich.edu            dr7.l0 = newDR7.l0;
3422623SN/A            dr7.g0 = newDR7.g0;
3432683Sktlim@umich.edu            if (dr7.l0 || dr7.g0) {
3442623SN/A                panic("Debug register breakpoints not implemented.\n");
3452623SN/A            } else {
3462623SN/A                /* Disable breakpoint 0. */
3472623SN/A            }
3482623SN/A            dr7.l1 = newDR7.l1;
3492623SN/A            dr7.g1 = newDR7.g1;
3502623SN/A            if (dr7.l1 || dr7.g1) {
3512623SN/A                panic("Debug register breakpoints not implemented.\n");
3522SN/A            } else {
3532683Sktlim@umich.edu                /* Disable breakpoint 1. */
3542427SN/A            }
3552683Sktlim@umich.edu            dr7.l2 = newDR7.l2;
3562427SN/A            dr7.g2 = newDR7.g2;
3572SN/A            if (dr7.l2 || dr7.g2) {
3582623SN/A                panic("Debug register breakpoints not implemented.\n");
3592623SN/A            } else {
3602623SN/A                /* Disable breakpoint 2. */
3612SN/A            }
3622683Sktlim@umich.edu            dr7.l3 = newDR7.l3;
3632SN/A            dr7.g3 = newDR7.g3;
3642623SN/A            if (dr7.l3 || dr7.g3) {
3652623SN/A                panic("Debug register breakpoints not implemented.\n");
3662SN/A            } else {
3672623SN/A                /* Disable breakpoint 3. */
3682623SN/A            }
3693276Sgblack@eecs.umich.edu            dr7.gd = newDR7.gd;
3703276Sgblack@eecs.umich.edu            dr7.rw0 = newDR7.rw0;
3713484Sktlim@umich.edu            dr7.len0 = newDR7.len0;
3723484Sktlim@umich.edu            dr7.rw1 = newDR7.rw1;
3733484Sktlim@umich.edu            dr7.len1 = newDR7.len1;
3743276Sgblack@eecs.umich.edu            dr7.rw2 = newDR7.rw2;
3753521Sgblack@eecs.umich.edu            dr7.len2 = newDR7.len2;
3763521Sgblack@eecs.umich.edu            dr7.rw3 = newDR7.rw3;
3773521Sgblack@eecs.umich.edu            dr7.len3 = newDR7.len3;
3783521Sgblack@eecs.umich.edu        }
3793484Sktlim@umich.edu        break;
3803276Sgblack@eecs.umich.edu      case MISCREG_M5_REG:
3813276Sgblack@eecs.umich.edu        // Writing anything to the m5reg with side effects makes it update
3823442Sgblack@eecs.umich.edu        // based on the current values of the relevant registers. The actual
3833442Sgblack@eecs.umich.edu        // value written is discarded.
3843280Sgblack@eecs.umich.edu        updateHandyM5Reg(regVal[MISCREG_EFER],
3853280Sgblack@eecs.umich.edu                         regVal[MISCREG_CR0],
3863276Sgblack@eecs.umich.edu                         regVal[MISCREG_CS_ATTR],
3873276Sgblack@eecs.umich.edu                         regVal[MISCREG_SS_ATTR],
3883276Sgblack@eecs.umich.edu                         regVal[MISCREG_RFLAGS],
3893442Sgblack@eecs.umich.edu                         tc);
3903442Sgblack@eecs.umich.edu        return;
3913276Sgblack@eecs.umich.edu      default:
3923276Sgblack@eecs.umich.edu        break;
3932470SN/A    }
3943064Sgblack@eecs.umich.edu    setMiscRegNoEffect(miscReg, newVal);
3952683Sktlim@umich.edu}
3962623SN/A
3972623SN/Avoid
3982623SN/AISA::serialize(CheckpointOut &cp) const
3992623SN/A{
4002623SN/A    SERIALIZE_ARRAY(regVal, NumMiscRegs);
4012623SN/A}
4022683Sktlim@umich.edu
4032623SN/Avoid
4042623SN/AISA::unserialize(CheckpointIn &cp)
4052623SN/A{
4062623SN/A    UNSERIALIZE_ARRAY(regVal, NumMiscRegs);
4072623SN/A    updateHandyM5Reg(regVal[MISCREG_EFER],
4082623SN/A                     regVal[MISCREG_CR0],
4092623SN/A                     regVal[MISCREG_CS_ATTR],
4102683Sktlim@umich.edu                     regVal[MISCREG_SS_ATTR],
4113577Sgblack@eecs.umich.edu                     regVal[MISCREG_RFLAGS],
4122683Sktlim@umich.edu                     NULL);
4132683Sktlim@umich.edu}
4142623SN/A
4152683Sktlim@umich.eduvoid
4162623SN/AISA::startup(ThreadContext *tc)
4172420SN/A{
4182SN/A    tc->getDecoderPtr()->setM5Reg(regVal[MISCREG_M5_REG]);
4192623SN/A}
4202623SN/A
4212SN/A}
4222SN/A
4232623SN/AX86ISA::ISA *
4242623SN/AX86ISAParams::create()
4252623SN/A{
4262623SN/A    return new X86ISA::ISA(this);
4272SN/A}
4282683Sktlim@umich.edu