isa.cc revision 12109
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/isa.hh" 32 33#include "arch/x86/decoder.hh" 34#include "arch/x86/tlb.hh" 35#include "cpu/base.hh" 36#include "cpu/thread_context.hh" 37#include "params/X86ISA.hh" 38#include "sim/serialize.hh" 39 40namespace X86ISA 41{ 42 43void 44ISA::updateHandyM5Reg(Efer efer, CR0 cr0, 45 SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags, 46 ThreadContext *tc) 47{ 48 HandyM5Reg m5reg = 0; 49 if (efer.lma) { 50 m5reg.mode = LongMode; 51 if (csAttr.longMode) 52 m5reg.submode = SixtyFourBitMode; 53 else 54 m5reg.submode = CompatabilityMode; 55 } else { 56 m5reg.mode = LegacyMode; 57 if (cr0.pe) { 58 if (rflags.vm) 59 m5reg.submode = Virtual8086Mode; 60 else 61 m5reg.submode = ProtectedMode; 62 } else { 63 m5reg.submode = RealMode; 64 } 65 } 66 m5reg.cpl = csAttr.dpl; 67 m5reg.paging = cr0.pg; 68 m5reg.prot = cr0.pe; 69 70 // Compute the default and alternate operand size. 71 if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) { 72 m5reg.defOp = 2; 73 m5reg.altOp = 1; 74 } else { 75 m5reg.defOp = 1; 76 m5reg.altOp = 2; 77 } 78 79 // Compute the default and alternate address size. 80 if (m5reg.submode == SixtyFourBitMode) { 81 m5reg.defAddr = 3; 82 m5reg.altAddr = 2; 83 } else if (csAttr.defaultSize) { 84 m5reg.defAddr = 2; 85 m5reg.altAddr = 1; 86 } else { 87 m5reg.defAddr = 1; 88 m5reg.altAddr = 2; 89 } 90 91 // Compute the stack size 92 if (m5reg.submode == SixtyFourBitMode) { 93 m5reg.stack = 3; 94 } else if (ssAttr.defaultSize) { 95 m5reg.stack = 2; 96 } else { 97 m5reg.stack = 1; 98 } 99 100 regVal[MISCREG_M5_REG] = m5reg; 101 if (tc) 102 tc->getDecoderPtr()->setM5Reg(m5reg); 103} 104 105void 106ISA::clear() 107{ 108 // Blank everything. 0 might not be an appropriate value for some things, 109 // but it is for most. 110 memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); 111 regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16); 112 regVal[MISCREG_DR7] = 1 << 10; 113} 114 115ISA::ISA(Params *p) 116 : SimObject(p) 117{ 118 clear(); 119} 120 121const X86ISAParams * 122ISA::params() const 123{ 124 return dynamic_cast<const Params *>(_params); 125} 126 127MiscReg 128ISA::readMiscRegNoEffect(int miscReg) const 129{ 130 // Make sure we're not dealing with an illegal control register. 131 // Instructions should filter out these indexes, and nothing else should 132 // attempt to read them directly. 133 assert(isValidMiscReg(miscReg)); 134 135 return regVal[miscReg]; 136} 137 138MiscReg 139ISA::readMiscReg(int miscReg, ThreadContext * tc) 140{ 141 if (miscReg == MISCREG_TSC) { 142 return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); 143 } 144 145 if (miscReg == MISCREG_FSW) { 146 MiscReg fsw = regVal[MISCREG_FSW]; 147 MiscReg top = regVal[MISCREG_X87_TOP]; 148 return (fsw & (~(7ULL << 11))) + (top << 11); 149 } 150 151 return readMiscRegNoEffect(miscReg); 152} 153 154void 155ISA::setMiscRegNoEffect(int miscReg, MiscReg val) 156{ 157 // Make sure we're not dealing with an illegal control register. 158 // Instructions should filter out these indexes, and nothing else should 159 // attempt to write to them directly. 160 assert(isValidMiscReg(miscReg)); 161 162 HandyM5Reg m5Reg = readMiscRegNoEffect(MISCREG_M5_REG); 163 switch (miscReg) { 164 case MISCREG_FSW: 165 val &= (1ULL << 16) - 1; 166 regVal[miscReg] = val; 167 miscReg = MISCREG_X87_TOP; 168 val <<= 11; 169 case MISCREG_X87_TOP: 170 val &= (1ULL << 3) - 1; 171 break; 172 case MISCREG_FTW: 173 val &= (1ULL << 8) - 1; 174 break; 175 case MISCREG_FCW: 176 case MISCREG_FOP: 177 val &= (1ULL << 16) - 1; 178 break; 179 case MISCREG_MXCSR: 180 val &= (1ULL << 32) - 1; 181 break; 182 case MISCREG_FISEG: 183 case MISCREG_FOSEG: 184 if (m5Reg.submode != SixtyFourBitMode) 185 val &= (1ULL << 16) - 1; 186 break; 187 case MISCREG_FIOFF: 188 case MISCREG_FOOFF: 189 if (m5Reg.submode != SixtyFourBitMode) 190 val &= (1ULL << 32) - 1; 191 break; 192 default: 193 break; 194 } 195 196 regVal[miscReg] = val; 197} 198 199void 200ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc) 201{ 202 MiscReg newVal = val; 203 switch(miscReg) 204 { 205 case MISCREG_CR0: 206 { 207 CR0 toggled = regVal[miscReg] ^ val; 208 CR0 newCR0 = val; 209 Efer efer = regVal[MISCREG_EFER]; 210 if (toggled.pg && efer.lme) { 211 if (newCR0.pg) { 212 //Turning on long mode 213 efer.lma = 1; 214 regVal[MISCREG_EFER] = efer; 215 } else { 216 //Turning off long mode 217 efer.lma = 0; 218 regVal[MISCREG_EFER] = efer; 219 } 220 } 221 if (toggled.pg) { 222 tc->getITBPtr()->flushAll(); 223 tc->getDTBPtr()->flushAll(); 224 } 225 //This must always be 1. 226 newCR0.et = 1; 227 newVal = newCR0; 228 updateHandyM5Reg(regVal[MISCREG_EFER], 229 newCR0, 230 regVal[MISCREG_CS_ATTR], 231 regVal[MISCREG_SS_ATTR], 232 regVal[MISCREG_RFLAGS], 233 tc); 234 } 235 break; 236 case MISCREG_CR2: 237 break; 238 case MISCREG_CR3: 239 tc->getITBPtr()->flushNonGlobal(); 240 tc->getDTBPtr()->flushNonGlobal(); 241 break; 242 case MISCREG_CR4: 243 { 244 CR4 toggled = regVal[miscReg] ^ val; 245 if (toggled.pae || toggled.pse || toggled.pge) { 246 tc->getITBPtr()->flushAll(); 247 tc->getDTBPtr()->flushAll(); 248 } 249 } 250 break; 251 case MISCREG_CR8: 252 break; 253 case MISCREG_CS_ATTR: 254 { 255 SegAttr toggled = regVal[miscReg] ^ val; 256 SegAttr newCSAttr = val; 257 if (toggled.longMode) { 258 if (newCSAttr.longMode) { 259 regVal[MISCREG_ES_EFF_BASE] = 0; 260 regVal[MISCREG_CS_EFF_BASE] = 0; 261 regVal[MISCREG_SS_EFF_BASE] = 0; 262 regVal[MISCREG_DS_EFF_BASE] = 0; 263 } else { 264 regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; 265 regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; 266 regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; 267 regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; 268 } 269 } 270 updateHandyM5Reg(regVal[MISCREG_EFER], 271 regVal[MISCREG_CR0], 272 newCSAttr, 273 regVal[MISCREG_SS_ATTR], 274 regVal[MISCREG_RFLAGS], 275 tc); 276 } 277 break; 278 case MISCREG_SS_ATTR: 279 updateHandyM5Reg(regVal[MISCREG_EFER], 280 regVal[MISCREG_CR0], 281 regVal[MISCREG_CS_ATTR], 282 val, 283 regVal[MISCREG_RFLAGS], 284 tc); 285 break; 286 // These segments always actually use their bases, or in other words 287 // their effective bases must stay equal to their actual bases. 288 case MISCREG_FS_BASE: 289 case MISCREG_GS_BASE: 290 case MISCREG_HS_BASE: 291 case MISCREG_TSL_BASE: 292 case MISCREG_TSG_BASE: 293 case MISCREG_TR_BASE: 294 case MISCREG_IDTR_BASE: 295 regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val; 296 break; 297 // These segments ignore their bases in 64 bit mode. 298 // their effective bases must stay equal to their actual bases. 299 case MISCREG_ES_BASE: 300 case MISCREG_CS_BASE: 301 case MISCREG_SS_BASE: 302 case MISCREG_DS_BASE: 303 { 304 Efer efer = regVal[MISCREG_EFER]; 305 SegAttr csAttr = regVal[MISCREG_CS_ATTR]; 306 if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode. 307 regVal[MISCREG_SEG_EFF_BASE(miscReg - 308 MISCREG_SEG_BASE_BASE)] = val; 309 } 310 break; 311 case MISCREG_TSC: 312 regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); 313 return; 314 case MISCREG_DR0: 315 case MISCREG_DR1: 316 case MISCREG_DR2: 317 case MISCREG_DR3: 318 /* These should eventually set up breakpoints. */ 319 break; 320 case MISCREG_DR4: 321 miscReg = MISCREG_DR6; 322 /* Fall through to have the same effects as DR6. */ 323 case MISCREG_DR6: 324 { 325 DR6 dr6 = regVal[MISCREG_DR6]; 326 DR6 newDR6 = val; 327 dr6.b0 = newDR6.b0; 328 dr6.b1 = newDR6.b1; 329 dr6.b2 = newDR6.b2; 330 dr6.b3 = newDR6.b3; 331 dr6.bd = newDR6.bd; 332 dr6.bs = newDR6.bs; 333 dr6.bt = newDR6.bt; 334 newVal = dr6; 335 } 336 break; 337 case MISCREG_DR5: 338 miscReg = MISCREG_DR7; 339 /* Fall through to have the same effects as DR7. */ 340 case MISCREG_DR7: 341 { 342 DR7 dr7 = regVal[MISCREG_DR7]; 343 DR7 newDR7 = val; 344 dr7.l0 = newDR7.l0; 345 dr7.g0 = newDR7.g0; 346 if (dr7.l0 || dr7.g0) { 347 panic("Debug register breakpoints not implemented.\n"); 348 } else { 349 /* Disable breakpoint 0. */ 350 } 351 dr7.l1 = newDR7.l1; 352 dr7.g1 = newDR7.g1; 353 if (dr7.l1 || dr7.g1) { 354 panic("Debug register breakpoints not implemented.\n"); 355 } else { 356 /* Disable breakpoint 1. */ 357 } 358 dr7.l2 = newDR7.l2; 359 dr7.g2 = newDR7.g2; 360 if (dr7.l2 || dr7.g2) { 361 panic("Debug register breakpoints not implemented.\n"); 362 } else { 363 /* Disable breakpoint 2. */ 364 } 365 dr7.l3 = newDR7.l3; 366 dr7.g3 = newDR7.g3; 367 if (dr7.l3 || dr7.g3) { 368 panic("Debug register breakpoints not implemented.\n"); 369 } else { 370 /* Disable breakpoint 3. */ 371 } 372 dr7.gd = newDR7.gd; 373 dr7.rw0 = newDR7.rw0; 374 dr7.len0 = newDR7.len0; 375 dr7.rw1 = newDR7.rw1; 376 dr7.len1 = newDR7.len1; 377 dr7.rw2 = newDR7.rw2; 378 dr7.len2 = newDR7.len2; 379 dr7.rw3 = newDR7.rw3; 380 dr7.len3 = newDR7.len3; 381 } 382 break; 383 case MISCREG_M5_REG: 384 // Writing anything to the m5reg with side effects makes it update 385 // based on the current values of the relevant registers. The actual 386 // value written is discarded. 387 updateHandyM5Reg(regVal[MISCREG_EFER], 388 regVal[MISCREG_CR0], 389 regVal[MISCREG_CS_ATTR], 390 regVal[MISCREG_SS_ATTR], 391 regVal[MISCREG_RFLAGS], 392 tc); 393 return; 394 default: 395 break; 396 } 397 setMiscRegNoEffect(miscReg, newVal); 398} 399 400void 401ISA::serialize(CheckpointOut &cp) const 402{ 403 SERIALIZE_ARRAY(regVal, NumMiscRegs); 404} 405 406void 407ISA::unserialize(CheckpointIn &cp) 408{ 409 UNSERIALIZE_ARRAY(regVal, NumMiscRegs); 410 updateHandyM5Reg(regVal[MISCREG_EFER], 411 regVal[MISCREG_CR0], 412 regVal[MISCREG_CS_ATTR], 413 regVal[MISCREG_SS_ATTR], 414 regVal[MISCREG_RFLAGS], 415 NULL); 416} 417 418void 419ISA::startup(ThreadContext *tc) 420{ 421 tc->getDecoderPtr()->setM5Reg(regVal[MISCREG_M5_REG]); 422} 423 424} 425 426X86ISA::ISA * 427X86ISAParams::create() 428{ 429 return new X86ISA::ISA(this); 430} 431