isa.cc revision 11165
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_CR0 && 133 miscReg < NUM_MISCREGS && 134 miscReg != MISCREG_CR1 && 135 !(miscReg > MISCREG_CR4 && 136 miscReg < MISCREG_CR8) && 137 !(miscReg > MISCREG_CR8 && 138 miscReg <= MISCREG_CR15)); 139 140 return regVal[miscReg]; 141} 142 143MiscReg 144ISA::readMiscReg(int miscReg, ThreadContext * tc) 145{ 146 if (miscReg == MISCREG_TSC) { 147 return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); 148 } 149 150 if (miscReg == MISCREG_FSW) { 151 MiscReg fsw = regVal[MISCREG_FSW]; 152 MiscReg top = regVal[MISCREG_X87_TOP]; 153 return (fsw & (~(7ULL << 11))) + (top << 11); 154 } 155 156 return readMiscRegNoEffect(miscReg); 157} 158 159void 160ISA::setMiscRegNoEffect(int miscReg, MiscReg val) 161{ 162 // Make sure we're not dealing with an illegal control register. 163 // Instructions should filter out these indexes, and nothing else should 164 // attempt to write to them directly. 165 assert(miscReg >= MISCREG_CR0 && 166 miscReg < NUM_MISCREGS && 167 miscReg != MISCREG_CR1 && 168 !(miscReg > MISCREG_CR4 && 169 miscReg < MISCREG_CR8) && 170 !(miscReg > MISCREG_CR8 && 171 miscReg <= MISCREG_CR15)); 172 173 HandyM5Reg m5Reg = readMiscRegNoEffect(MISCREG_M5_REG); 174 switch (miscReg) { 175 case MISCREG_FSW: 176 val &= (1ULL << 16) - 1; 177 regVal[miscReg] = val; 178 miscReg = MISCREG_X87_TOP; 179 val <<= 11; 180 case MISCREG_X87_TOP: 181 val &= (1ULL << 3) - 1; 182 break; 183 case MISCREG_FTW: 184 val &= (1ULL << 8) - 1; 185 break; 186 case MISCREG_FCW: 187 case MISCREG_FOP: 188 val &= (1ULL << 16) - 1; 189 break; 190 case MISCREG_MXCSR: 191 val &= (1ULL << 32) - 1; 192 break; 193 case MISCREG_FISEG: 194 case MISCREG_FOSEG: 195 if (m5Reg.submode != SixtyFourBitMode) 196 val &= (1ULL << 16) - 1; 197 break; 198 case MISCREG_FIOFF: 199 case MISCREG_FOOFF: 200 if (m5Reg.submode != SixtyFourBitMode) 201 val &= (1ULL << 32) - 1; 202 break; 203 default: 204 break; 205 } 206 207 regVal[miscReg] = val; 208} 209 210void 211ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc) 212{ 213 MiscReg newVal = val; 214 switch(miscReg) 215 { 216 case MISCREG_CR0: 217 { 218 CR0 toggled = regVal[miscReg] ^ val; 219 CR0 newCR0 = val; 220 Efer efer = regVal[MISCREG_EFER]; 221 if (toggled.pg && efer.lme) { 222 if (newCR0.pg) { 223 //Turning on long mode 224 efer.lma = 1; 225 regVal[MISCREG_EFER] = efer; 226 } else { 227 //Turning off long mode 228 efer.lma = 0; 229 regVal[MISCREG_EFER] = efer; 230 } 231 } 232 if (toggled.pg) { 233 tc->getITBPtr()->flushAll(); 234 tc->getDTBPtr()->flushAll(); 235 } 236 //This must always be 1. 237 newCR0.et = 1; 238 newVal = newCR0; 239 updateHandyM5Reg(regVal[MISCREG_EFER], 240 newCR0, 241 regVal[MISCREG_CS_ATTR], 242 regVal[MISCREG_SS_ATTR], 243 regVal[MISCREG_RFLAGS], 244 tc); 245 } 246 break; 247 case MISCREG_CR2: 248 break; 249 case MISCREG_CR3: 250 tc->getITBPtr()->flushNonGlobal(); 251 tc->getDTBPtr()->flushNonGlobal(); 252 break; 253 case MISCREG_CR4: 254 { 255 CR4 toggled = regVal[miscReg] ^ val; 256 if (toggled.pae || toggled.pse || toggled.pge) { 257 tc->getITBPtr()->flushAll(); 258 tc->getDTBPtr()->flushAll(); 259 } 260 } 261 break; 262 case MISCREG_CR8: 263 break; 264 case MISCREG_CS_ATTR: 265 { 266 SegAttr toggled = regVal[miscReg] ^ val; 267 SegAttr newCSAttr = val; 268 if (toggled.longMode) { 269 if (newCSAttr.longMode) { 270 regVal[MISCREG_ES_EFF_BASE] = 0; 271 regVal[MISCREG_CS_EFF_BASE] = 0; 272 regVal[MISCREG_SS_EFF_BASE] = 0; 273 regVal[MISCREG_DS_EFF_BASE] = 0; 274 } else { 275 regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; 276 regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; 277 regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; 278 regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; 279 } 280 } 281 updateHandyM5Reg(regVal[MISCREG_EFER], 282 regVal[MISCREG_CR0], 283 newCSAttr, 284 regVal[MISCREG_SS_ATTR], 285 regVal[MISCREG_RFLAGS], 286 tc); 287 } 288 break; 289 case MISCREG_SS_ATTR: 290 updateHandyM5Reg(regVal[MISCREG_EFER], 291 regVal[MISCREG_CR0], 292 regVal[MISCREG_CS_ATTR], 293 val, 294 regVal[MISCREG_RFLAGS], 295 tc); 296 break; 297 // These segments always actually use their bases, or in other words 298 // their effective bases must stay equal to their actual bases. 299 case MISCREG_FS_BASE: 300 case MISCREG_GS_BASE: 301 case MISCREG_HS_BASE: 302 case MISCREG_TSL_BASE: 303 case MISCREG_TSG_BASE: 304 case MISCREG_TR_BASE: 305 case MISCREG_IDTR_BASE: 306 regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val; 307 break; 308 // These segments ignore their bases in 64 bit mode. 309 // their effective bases must stay equal to their actual bases. 310 case MISCREG_ES_BASE: 311 case MISCREG_CS_BASE: 312 case MISCREG_SS_BASE: 313 case MISCREG_DS_BASE: 314 { 315 Efer efer = regVal[MISCREG_EFER]; 316 SegAttr csAttr = regVal[MISCREG_CS_ATTR]; 317 if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode. 318 regVal[MISCREG_SEG_EFF_BASE(miscReg - 319 MISCREG_SEG_BASE_BASE)] = val; 320 } 321 break; 322 case MISCREG_TSC: 323 regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); 324 return; 325 case MISCREG_DR0: 326 case MISCREG_DR1: 327 case MISCREG_DR2: 328 case MISCREG_DR3: 329 /* These should eventually set up breakpoints. */ 330 break; 331 case MISCREG_DR4: 332 miscReg = MISCREG_DR6; 333 /* Fall through to have the same effects as DR6. */ 334 case MISCREG_DR6: 335 { 336 DR6 dr6 = regVal[MISCREG_DR6]; 337 DR6 newDR6 = val; 338 dr6.b0 = newDR6.b0; 339 dr6.b1 = newDR6.b1; 340 dr6.b2 = newDR6.b2; 341 dr6.b3 = newDR6.b3; 342 dr6.bd = newDR6.bd; 343 dr6.bs = newDR6.bs; 344 dr6.bt = newDR6.bt; 345 newVal = dr6; 346 } 347 break; 348 case MISCREG_DR5: 349 miscReg = MISCREG_DR7; 350 /* Fall through to have the same effects as DR7. */ 351 case MISCREG_DR7: 352 { 353 DR7 dr7 = regVal[MISCREG_DR7]; 354 DR7 newDR7 = val; 355 dr7.l0 = newDR7.l0; 356 dr7.g0 = newDR7.g0; 357 if (dr7.l0 || dr7.g0) { 358 panic("Debug register breakpoints not implemented.\n"); 359 } else { 360 /* Disable breakpoint 0. */ 361 } 362 dr7.l1 = newDR7.l1; 363 dr7.g1 = newDR7.g1; 364 if (dr7.l1 || dr7.g1) { 365 panic("Debug register breakpoints not implemented.\n"); 366 } else { 367 /* Disable breakpoint 1. */ 368 } 369 dr7.l2 = newDR7.l2; 370 dr7.g2 = newDR7.g2; 371 if (dr7.l2 || dr7.g2) { 372 panic("Debug register breakpoints not implemented.\n"); 373 } else { 374 /* Disable breakpoint 2. */ 375 } 376 dr7.l3 = newDR7.l3; 377 dr7.g3 = newDR7.g3; 378 if (dr7.l3 || dr7.g3) { 379 panic("Debug register breakpoints not implemented.\n"); 380 } else { 381 /* Disable breakpoint 3. */ 382 } 383 dr7.gd = newDR7.gd; 384 dr7.rw0 = newDR7.rw0; 385 dr7.len0 = newDR7.len0; 386 dr7.rw1 = newDR7.rw1; 387 dr7.len1 = newDR7.len1; 388 dr7.rw2 = newDR7.rw2; 389 dr7.len2 = newDR7.len2; 390 dr7.rw3 = newDR7.rw3; 391 dr7.len3 = newDR7.len3; 392 } 393 break; 394 case MISCREG_M5_REG: 395 // Writing anything to the m5reg with side effects makes it update 396 // based on the current values of the relevant registers. The actual 397 // value written is discarded. 398 updateHandyM5Reg(regVal[MISCREG_EFER], 399 regVal[MISCREG_CR0], 400 regVal[MISCREG_CS_ATTR], 401 regVal[MISCREG_SS_ATTR], 402 regVal[MISCREG_RFLAGS], 403 tc); 404 return; 405 default: 406 break; 407 } 408 setMiscRegNoEffect(miscReg, newVal); 409} 410 411void 412ISA::serialize(CheckpointOut &cp) const 413{ 414 SERIALIZE_ARRAY(regVal, NumMiscRegs); 415} 416 417void 418ISA::unserialize(CheckpointIn &cp) 419{ 420 UNSERIALIZE_ARRAY(regVal, NumMiscRegs); 421 updateHandyM5Reg(regVal[MISCREG_EFER], 422 regVal[MISCREG_CR0], 423 regVal[MISCREG_CS_ATTR], 424 regVal[MISCREG_SS_ATTR], 425 regVal[MISCREG_RFLAGS], 426 NULL); 427} 428 429void 430ISA::startup(ThreadContext *tc) 431{ 432 tc->getDecoderPtr()->setM5Reg(regVal[MISCREG_M5_REG]); 433} 434 435} 436 437X86ISA::ISA * 438X86ISAParams::create() 439{ 440 return new X86ISA::ISA(this); 441} 442