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