isa.cc revision 10844
1/* 2 * Copyright (c) 2009 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 */ 30 31#include "arch/x86/decoder.hh" 32#include "arch/x86/isa.hh" 33#include "arch/x86/tlb.hh" 34#include "cpu/base.hh" 35#include "cpu/thread_context.hh" 36#include "params/X86ISA.hh" 37#include "sim/serialize.hh" 38 39namespace X86ISA 40{ 41 42void 43ISA::updateHandyM5Reg(Efer efer, CR0 cr0, 44 SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags, 45 ThreadContext *tc) 46{ 47 HandyM5Reg m5reg = 0; 48 if (efer.lma) { 49 m5reg.mode = LongMode; 50 if (csAttr.longMode) 51 m5reg.submode = SixtyFourBitMode; 52 else 53 m5reg.submode = CompatabilityMode; 54 } else { 55 m5reg.mode = LegacyMode; 56 if (cr0.pe) { 57 if (rflags.vm) 58 m5reg.submode = Virtual8086Mode; 59 else 60 m5reg.submode = ProtectedMode; 61 } else { 62 m5reg.submode = RealMode; 63 } 64 } 65 m5reg.cpl = csAttr.dpl; 66 m5reg.paging = cr0.pg; 67 m5reg.prot = cr0.pe; 68 69 // Compute the default and alternate operand size. 70 if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) { 71 m5reg.defOp = 2; 72 m5reg.altOp = 1; 73 } else { 74 m5reg.defOp = 1; 75 m5reg.altOp = 2; 76 } 77 78 // Compute the default and alternate address size. 79 if (m5reg.submode == SixtyFourBitMode) { 80 m5reg.defAddr = 3; 81 m5reg.altAddr = 2; 82 } else if (csAttr.defaultSize) { 83 m5reg.defAddr = 2; 84 m5reg.altAddr = 1; 85 } else { 86 m5reg.defAddr = 1; 87 m5reg.altAddr = 2; 88 } 89 90 // Compute the stack size 91 if (m5reg.submode == SixtyFourBitMode) { 92 m5reg.stack = 3; 93 } else if (ssAttr.defaultSize) { 94 m5reg.stack = 2; 95 } else { 96 m5reg.stack = 1; 97 } 98 99 regVal[MISCREG_M5_REG] = m5reg; 100 if (tc) 101 tc->getDecoderPtr()->setM5Reg(m5reg); 102} 103 104void 105ISA::clear() 106{ 107 // Blank everything. 0 might not be an appropriate value for some things, 108 // but it is for most. 109 memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); 110 regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16); 111 regVal[MISCREG_DR7] = 1 << 10; 112} 113 114ISA::ISA(Params *p) 115 : SimObject(p) 116{ 117 clear(); 118} 119 120const X86ISAParams * 121ISA::params() const 122{ 123 return dynamic_cast<const Params *>(_params); 124} 125 126MiscReg 127ISA::readMiscRegNoEffect(int miscReg) const 128{ 129 // Make sure we're not dealing with an illegal control register. 130 // Instructions should filter out these indexes, and nothing else should 131 // attempt to read them directly. 132 assert( miscReg != MISCREG_CR1 && 133 !(miscReg > MISCREG_CR4 && 134 miscReg < MISCREG_CR8) && 135 !(miscReg > MISCREG_CR8 && 136 miscReg <= MISCREG_CR15)); 137 138 return regVal[miscReg]; 139} 140 141MiscReg 142ISA::readMiscReg(int miscReg, ThreadContext * tc) 143{ 144 if (miscReg == MISCREG_TSC) { 145 return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); 146 } 147 148 if (miscReg == MISCREG_FSW) { 149 MiscReg fsw = regVal[MISCREG_FSW]; 150 MiscReg top = regVal[MISCREG_X87_TOP]; 151 return (fsw & (~(7ULL << 11))) + (top << 11); 152 } 153 154 return readMiscRegNoEffect(miscReg); 155} 156 157void 158ISA::setMiscRegNoEffect(int miscReg, MiscReg val) 159{ 160 // Make sure we're not dealing with an illegal control register. 161 // Instructions should filter out these indexes, and nothing else should 162 // attempt to write to them directly. 163 assert( miscReg != MISCREG_CR1 && 164 !(miscReg > MISCREG_CR4 && 165 miscReg < MISCREG_CR8) && 166 !(miscReg > MISCREG_CR8 && 167 miscReg <= MISCREG_CR15)); 168 regVal[miscReg] = val; 169} 170 171void 172ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc) 173{ 174 MiscReg newVal = val; 175 switch(miscReg) 176 { 177 case MISCREG_CR0: 178 { 179 CR0 toggled = regVal[miscReg] ^ val; 180 CR0 newCR0 = val; 181 Efer efer = regVal[MISCREG_EFER]; 182 if (toggled.pg && efer.lme) { 183 if (newCR0.pg) { 184 //Turning on long mode 185 efer.lma = 1; 186 regVal[MISCREG_EFER] = efer; 187 } else { 188 //Turning off long mode 189 efer.lma = 0; 190 regVal[MISCREG_EFER] = efer; 191 } 192 } 193 if (toggled.pg) { 194 tc->getITBPtr()->flushAll(); 195 tc->getDTBPtr()->flushAll(); 196 } 197 //This must always be 1. 198 newCR0.et = 1; 199 newVal = newCR0; 200 updateHandyM5Reg(regVal[MISCREG_EFER], 201 newCR0, 202 regVal[MISCREG_CS_ATTR], 203 regVal[MISCREG_SS_ATTR], 204 regVal[MISCREG_RFLAGS], 205 tc); 206 } 207 break; 208 case MISCREG_CR2: 209 break; 210 case MISCREG_CR3: 211 tc->getITBPtr()->flushNonGlobal(); 212 tc->getDTBPtr()->flushNonGlobal(); 213 break; 214 case MISCREG_CR4: 215 { 216 CR4 toggled = regVal[miscReg] ^ val; 217 if (toggled.pae || toggled.pse || toggled.pge) { 218 tc->getITBPtr()->flushAll(); 219 tc->getDTBPtr()->flushAll(); 220 } 221 } 222 break; 223 case MISCREG_CR8: 224 break; 225 case MISCREG_CS_ATTR: 226 { 227 SegAttr toggled = regVal[miscReg] ^ val; 228 SegAttr newCSAttr = val; 229 if (toggled.longMode) { 230 if (newCSAttr.longMode) { 231 regVal[MISCREG_ES_EFF_BASE] = 0; 232 regVal[MISCREG_CS_EFF_BASE] = 0; 233 regVal[MISCREG_SS_EFF_BASE] = 0; 234 regVal[MISCREG_DS_EFF_BASE] = 0; 235 } else { 236 regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; 237 regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; 238 regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; 239 regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; 240 } 241 } 242 updateHandyM5Reg(regVal[MISCREG_EFER], 243 regVal[MISCREG_CR0], 244 newCSAttr, 245 regVal[MISCREG_SS_ATTR], 246 regVal[MISCREG_RFLAGS], 247 tc); 248 } 249 break; 250 case MISCREG_SS_ATTR: 251 updateHandyM5Reg(regVal[MISCREG_EFER], 252 regVal[MISCREG_CR0], 253 regVal[MISCREG_CS_ATTR], 254 val, 255 regVal[MISCREG_RFLAGS], 256 tc); 257 break; 258 // These segments always actually use their bases, or in other words 259 // their effective bases must stay equal to their actual bases. 260 case MISCREG_FS_BASE: 261 case MISCREG_GS_BASE: 262 case MISCREG_HS_BASE: 263 case MISCREG_TSL_BASE: 264 case MISCREG_TSG_BASE: 265 case MISCREG_TR_BASE: 266 case MISCREG_IDTR_BASE: 267 regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val; 268 break; 269 // These segments ignore their bases in 64 bit mode. 270 // their effective bases must stay equal to their actual bases. 271 case MISCREG_ES_BASE: 272 case MISCREG_CS_BASE: 273 case MISCREG_SS_BASE: 274 case MISCREG_DS_BASE: 275 { 276 Efer efer = regVal[MISCREG_EFER]; 277 SegAttr csAttr = regVal[MISCREG_CS_ATTR]; 278 if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode. 279 regVal[MISCREG_SEG_EFF_BASE(miscReg - 280 MISCREG_SEG_BASE_BASE)] = val; 281 } 282 break; 283 case MISCREG_TSC: 284 regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); 285 return; 286 case MISCREG_DR0: 287 case MISCREG_DR1: 288 case MISCREG_DR2: 289 case MISCREG_DR3: 290 /* These should eventually set up breakpoints. */ 291 break; 292 case MISCREG_DR4: 293 miscReg = MISCREG_DR6; 294 /* Fall through to have the same effects as DR6. */ 295 case MISCREG_DR6: 296 { 297 DR6 dr6 = regVal[MISCREG_DR6]; 298 DR6 newDR6 = val; 299 dr6.b0 = newDR6.b0; 300 dr6.b1 = newDR6.b1; 301 dr6.b2 = newDR6.b2; 302 dr6.b3 = newDR6.b3; 303 dr6.bd = newDR6.bd; 304 dr6.bs = newDR6.bs; 305 dr6.bt = newDR6.bt; 306 newVal = dr6; 307 } 308 break; 309 case MISCREG_DR5: 310 miscReg = MISCREG_DR7; 311 /* Fall through to have the same effects as DR7. */ 312 case MISCREG_DR7: 313 { 314 DR7 dr7 = regVal[MISCREG_DR7]; 315 DR7 newDR7 = val; 316 dr7.l0 = newDR7.l0; 317 dr7.g0 = newDR7.g0; 318 if (dr7.l0 || dr7.g0) { 319 panic("Debug register breakpoints not implemented.\n"); 320 } else { 321 /* Disable breakpoint 0. */ 322 } 323 dr7.l1 = newDR7.l1; 324 dr7.g1 = newDR7.g1; 325 if (dr7.l1 || dr7.g1) { 326 panic("Debug register breakpoints not implemented.\n"); 327 } else { 328 /* Disable breakpoint 1. */ 329 } 330 dr7.l2 = newDR7.l2; 331 dr7.g2 = newDR7.g2; 332 if (dr7.l2 || dr7.g2) { 333 panic("Debug register breakpoints not implemented.\n"); 334 } else { 335 /* Disable breakpoint 2. */ 336 } 337 dr7.l3 = newDR7.l3; 338 dr7.g3 = newDR7.g3; 339 if (dr7.l3 || dr7.g3) { 340 panic("Debug register breakpoints not implemented.\n"); 341 } else { 342 /* Disable breakpoint 3. */ 343 } 344 dr7.gd = newDR7.gd; 345 dr7.rw0 = newDR7.rw0; 346 dr7.len0 = newDR7.len0; 347 dr7.rw1 = newDR7.rw1; 348 dr7.len1 = newDR7.len1; 349 dr7.rw2 = newDR7.rw2; 350 dr7.len2 = newDR7.len2; 351 dr7.rw3 = newDR7.rw3; 352 dr7.len3 = newDR7.len3; 353 } 354 break; 355 case MISCREG_M5_REG: 356 // Writing anything to the m5reg with side effects makes it update 357 // based on the current values of the relevant registers. The actual 358 // value written is discarded. 359 updateHandyM5Reg(regVal[MISCREG_EFER], 360 regVal[MISCREG_CR0], 361 regVal[MISCREG_CS_ATTR], 362 regVal[MISCREG_SS_ATTR], 363 regVal[MISCREG_RFLAGS], 364 tc); 365 return; 366 default: 367 break; 368 } 369 setMiscRegNoEffect(miscReg, newVal); 370} 371 372void 373ISA::serialize(std::ostream & os) 374{ 375 SERIALIZE_ARRAY(regVal, NumMiscRegs); 376} 377 378void 379ISA::unserialize(Checkpoint * cp, const std::string & section) 380{ 381 UNSERIALIZE_ARRAY(regVal, NumMiscRegs); 382 updateHandyM5Reg(regVal[MISCREG_EFER], 383 regVal[MISCREG_CR0], 384 regVal[MISCREG_CS_ATTR], 385 regVal[MISCREG_SS_ATTR], 386 regVal[MISCREG_RFLAGS], 387 NULL); 388} 389 390void 391ISA::startup(ThreadContext *tc) 392{ 393 tc->getDecoderPtr()->setM5Reg(regVal[MISCREG_M5_REG]); 394} 395 396} 397 398X86ISA::ISA * 399X86ISAParams::create() 400{ 401 return new X86ISA::ISA(this); 402} 403