misc.isa revision 12498
1// -*- mode:c++ -*- 2 3// Copyright (c) 2010-2013,2017 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Redistribution and use in source and binary forms, with or without 16// modification, are permitted provided that the following conditions are 17// met: redistributions of source code must retain the above copyright 18// notice, this list of conditions and the following disclaimer; 19// redistributions in binary form must reproduce the above copyright 20// notice, this list of conditions and the following disclaimer in the 21// documentation and/or other materials provided with the distribution; 22// neither the name of the copyright holders nor the names of its 23// contributors may be used to endorse or promote products derived from 24// this software without specific prior written permission. 25// 26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37// 38// Authors: Gabe Black 39 40let {{ 41 42 svcCode = ''' 43 fault = std::make_shared<SupervisorCall>(machInst, imm); 44 ''' 45 46 svcIop = InstObjParams("svc", "Svc", "ImmOp", 47 { "code": svcCode, 48 "predicate_test": predicateTest }, 49 ["IsSyscall", "IsNonSpeculative", "IsSerializeAfter"]) 50 header_output = ImmOpDeclare.subst(svcIop) 51 decoder_output = ImmOpConstructor.subst(svcIop) 52 exec_output = PredOpExecute.subst(svcIop) 53 54 smcCode = ''' 55 HCR hcr = Hcr; 56 CPSR cpsr = Cpsr; 57 SCR scr = Scr; 58 59 if ((cpsr.mode != MODE_USER) && FullSystem) { 60 if (ArmSystem::haveVirtualization(xc->tcBase()) && 61 !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP) && hcr.tsc) { 62 fault = std::make_shared<HypervisorTrap>(machInst, 0, 63 EC_SMC_TO_HYP); 64 } else { 65 if (scr.scd) { 66 fault = disabledFault(); 67 } else { 68 fault = std::make_shared<SecureMonitorCall>(machInst); 69 } 70 } 71 } else { 72 fault = disabledFault(); 73 } 74 ''' 75 76 smcIop = InstObjParams("smc", "Smc", "PredOp", 77 { "code": smcCode, 78 "predicate_test": predicateTest }, 79 ["IsNonSpeculative", "IsSerializeAfter"]) 80 header_output += BasicDeclare.subst(smcIop) 81 decoder_output += BasicConstructor.subst(smcIop) 82 exec_output += PredOpExecute.subst(smcIop) 83 84 hvcCode = ''' 85 CPSR cpsr = Cpsr; 86 SCR scr = Scr; 87 88 // Filter out the various cases where this instruction isn't defined 89 if (!FullSystem || !ArmSystem::haveVirtualization(xc->tcBase()) || 90 (cpsr.mode == MODE_USER) || 91 (ArmSystem::haveSecurity(xc->tcBase()) && (!scr.ns || !scr.hce))) { 92 fault = disabledFault(); 93 } else { 94 fault = std::make_shared<HypervisorCall>(machInst, imm); 95 } 96 ''' 97 98 hvcIop = InstObjParams("hvc", "Hvc", "ImmOp", 99 { "code": hvcCode, 100 "predicate_test": predicateTest }, 101 ["IsNonSpeculative", "IsSerializeAfter"]) 102 header_output += ImmOpDeclare.subst(hvcIop) 103 decoder_output += ImmOpConstructor.subst(hvcIop) 104 exec_output += PredOpExecute.subst(hvcIop) 105 106 eretCode = ''' 107 SCTLR sctlr = Sctlr; 108 CPSR old_cpsr = Cpsr; 109 old_cpsr.nz = CondCodesNZ; 110 old_cpsr.c = CondCodesC; 111 old_cpsr.v = CondCodesV; 112 old_cpsr.ge = CondCodesGE; 113 114 CPSR new_cpsr = cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, 115 true, sctlr.nmfi, xc->tcBase()); 116 Cpsr = ~CondCodesMask & new_cpsr; 117 CondCodesNZ = new_cpsr.nz; 118 CondCodesC = new_cpsr.c; 119 CondCodesV = new_cpsr.v; 120 CondCodesGE = new_cpsr.ge; 121 122 NextThumb = (new_cpsr).t; 123 NextJazelle = (new_cpsr).j; 124 NextItState = (((new_cpsr).it2 << 2) & 0xFC) 125 | ((new_cpsr).it1 & 0x3); 126 127 NPC = (old_cpsr.mode == MODE_HYP) ? ElrHyp : LR; 128 ''' 129 130 eretIop = InstObjParams("eret", "Eret", "PredOp", 131 { "code": eretCode, 132 "predicate_test": predicateTest }, 133 ["IsNonSpeculative", "IsSerializeAfter", 134 "IsSquashAfter"]) 135 header_output += BasicDeclare.subst(eretIop) 136 decoder_output += BasicConstructor.subst(eretIop) 137 exec_output += PredOpExecute.subst(eretIop) 138 139 crcCode = ''' 140 constexpr uint8_t size_bytes = %(sz)d; 141 constexpr uint32_t poly = %(polynom)s; 142 143 uint32_t data = htole(Op2); 144 auto data_buffer = reinterpret_cast<uint8_t*>(&data); 145 146 Dest = crc32<poly>( 147 data_buffer, /* Message Register */ 148 Op1, /* Initial Value of the CRC */ 149 size_bytes /* Size of the original Message */ 150 ); 151 ''' 152 153 def crc32Emit(mnem, implCode, castagnoli, size): 154 global header_output, decoder_output, exec_output 155 156 if castagnoli: 157 # crc32c instructions 158 poly = "0x1EDC6F41" 159 else: 160 # crc32 instructions 161 poly = "0x04C11DB7" 162 163 data = {'sz' : size, 'polynom': poly} 164 165 instCode = implCode % data 166 167 crcIop = InstObjParams(mnem, mnem.capitalize(), "RegRegRegOp", 168 { "code": instCode, 169 "predicate_test": predicateTest }, []) 170 header_output += RegRegRegOpDeclare.subst(crcIop) 171 decoder_output += RegRegRegOpConstructor.subst(crcIop) 172 exec_output += PredOpExecute.subst(crcIop) 173 174 crc32Emit("crc32b", crcCode, False, 1); 175 crc32Emit("crc32h", crcCode, False, 2); 176 crc32Emit("crc32w", crcCode, False, 4); 177 crc32Emit("crc32cb", crcCode, True, 1); 178 crc32Emit("crc32ch", crcCode, True, 2); 179 crc32Emit("crc32cw", crcCode, True, 4); 180 181}}; 182 183let {{ 184 185 header_output = decoder_output = exec_output = "" 186 187 mrsCpsrCode = ''' 188 CPSR cpsr = Cpsr; 189 cpsr.nz = CondCodesNZ; 190 cpsr.c = CondCodesC; 191 cpsr.v = CondCodesV; 192 cpsr.ge = CondCodesGE; 193 Dest = cpsr & 0xF8FF03DF 194 ''' 195 196 mrsCpsrIop = InstObjParams("mrs", "MrsCpsr", "MrsOp", 197 { "code": mrsCpsrCode, 198 "predicate_test": condPredicateTest }, 199 ["IsSerializeBefore"]) 200 header_output += MrsDeclare.subst(mrsCpsrIop) 201 decoder_output += MrsConstructor.subst(mrsCpsrIop) 202 exec_output += PredOpExecute.subst(mrsCpsrIop) 203 204 mrsSpsrCode = "Dest = Spsr" 205 mrsSpsrIop = InstObjParams("mrs", "MrsSpsr", "MrsOp", 206 { "code": mrsSpsrCode, 207 "predicate_test": predicateTest }, 208 ["IsSerializeBefore"]) 209 header_output += MrsDeclare.subst(mrsSpsrIop) 210 decoder_output += MrsConstructor.subst(mrsSpsrIop) 211 exec_output += PredOpExecute.subst(mrsSpsrIop) 212 213 mrsBankedRegCode = ''' 214 bool isIntReg; 215 int regIdx; 216 217 if (decodeMrsMsrBankedReg(byteMask, r, isIntReg, regIdx, Cpsr, Scr, Nsacr)) { 218 if (isIntReg) { 219 Dest = DecodedBankedIntReg; 220 } else { 221 Dest = xc->readMiscReg(regIdx); 222 } 223 } else { 224 return std::make_shared<UndefinedInstruction>(machInst, false, 225 mnemonic); 226 } 227 ''' 228 mrsBankedRegIop = InstObjParams("mrs", "MrsBankedReg", "MrsOp", 229 { "code": mrsBankedRegCode, 230 "predicate_test": predicateTest }, 231 ["IsSerializeBefore"]) 232 header_output += MrsBankedRegDeclare.subst(mrsBankedRegIop) 233 decoder_output += MrsBankedRegConstructor.subst(mrsBankedRegIop) 234 exec_output += PredOpExecute.subst(mrsBankedRegIop) 235 236 msrBankedRegCode = ''' 237 bool isIntReg; 238 int regIdx; 239 240 if (decodeMrsMsrBankedReg(byteMask, r, isIntReg, regIdx, Cpsr, Scr, Nsacr)) { 241 if (isIntReg) { 242 // This is a bit nasty, you would have thought that 243 // DecodedBankedIntReg wouldn't be written to unless the 244 // conditions on the IF statements above are met, however if 245 // you look at the generated C code you'll find that they are. 246 // However this is safe as DecodedBankedIntReg (which is used 247 // in operands.isa to get the index of DecodedBankedIntReg) 248 // will return INTREG_DUMMY if its not a valid integer 249 // register, so redirecting the write to somewhere we don't 250 // care about. 251 DecodedBankedIntReg = Op1; 252 } else { 253 xc->setMiscReg(regIdx, Op1); 254 } 255 } else { 256 return std::make_shared<UndefinedInstruction>(machInst, false, 257 mnemonic); 258 } 259 ''' 260 msrBankedRegIop = InstObjParams("msr", "MsrBankedReg", "MsrRegOp", 261 { "code": msrBankedRegCode, 262 "predicate_test": predicateTest }, 263 ["IsSerializeAfter", "IsNonSpeculative"]) 264 header_output += MsrBankedRegDeclare.subst(msrBankedRegIop) 265 decoder_output += MsrBankedRegConstructor.subst(msrBankedRegIop) 266 exec_output += PredOpExecute.subst(msrBankedRegIop) 267 268 msrCpsrRegCode = ''' 269 SCTLR sctlr = Sctlr; 270 CPSR old_cpsr = Cpsr; 271 old_cpsr.nz = CondCodesNZ; 272 old_cpsr.c = CondCodesC; 273 old_cpsr.v = CondCodesV; 274 old_cpsr.ge = CondCodesGE; 275 276 CPSR new_cpsr = 277 cpsrWriteByInstr(old_cpsr, Op1, Scr, Nsacr, byteMask, false, 278 sctlr.nmfi, xc->tcBase()); 279 Cpsr = ~CondCodesMask & new_cpsr; 280 CondCodesNZ = new_cpsr.nz; 281 CondCodesC = new_cpsr.c; 282 CondCodesV = new_cpsr.v; 283 CondCodesGE = new_cpsr.ge; 284 ''' 285 msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp", 286 { "code": msrCpsrRegCode, 287 "predicate_test": condPredicateTest }, 288 ["IsSerializeAfter","IsNonSpeculative"]) 289 header_output += MsrRegDeclare.subst(msrCpsrRegIop) 290 decoder_output += MsrRegConstructor.subst(msrCpsrRegIop) 291 exec_output += PredOpExecute.subst(msrCpsrRegIop) 292 293 msrSpsrRegCode = "Spsr = spsrWriteByInstr(Spsr, Op1, byteMask, false);" 294 msrSpsrRegIop = InstObjParams("msr", "MsrSpsrReg", "MsrRegOp", 295 { "code": msrSpsrRegCode, 296 "predicate_test": predicateTest }, 297 ["IsSerializeAfter","IsNonSpeculative"]) 298 header_output += MsrRegDeclare.subst(msrSpsrRegIop) 299 decoder_output += MsrRegConstructor.subst(msrSpsrRegIop) 300 exec_output += PredOpExecute.subst(msrSpsrRegIop) 301 302 msrCpsrImmCode = ''' 303 SCTLR sctlr = Sctlr; 304 CPSR old_cpsr = Cpsr; 305 old_cpsr.nz = CondCodesNZ; 306 old_cpsr.c = CondCodesC; 307 old_cpsr.v = CondCodesV; 308 old_cpsr.ge = CondCodesGE; 309 CPSR new_cpsr = 310 cpsrWriteByInstr(old_cpsr, imm, Scr, Nsacr, byteMask, false, 311 sctlr.nmfi, xc->tcBase()); 312 Cpsr = ~CondCodesMask & new_cpsr; 313 CondCodesNZ = new_cpsr.nz; 314 CondCodesC = new_cpsr.c; 315 CondCodesV = new_cpsr.v; 316 CondCodesGE = new_cpsr.ge; 317 ''' 318 msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp", 319 { "code": msrCpsrImmCode, 320 "predicate_test": condPredicateTest }, 321 ["IsSerializeAfter","IsNonSpeculative"]) 322 header_output += MsrImmDeclare.subst(msrCpsrImmIop) 323 decoder_output += MsrImmConstructor.subst(msrCpsrImmIop) 324 exec_output += PredOpExecute.subst(msrCpsrImmIop) 325 326 msrSpsrImmCode = "Spsr = spsrWriteByInstr(Spsr, imm, byteMask, false);" 327 msrSpsrImmIop = InstObjParams("msr", "MsrSpsrImm", "MsrImmOp", 328 { "code": msrSpsrImmCode, 329 "predicate_test": predicateTest }, 330 ["IsSerializeAfter","IsNonSpeculative"]) 331 header_output += MsrImmDeclare.subst(msrSpsrImmIop) 332 decoder_output += MsrImmConstructor.subst(msrSpsrImmIop) 333 exec_output += PredOpExecute.subst(msrSpsrImmIop) 334 335 revCode = ''' 336 uint32_t val = Op1; 337 Dest = swap_byte(val); 338 ''' 339 revIop = InstObjParams("rev", "Rev", "RegRegOp", 340 { "code": revCode, 341 "predicate_test": predicateTest }, []) 342 header_output += RegRegOpDeclare.subst(revIop) 343 decoder_output += RegRegOpConstructor.subst(revIop) 344 exec_output += PredOpExecute.subst(revIop) 345 346 rev16Code = ''' 347 uint32_t val = Op1; 348 Dest = (bits(val, 15, 8) << 0) | 349 (bits(val, 7, 0) << 8) | 350 (bits(val, 31, 24) << 16) | 351 (bits(val, 23, 16) << 24); 352 ''' 353 rev16Iop = InstObjParams("rev16", "Rev16", "RegRegOp", 354 { "code": rev16Code, 355 "predicate_test": predicateTest }, []) 356 header_output += RegRegOpDeclare.subst(rev16Iop) 357 decoder_output += RegRegOpConstructor.subst(rev16Iop) 358 exec_output += PredOpExecute.subst(rev16Iop) 359 360 revshCode = ''' 361 uint16_t val = Op1; 362 Dest = sext<16>(swap_byte(val)); 363 ''' 364 revshIop = InstObjParams("revsh", "Revsh", "RegRegOp", 365 { "code": revshCode, 366 "predicate_test": predicateTest }, []) 367 header_output += RegRegOpDeclare.subst(revshIop) 368 decoder_output += RegRegOpConstructor.subst(revshIop) 369 exec_output += PredOpExecute.subst(revshIop) 370 371 rbitCode = ''' 372 Dest = reverseBits(Op1); 373 ''' 374 rbitIop = InstObjParams("rbit", "Rbit", "RegRegOp", 375 { "code": rbitCode, 376 "predicate_test": predicateTest }, []) 377 header_output += RegRegOpDeclare.subst(rbitIop) 378 decoder_output += RegRegOpConstructor.subst(rbitIop) 379 exec_output += PredOpExecute.subst(rbitIop) 380 381 clzCode = ''' 382 Dest = (Op1 == 0) ? 32 : (31 - findMsbSet(Op1)); 383 ''' 384 clzIop = InstObjParams("clz", "Clz", "RegRegOp", 385 { "code": clzCode, 386 "predicate_test": predicateTest }, []) 387 header_output += RegRegOpDeclare.subst(clzIop) 388 decoder_output += RegRegOpConstructor.subst(clzIop) 389 exec_output += PredOpExecute.subst(clzIop) 390 391 ssatCode = ''' 392 int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0); 393 int32_t res; 394 if (satInt(res, operand, imm)) 395 CpsrQ = 1 << 27; 396 Dest = res; 397 ''' 398 ssatIop = InstObjParams("ssat", "Ssat", "RegImmRegShiftOp", 399 { "code": ssatCode, 400 "predicate_test": pickPredicate(ssatCode) }, []) 401 header_output += RegImmRegShiftOpDeclare.subst(ssatIop) 402 decoder_output += RegImmRegShiftOpConstructor.subst(ssatIop) 403 exec_output += PredOpExecute.subst(ssatIop) 404 405 usatCode = ''' 406 int32_t operand = shift_rm_imm(Op1, shiftAmt, shiftType, 0); 407 int32_t res; 408 if (uSatInt(res, operand, imm)) 409 CpsrQ = 1 << 27; 410 Dest = res; 411 ''' 412 usatIop = InstObjParams("usat", "Usat", "RegImmRegShiftOp", 413 { "code": usatCode, 414 "predicate_test": pickPredicate(usatCode) }, []) 415 header_output += RegImmRegShiftOpDeclare.subst(usatIop) 416 decoder_output += RegImmRegShiftOpConstructor.subst(usatIop) 417 exec_output += PredOpExecute.subst(usatIop) 418 419 ssat16Code = ''' 420 int32_t res; 421 uint32_t resTemp = 0; 422 int32_t argLow = sext<16>(bits(Op1, 15, 0)); 423 int32_t argHigh = sext<16>(bits(Op1, 31, 16)); 424 if (satInt(res, argLow, imm)) 425 CpsrQ = 1 << 27; 426 replaceBits(resTemp, 15, 0, res); 427 if (satInt(res, argHigh, imm)) 428 CpsrQ = 1 << 27; 429 replaceBits(resTemp, 31, 16, res); 430 Dest = resTemp; 431 ''' 432 ssat16Iop = InstObjParams("ssat16", "Ssat16", "RegImmRegOp", 433 { "code": ssat16Code, 434 "predicate_test": pickPredicate(ssat16Code) }, []) 435 header_output += RegImmRegOpDeclare.subst(ssat16Iop) 436 decoder_output += RegImmRegOpConstructor.subst(ssat16Iop) 437 exec_output += PredOpExecute.subst(ssat16Iop) 438 439 usat16Code = ''' 440 int32_t res; 441 uint32_t resTemp = 0; 442 int32_t argLow = sext<16>(bits(Op1, 15, 0)); 443 int32_t argHigh = sext<16>(bits(Op1, 31, 16)); 444 if (uSatInt(res, argLow, imm)) 445 CpsrQ = 1 << 27; 446 replaceBits(resTemp, 15, 0, res); 447 if (uSatInt(res, argHigh, imm)) 448 CpsrQ = 1 << 27; 449 replaceBits(resTemp, 31, 16, res); 450 Dest = resTemp; 451 ''' 452 usat16Iop = InstObjParams("usat16", "Usat16", "RegImmRegOp", 453 { "code": usat16Code, 454 "predicate_test": pickPredicate(usat16Code) }, []) 455 header_output += RegImmRegOpDeclare.subst(usat16Iop) 456 decoder_output += RegImmRegOpConstructor.subst(usat16Iop) 457 exec_output += PredOpExecute.subst(usat16Iop) 458 459 sxtbIop = InstObjParams("sxtb", "Sxtb", "RegImmRegOp", 460 { "code": 461 "Dest = sext<8>((uint8_t)(Op1_ud >> imm));", 462 "predicate_test": predicateTest }, []) 463 header_output += RegImmRegOpDeclare.subst(sxtbIop) 464 decoder_output += RegImmRegOpConstructor.subst(sxtbIop) 465 exec_output += PredOpExecute.subst(sxtbIop) 466 467 sxtabIop = InstObjParams("sxtab", "Sxtab", "RegRegRegImmOp", 468 { "code": 469 ''' 470 Dest = sext<8>((uint8_t)(Op2_ud >> imm)) + 471 Op1; 472 ''', 473 "predicate_test": predicateTest }, []) 474 header_output += RegRegRegImmOpDeclare.subst(sxtabIop) 475 decoder_output += RegRegRegImmOpConstructor.subst(sxtabIop) 476 exec_output += PredOpExecute.subst(sxtabIop) 477 478 sxtb16Code = ''' 479 uint32_t resTemp = 0; 480 replaceBits(resTemp, 15, 0, sext<8>(bits(Op1, imm + 7, imm))); 481 replaceBits(resTemp, 31, 16, 482 sext<8>(bits(Op1, (imm + 23) % 32, (imm + 16) % 32))); 483 Dest = resTemp; 484 ''' 485 sxtb16Iop = InstObjParams("sxtb16", "Sxtb16", "RegImmRegOp", 486 { "code": sxtb16Code, 487 "predicate_test": predicateTest }, []) 488 header_output += RegImmRegOpDeclare.subst(sxtb16Iop) 489 decoder_output += RegImmRegOpConstructor.subst(sxtb16Iop) 490 exec_output += PredOpExecute.subst(sxtb16Iop) 491 492 sxtab16Code = ''' 493 uint32_t resTemp = 0; 494 replaceBits(resTemp, 15, 0, sext<8>(bits(Op2, imm + 7, imm)) + 495 bits(Op1, 15, 0)); 496 replaceBits(resTemp, 31, 16, 497 sext<8>(bits(Op2, (imm + 23) % 32, (imm + 16) % 32)) + 498 bits(Op1, 31, 16)); 499 Dest = resTemp; 500 ''' 501 sxtab16Iop = InstObjParams("sxtab16", "Sxtab16", "RegRegRegImmOp", 502 { "code": sxtab16Code, 503 "predicate_test": predicateTest }, []) 504 header_output += RegRegRegImmOpDeclare.subst(sxtab16Iop) 505 decoder_output += RegRegRegImmOpConstructor.subst(sxtab16Iop) 506 exec_output += PredOpExecute.subst(sxtab16Iop) 507 508 sxthCode = ''' 509 uint64_t rotated = (uint32_t)Op1; 510 rotated = (rotated | (rotated << 32)) >> imm; 511 Dest = sext<16>((uint16_t)rotated); 512 ''' 513 sxthIop = InstObjParams("sxth", "Sxth", "RegImmRegOp", 514 { "code": sxthCode, 515 "predicate_test": predicateTest }, []) 516 header_output += RegImmRegOpDeclare.subst(sxthIop) 517 decoder_output += RegImmRegOpConstructor.subst(sxthIop) 518 exec_output += PredOpExecute.subst(sxthIop) 519 520 sxtahCode = ''' 521 uint64_t rotated = (uint32_t)Op2; 522 rotated = (rotated | (rotated << 32)) >> imm; 523 Dest = sext<16>((uint16_t)rotated) + Op1; 524 ''' 525 sxtahIop = InstObjParams("sxtah", "Sxtah", "RegRegRegImmOp", 526 { "code": sxtahCode, 527 "predicate_test": predicateTest }, []) 528 header_output += RegRegRegImmOpDeclare.subst(sxtahIop) 529 decoder_output += RegRegRegImmOpConstructor.subst(sxtahIop) 530 exec_output += PredOpExecute.subst(sxtahIop) 531 532 uxtbIop = InstObjParams("uxtb", "Uxtb", "RegImmRegOp", 533 { "code": "Dest = (uint8_t)(Op1_ud >> imm);", 534 "predicate_test": predicateTest }, []) 535 header_output += RegImmRegOpDeclare.subst(uxtbIop) 536 decoder_output += RegImmRegOpConstructor.subst(uxtbIop) 537 exec_output += PredOpExecute.subst(uxtbIop) 538 539 uxtabIop = InstObjParams("uxtab", "Uxtab", "RegRegRegImmOp", 540 { "code": 541 "Dest = (uint8_t)(Op2_ud >> imm) + Op1;", 542 "predicate_test": predicateTest }, []) 543 header_output += RegRegRegImmOpDeclare.subst(uxtabIop) 544 decoder_output += RegRegRegImmOpConstructor.subst(uxtabIop) 545 exec_output += PredOpExecute.subst(uxtabIop) 546 547 uxtb16Code = ''' 548 uint32_t resTemp = 0; 549 replaceBits(resTemp, 15, 0, (uint8_t)(bits(Op1, imm + 7, imm))); 550 replaceBits(resTemp, 31, 16, 551 (uint8_t)(bits(Op1, (imm + 23) % 32, (imm + 16) % 32))); 552 Dest = resTemp; 553 ''' 554 uxtb16Iop = InstObjParams("uxtb16", "Uxtb16", "RegImmRegOp", 555 { "code": uxtb16Code, 556 "predicate_test": predicateTest }, []) 557 header_output += RegImmRegOpDeclare.subst(uxtb16Iop) 558 decoder_output += RegImmRegOpConstructor.subst(uxtb16Iop) 559 exec_output += PredOpExecute.subst(uxtb16Iop) 560 561 uxtab16Code = ''' 562 uint32_t resTemp = 0; 563 replaceBits(resTemp, 15, 0, (uint8_t)(bits(Op2, imm + 7, imm)) + 564 bits(Op1, 15, 0)); 565 replaceBits(resTemp, 31, 16, 566 (uint8_t)(bits(Op2, (imm + 23) % 32, (imm + 16) % 32)) + 567 bits(Op1, 31, 16)); 568 Dest = resTemp; 569 ''' 570 uxtab16Iop = InstObjParams("uxtab16", "Uxtab16", "RegRegRegImmOp", 571 { "code": uxtab16Code, 572 "predicate_test": predicateTest }, []) 573 header_output += RegRegRegImmOpDeclare.subst(uxtab16Iop) 574 decoder_output += RegRegRegImmOpConstructor.subst(uxtab16Iop) 575 exec_output += PredOpExecute.subst(uxtab16Iop) 576 577 uxthCode = ''' 578 uint64_t rotated = (uint32_t)Op1; 579 rotated = (rotated | (rotated << 32)) >> imm; 580 Dest = (uint16_t)rotated; 581 ''' 582 uxthIop = InstObjParams("uxth", "Uxth", "RegImmRegOp", 583 { "code": uxthCode, 584 "predicate_test": predicateTest }, []) 585 header_output += RegImmRegOpDeclare.subst(uxthIop) 586 decoder_output += RegImmRegOpConstructor.subst(uxthIop) 587 exec_output += PredOpExecute.subst(uxthIop) 588 589 uxtahCode = ''' 590 uint64_t rotated = (uint32_t)Op2; 591 rotated = (rotated | (rotated << 32)) >> imm; 592 Dest = (uint16_t)rotated + Op1; 593 ''' 594 uxtahIop = InstObjParams("uxtah", "Uxtah", "RegRegRegImmOp", 595 { "code": uxtahCode, 596 "predicate_test": predicateTest }, []) 597 header_output += RegRegRegImmOpDeclare.subst(uxtahIop) 598 decoder_output += RegRegRegImmOpConstructor.subst(uxtahIop) 599 exec_output += PredOpExecute.subst(uxtahIop) 600 601 selCode = ''' 602 uint32_t resTemp = 0; 603 for (unsigned i = 0; i < 4; i++) { 604 int low = i * 8; 605 int high = low + 7; 606 replaceBits(resTemp, high, low, 607 bits(CondCodesGE, i) ? 608 bits(Op1, high, low) : bits(Op2, high, low)); 609 } 610 Dest = resTemp; 611 ''' 612 selIop = InstObjParams("sel", "Sel", "RegRegRegOp", 613 { "code": selCode, 614 "predicate_test": predicateTest }, []) 615 header_output += RegRegRegOpDeclare.subst(selIop) 616 decoder_output += RegRegRegOpConstructor.subst(selIop) 617 exec_output += PredOpExecute.subst(selIop) 618 619 usad8Code = ''' 620 uint32_t resTemp = 0; 621 for (unsigned i = 0; i < 4; i++) { 622 int low = i * 8; 623 int high = low + 7; 624 int32_t diff = bits(Op1, high, low) - 625 bits(Op2, high, low); 626 resTemp += ((diff < 0) ? -diff : diff); 627 } 628 Dest = resTemp; 629 ''' 630 usad8Iop = InstObjParams("usad8", "Usad8", "RegRegRegOp", 631 { "code": usad8Code, 632 "predicate_test": predicateTest }, []) 633 header_output += RegRegRegOpDeclare.subst(usad8Iop) 634 decoder_output += RegRegRegOpConstructor.subst(usad8Iop) 635 exec_output += PredOpExecute.subst(usad8Iop) 636 637 usada8Code = ''' 638 uint32_t resTemp = 0; 639 for (unsigned i = 0; i < 4; i++) { 640 int low = i * 8; 641 int high = low + 7; 642 int32_t diff = bits(Op1, high, low) - 643 bits(Op2, high, low); 644 resTemp += ((diff < 0) ? -diff : diff); 645 } 646 Dest = Op3 + resTemp; 647 ''' 648 usada8Iop = InstObjParams("usada8", "Usada8", "RegRegRegRegOp", 649 { "code": usada8Code, 650 "predicate_test": predicateTest }, []) 651 header_output += RegRegRegRegOpDeclare.subst(usada8Iop) 652 decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop) 653 exec_output += PredOpExecute.subst(usada8Iop) 654 655 bkptCode = 'return std::make_shared<PrefetchAbort>(PC, ArmFault::DebugEvent);\n' 656 bkptIop = InstObjParams("bkpt", "BkptInst", "PredOp", bkptCode) 657 header_output += BasicDeclare.subst(bkptIop) 658 decoder_output += BasicConstructor.subst(bkptIop) 659 exec_output += BasicExecute.subst(bkptIop) 660 661 nopIop = InstObjParams("nop", "NopInst", "ArmStaticInst", "", ['IsNop']) 662 header_output += BasicDeclare.subst(nopIop) 663 decoder_output += BasicConstructor64.subst(nopIop) 664 exec_output += BasicExecute.subst(nopIop) 665 666 yieldIop = InstObjParams("yield", "YieldInst", "PredOp", \ 667 { "code" : "", "predicate_test" : predicateTest }) 668 header_output += BasicDeclare.subst(yieldIop) 669 decoder_output += BasicConstructor.subst(yieldIop) 670 exec_output += PredOpExecute.subst(yieldIop) 671 672 wfeCode = ''' 673 CPSR cpsr = Cpsr; 674 SCR scr = Scr64; 675 676 // WFE Sleeps if SevMailbox==0 and no unmasked interrupts are pending, 677 ThreadContext *tc = xc->tcBase(); 678 if (SevMailbox == 1) { 679 SevMailbox = 0; 680 PseudoInst::quiesceSkip(tc); 681 } else if (tc->getCpuPtr()->getInterruptController( 682 tc->threadId())->checkInterrupts(tc)) { 683 PseudoInst::quiesceSkip(tc); 684 } else { 685 fault = trapWFx(tc, cpsr, scr, true); 686 if (fault == NoFault) { 687 PseudoInst::quiesce(tc); 688 } else { 689 PseudoInst::quiesceSkip(tc); 690 } 691 } 692 ''' 693 wfePredFixUpCode = ''' 694 // WFE is predicated false, reset SevMailbox to reduce spurious sleeps 695 // and SEV interrupts 696 SevMailbox = 1; 697 ''' 698 wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \ 699 { "code" : wfeCode, 700 "pred_fixup" : wfePredFixUpCode, 701 "predicate_test" : predicateTest }, 702 ["IsNonSpeculative", "IsQuiesce", 703 "IsSerializeAfter", "IsUnverifiable"]) 704 header_output += BasicDeclare.subst(wfeIop) 705 decoder_output += BasicConstructor.subst(wfeIop) 706 exec_output += QuiescePredOpExecuteWithFixup.subst(wfeIop) 707 708 wfiCode = ''' 709 HCR hcr = Hcr; 710 CPSR cpsr = Cpsr; 711 SCR scr = Scr64; 712 713 // WFI doesn't sleep if interrupts are pending (masked or not) 714 ThreadContext *tc = xc->tcBase(); 715 if (tc->getCpuPtr()->getInterruptController( 716 tc->threadId())->checkWfiWake(hcr, cpsr, scr)) { 717 PseudoInst::quiesceSkip(tc); 718 } else { 719 fault = trapWFx(tc, cpsr, scr, false); 720 if (fault == NoFault) { 721 PseudoInst::quiesce(tc); 722 } else { 723 PseudoInst::quiesceSkip(tc); 724 } 725 } 726 tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0); 727 ''' 728 wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \ 729 { "code" : wfiCode, "predicate_test" : predicateTest }, 730 ["IsNonSpeculative", "IsQuiesce", 731 "IsSerializeAfter", "IsUnverifiable"]) 732 header_output += BasicDeclare.subst(wfiIop) 733 decoder_output += BasicConstructor.subst(wfiIop) 734 exec_output += QuiescePredOpExecute.subst(wfiIop) 735 736 sevCode = ''' 737 SevMailbox = 1; 738 System *sys = xc->tcBase()->getSystemPtr(); 739 for (int x = 0; x < sys->numContexts(); x++) { 740 ThreadContext *oc = sys->getThreadContext(x); 741 if (oc == xc->tcBase()) 742 continue; 743 // Wake CPU with interrupt if they were sleeping 744 if (oc->readMiscReg(MISCREG_SEV_MAILBOX) == 0) { 745 // Post Interrupt and wake cpu if needed 746 oc->getCpuPtr()->postInterrupt(oc->threadId(), INT_SEV, 0); 747 } 748 } 749 ''' 750 sevIop = InstObjParams("sev", "SevInst", "PredOp", \ 751 { "code" : sevCode, "predicate_test" : predicateTest }, 752 ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"]) 753 header_output += BasicDeclare.subst(sevIop) 754 decoder_output += BasicConstructor.subst(sevIop) 755 exec_output += PredOpExecute.subst(sevIop) 756 757 sevlCode = ''' 758 SevMailbox = 1; 759 ''' 760 sevlIop = InstObjParams("sevl", "SevlInst", "PredOp", \ 761 { "code" : sevlCode, "predicate_test" : predicateTest }, 762 ["IsNonSpeculative", "IsSquashAfter", "IsUnverifiable"]) 763 header_output += BasicDeclare.subst(sevlIop) 764 decoder_output += BasicConstructor.subst(sevlIop) 765 exec_output += BasicExecute.subst(sevlIop) 766 767 itIop = InstObjParams("it", "ItInst", "PredOp", \ 768 { "code" : ";", 769 "predicate_test" : predicateTest }, []) 770 header_output += BasicDeclare.subst(itIop) 771 decoder_output += BasicConstructor.subst(itIop) 772 exec_output += PredOpExecute.subst(itIop) 773 unknownCode = ''' 774 return std::make_shared<UndefinedInstruction>(machInst, true); 775 ''' 776 unknownIop = InstObjParams("unknown", "Unknown", "UnknownOp", \ 777 { "code": unknownCode, 778 "predicate_test": predicateTest }) 779 header_output += BasicDeclare.subst(unknownIop) 780 decoder_output += BasicConstructor.subst(unknownIop) 781 exec_output += PredOpExecute.subst(unknownIop) 782 783 ubfxCode = ''' 784 Dest = bits(Op1, imm2, imm1); 785 ''' 786 ubfxIop = InstObjParams("ubfx", "Ubfx", "RegRegImmImmOp", 787 { "code": ubfxCode, 788 "predicate_test": predicateTest }, []) 789 header_output += RegRegImmImmOpDeclare.subst(ubfxIop) 790 decoder_output += RegRegImmImmOpConstructor.subst(ubfxIop) 791 exec_output += PredOpExecute.subst(ubfxIop) 792 793 sbfxCode = ''' 794 int32_t resTemp = bits(Op1, imm2, imm1); 795 Dest = resTemp | -(resTemp & (1 << (imm2 - imm1))); 796 ''' 797 sbfxIop = InstObjParams("sbfx", "Sbfx", "RegRegImmImmOp", 798 { "code": sbfxCode, 799 "predicate_test": predicateTest }, []) 800 header_output += RegRegImmImmOpDeclare.subst(sbfxIop) 801 decoder_output += RegRegImmImmOpConstructor.subst(sbfxIop) 802 exec_output += PredOpExecute.subst(sbfxIop) 803 804 bfcCode = ''' 805 Dest = Op1 & ~(mask(imm2 - imm1 + 1) << imm1); 806 ''' 807 bfcIop = InstObjParams("bfc", "Bfc", "RegRegImmImmOp", 808 { "code": bfcCode, 809 "predicate_test": predicateTest }, []) 810 header_output += RegRegImmImmOpDeclare.subst(bfcIop) 811 decoder_output += RegRegImmImmOpConstructor.subst(bfcIop) 812 exec_output += PredOpExecute.subst(bfcIop) 813 814 bfiCode = ''' 815 uint32_t bitMask = (mask(imm2 - imm1 + 1) << imm1); 816 Dest = ((Op1 << imm1) & bitMask) | (Dest & ~bitMask); 817 ''' 818 bfiIop = InstObjParams("bfi", "Bfi", "RegRegImmImmOp", 819 { "code": bfiCode, 820 "predicate_test": predicateTest }, []) 821 header_output += RegRegImmImmOpDeclare.subst(bfiIop) 822 decoder_output += RegRegImmImmOpConstructor.subst(bfiIop) 823 exec_output += PredOpExecute.subst(bfiIop) 824 825 mrc14code = ''' 826 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId( 827 RegId(MiscRegClass, op1)).index(); 828 bool can_read, undefined; 829 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr); 830 if (!can_read || undefined) { 831 return std::make_shared<UndefinedInstruction>(machInst, false, 832 mnemonic); 833 } 834 if (mcrMrc14TrapToHyp((const MiscRegIndex) op1, Hcr, Cpsr, Scr, Hdcr, 835 Hstr, Hcptr, imm)) { 836 return std::make_shared<HypervisorTrap>(machInst, imm, 837 EC_TRAPPED_CP14_MCR_MRC); 838 } 839 Dest = MiscOp1; 840 ''' 841 842 mrc14Iop = InstObjParams("mrc", "Mrc14", "RegRegImmOp", 843 { "code": mrc14code, 844 "predicate_test": predicateTest }, []) 845 header_output += RegRegImmOpDeclare.subst(mrc14Iop) 846 decoder_output += RegRegImmOpConstructor.subst(mrc14Iop) 847 exec_output += PredOpExecute.subst(mrc14Iop) 848 849 850 mcr14code = ''' 851 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId( 852 RegId(MiscRegClass, dest)).index(); 853 bool can_write, undefined; 854 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr); 855 if (undefined || !can_write) { 856 return std::make_shared<UndefinedInstruction>(machInst, false, 857 mnemonic); 858 } 859 if (mcrMrc14TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, 860 Hstr, Hcptr, imm)) { 861 return std::make_shared<HypervisorTrap>(machInst, imm, 862 EC_TRAPPED_CP14_MCR_MRC); 863 } 864 MiscDest = Op1; 865 ''' 866 mcr14Iop = InstObjParams("mcr", "Mcr14", "RegRegImmOp", 867 { "code": mcr14code, 868 "predicate_test": predicateTest }, 869 ["IsSerializeAfter","IsNonSpeculative"]) 870 header_output += RegRegImmOpDeclare.subst(mcr14Iop) 871 decoder_output += RegRegImmOpConstructor.subst(mcr14Iop) 872 exec_output += PredOpExecute.subst(mcr14Iop) 873 874 mrc15code = ''' 875 int preFlatOp1 = flattenMiscRegNsBanked(op1, xc->tcBase()); 876 MiscRegIndex miscReg = (MiscRegIndex) 877 xc->tcBase()->flattenRegId(RegId(MiscRegClass, 878 preFlatOp1)).index(); 879 bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr, 880 Hcptr, imm); 881 bool can_read, undefined; 882 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr); 883 // if we're in non secure PL1 mode then we can trap regargless of whether 884 // the register is accessable, in other modes we trap if only if the register 885 // IS accessable. 886 if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) && 887 !inSecureState(Scr, Cpsr)))) { 888 return std::make_shared<UndefinedInstruction>(machInst, false, 889 mnemonic); 890 } 891 if (hypTrap) { 892 return std::make_shared<HypervisorTrap>(machInst, imm, 893 EC_TRAPPED_CP15_MCR_MRC); 894 } 895 Dest = MiscNsBankedOp1; 896 ''' 897 898 mrc15Iop = InstObjParams("mrc", "Mrc15", "RegMiscRegImmOp", 899 { "code": mrc15code, 900 "predicate_test": predicateTest }, []) 901 header_output += RegMiscRegImmOpDeclare.subst(mrc15Iop) 902 decoder_output += RegMiscRegImmOpConstructor.subst(mrc15Iop) 903 exec_output += PredOpExecute.subst(mrc15Iop) 904 905 906 mcr15code = ''' 907 int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase()); 908 MiscRegIndex miscReg = (MiscRegIndex) 909 xc->tcBase()->flattenRegId(RegId(MiscRegClass, 910 preFlatDest)).index(); 911 bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr, 912 Hcptr, imm); 913 bool can_write, undefined; 914 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr); 915 916 // if we're in non secure PL1 mode then we can trap regargless of whether 917 // the register is accessable, in other modes we trap if only if the register 918 // IS accessable. 919 if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) && 920 !inSecureState(Scr, Cpsr)))) { 921 return std::make_shared<UndefinedInstruction>(machInst, false, 922 mnemonic); 923 } 924 if (hypTrap) { 925 return std::make_shared<HypervisorTrap>(machInst, imm, 926 EC_TRAPPED_CP15_MCR_MRC); 927 } 928 MiscNsBankedDest = Op1; 929 ''' 930 mcr15Iop = InstObjParams("mcr", "Mcr15", "MiscRegRegImmOp", 931 { "code": mcr15code, 932 "predicate_test": predicateTest }, 933 ["IsSerializeAfter","IsNonSpeculative"]) 934 header_output += MiscRegRegImmOpDeclare.subst(mcr15Iop) 935 decoder_output += MiscRegRegImmOpConstructor.subst(mcr15Iop) 936 exec_output += PredOpExecute.subst(mcr15Iop) 937 938 939 mrrc15code = ''' 940 int preFlatOp1 = flattenMiscRegNsBanked(op1, xc->tcBase()); 941 MiscRegIndex miscReg = (MiscRegIndex) 942 xc->tcBase()->flattenRegId(RegId(MiscRegClass, 943 preFlatOp1)).index(); 944 bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm); 945 bool can_read, undefined; 946 std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr); 947 // if we're in non secure PL1 mode then we can trap regargless of whether 948 // the register is accessable, in other modes we trap if only if the register 949 // IS accessable. 950 if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) && 951 !inSecureState(Scr, Cpsr)))) { 952 return std::make_shared<UndefinedInstruction>(machInst, false, 953 mnemonic); 954 } 955 if (hypTrap) { 956 return std::make_shared<HypervisorTrap>(machInst, imm, 957 EC_TRAPPED_CP15_MCRR_MRRC); 958 } 959 Dest = bits(MiscNsBankedOp164, 63, 32); 960 Dest2 = bits(MiscNsBankedOp164, 31, 0); 961 ''' 962 mrrc15Iop = InstObjParams("mrrc", "Mrrc15", "MrrcOp", 963 { "code": mrrc15code, 964 "predicate_test": predicateTest }, []) 965 header_output += MrrcOpDeclare.subst(mrrc15Iop) 966 decoder_output += MrrcOpConstructor.subst(mrrc15Iop) 967 exec_output += PredOpExecute.subst(mrrc15Iop) 968 969 970 mcrr15code = ''' 971 int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase()); 972 MiscRegIndex miscReg = (MiscRegIndex) 973 xc->tcBase()->flattenRegId(RegId(MiscRegClass, 974 preFlatDest)).index(); 975 bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm); 976 bool can_write, undefined; 977 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr); 978 979 // if we're in non secure PL1 mode then we can trap regargless of whether 980 // the register is accessable, in other modes we trap if only if the register 981 // IS accessable. 982 if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) && 983 !inSecureState(Scr, Cpsr)))) { 984 return std::make_shared<UndefinedInstruction>(machInst, false, 985 mnemonic); 986 } 987 if (hypTrap) { 988 return std::make_shared<HypervisorTrap>(machInst, imm, 989 EC_TRAPPED_CP15_MCRR_MRRC); 990 } 991 MiscNsBankedDest64 = ((uint64_t) Op1 << 32) | Op2; 992 ''' 993 mcrr15Iop = InstObjParams("mcrr", "Mcrr15", "McrrOp", 994 { "code": mcrr15code, 995 "predicate_test": predicateTest }, []) 996 header_output += McrrOpDeclare.subst(mcrr15Iop) 997 decoder_output += McrrOpConstructor.subst(mcrr15Iop) 998 exec_output += PredOpExecute.subst(mcrr15Iop) 999 1000 1001 enterxCode = ''' 1002 NextThumb = true; 1003 NextJazelle = true; 1004 ''' 1005 enterxIop = InstObjParams("enterx", "Enterx", "PredOp", 1006 { "code": enterxCode, 1007 "predicate_test": predicateTest }, []) 1008 header_output += BasicDeclare.subst(enterxIop) 1009 decoder_output += BasicConstructor.subst(enterxIop) 1010 exec_output += PredOpExecute.subst(enterxIop) 1011 1012 leavexCode = ''' 1013 NextThumb = true; 1014 NextJazelle = false; 1015 ''' 1016 leavexIop = InstObjParams("leavex", "Leavex", "PredOp", 1017 { "code": leavexCode, 1018 "predicate_test": predicateTest }, []) 1019 header_output += BasicDeclare.subst(leavexIop) 1020 decoder_output += BasicConstructor.subst(leavexIop) 1021 exec_output += PredOpExecute.subst(leavexIop) 1022 1023 setendCode = ''' 1024 CPSR cpsr = Cpsr; 1025 cpsr.e = imm; 1026 Cpsr = cpsr; 1027 fault = checkSETENDEnabled(xc->tcBase(), cpsr); 1028 ''' 1029 setendIop = InstObjParams("setend", "Setend", "ImmOp", 1030 { "code": setendCode, 1031 "predicate_test": predicateTest }, 1032 ["IsSerializeAfter","IsNonSpeculative"]) 1033 header_output += ImmOpDeclare.subst(setendIop) 1034 decoder_output += ImmOpConstructor.subst(setendIop) 1035 exec_output += PredOpExecute.subst(setendIop) 1036 1037 clrexCode = ''' 1038 LLSCLock = 0; 1039 ''' 1040 clrexIop = InstObjParams("clrex", "Clrex","PredOp", 1041 { "code": clrexCode, 1042 "predicate_test": predicateTest },[]) 1043 header_output += BasicDeclare.subst(clrexIop) 1044 decoder_output += BasicConstructor.subst(clrexIop) 1045 exec_output += PredOpExecute.subst(clrexIop) 1046 1047 McrDcCheckCode = ''' 1048 int preFlatDest = flattenMiscRegNsBanked(dest, xc->tcBase()); 1049 MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId( 1050 RegId(MiscRegClass, preFlatDest)).index(); 1051 bool hypTrap = mcrMrc15TrapToHyp(miscReg, Hcr, Cpsr, Scr, Hdcr, Hstr, 1052 Hcptr, imm); 1053 bool can_write, undefined; 1054 std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr); 1055 1056 // if we're in non secure PL1 mode then we can trap regardless 1057 // of whether the register is accessible, in other modes we 1058 // trap if only if the register IS accessible. 1059 if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) & 1060 !inSecureState(Scr, Cpsr)))) { 1061 return std::make_shared<UndefinedInstruction>(machInst, false, 1062 mnemonic); 1063 } 1064 if (hypTrap) { 1065 return std::make_shared<HypervisorTrap>(machInst, imm, 1066 EC_TRAPPED_CP15_MCR_MRC); 1067 } 1068 ''' 1069 1070 McrDcimvacCode = ''' 1071 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | 1072 Request::INVALIDATE | 1073 Request::DST_POC); 1074 EA = Op1; 1075 ''' 1076 McrDcimvacIop = InstObjParams("mcr dcimvac", "McrDcimvac", 1077 "MiscRegRegImmMemOp", 1078 {"memacc_code": McrDcCheckCode, 1079 "postacc_code": "", 1080 "ea_code": McrDcimvacCode, 1081 "predicate_test": predicateTest}, 1082 ['IsMemRef', 'IsStore']) 1083 header_output += MiscRegRegImmMemOpDeclare.subst(McrDcimvacIop) 1084 decoder_output += MiscRegRegImmOpConstructor.subst(McrDcimvacIop) 1085 exec_output += Mcr15Execute.subst(McrDcimvacIop) + \ 1086 Mcr15InitiateAcc.subst(McrDcimvacIop) + \ 1087 Mcr15CompleteAcc.subst(McrDcimvacIop) 1088 1089 McrDccmvacCode = ''' 1090 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | 1091 Request::CLEAN | 1092 Request::DST_POC); 1093 EA = Op1; 1094 ''' 1095 McrDccmvacIop = InstObjParams("mcr dccmvac", "McrDccmvac", 1096 "MiscRegRegImmMemOp", 1097 {"memacc_code": McrDcCheckCode, 1098 "postacc_code": "", 1099 "ea_code": McrDccmvacCode, 1100 "predicate_test": predicateTest}, 1101 ['IsMemRef', 'IsStore']) 1102 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvacIop) 1103 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvacIop) 1104 exec_output += Mcr15Execute.subst(McrDccmvacIop) + \ 1105 Mcr15InitiateAcc.subst(McrDccmvacIop) + \ 1106 Mcr15CompleteAcc.subst(McrDccmvacIop) 1107 1108 McrDccmvauCode = ''' 1109 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | 1110 Request::CLEAN | 1111 Request::DST_POU); 1112 EA = Op1; 1113 ''' 1114 McrDccmvauIop = InstObjParams("mcr dccmvau", "McrDccmvau", 1115 "MiscRegRegImmMemOp", 1116 {"memacc_code": McrDcCheckCode, 1117 "postacc_code": "", 1118 "ea_code": McrDccmvauCode, 1119 "predicate_test": predicateTest}, 1120 ['IsMemRef', 'IsStore']) 1121 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccmvauIop) 1122 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccmvauIop) 1123 exec_output += Mcr15Execute.subst(McrDccmvauIop) + \ 1124 Mcr15InitiateAcc.subst(McrDccmvauIop) + \ 1125 Mcr15CompleteAcc.subst(McrDccmvauIop) 1126 1127 McrDccimvacCode = ''' 1128 const Request::Flags memAccessFlags(ArmISA::TLB::MustBeOne | 1129 Request::CLEAN | 1130 Request::INVALIDATE | 1131 Request::DST_POC); 1132 EA = Op1; 1133 ''' 1134 McrDccimvacIop = InstObjParams("mcr dccimvac", "McrDccimvac", 1135 "MiscRegRegImmMemOp", 1136 {"memacc_code": McrDcCheckCode, 1137 "postacc_code": "", 1138 "ea_code": McrDccimvacCode, 1139 "predicate_test": predicateTest}, 1140 ['IsMemRef', 'IsStore']) 1141 header_output += MiscRegRegImmMemOpDeclare.subst(McrDccimvacIop) 1142 decoder_output += MiscRegRegImmOpConstructor.subst(McrDccimvacIop) 1143 exec_output += Mcr15Execute.subst(McrDccimvacIop) + \ 1144 Mcr15InitiateAcc.subst(McrDccimvacIop) + \ 1145 Mcr15CompleteAcc.subst(McrDccimvacIop) 1146 1147 isbCode = ''' 1148 // If the barrier is due to a CP15 access check for hyp traps 1149 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15ISB, Hcr, Cpsr, Scr, 1150 Hdcr, Hstr, Hcptr, imm)) { 1151 return std::make_shared<HypervisorTrap>(machInst, imm, 1152 EC_TRAPPED_CP15_MCR_MRC); 1153 } 1154 ''' 1155 isbIop = InstObjParams("isb", "Isb", "ImmOp", 1156 {"code": isbCode, 1157 "predicate_test": predicateTest}, 1158 ['IsSquashAfter']) 1159 header_output += ImmOpDeclare.subst(isbIop) 1160 decoder_output += ImmOpConstructor.subst(isbIop) 1161 exec_output += PredOpExecute.subst(isbIop) 1162 1163 dsbCode = ''' 1164 // If the barrier is due to a CP15 access check for hyp traps 1165 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15DSB, Hcr, Cpsr, Scr, 1166 Hdcr, Hstr, Hcptr, imm)) { 1167 return std::make_shared<HypervisorTrap>(machInst, imm, 1168 EC_TRAPPED_CP15_MCR_MRC); 1169 } 1170 ''' 1171 dsbIop = InstObjParams("dsb", "Dsb", "ImmOp", 1172 {"code": dsbCode, 1173 "predicate_test": predicateTest}, 1174 ['IsMemBarrier', 'IsSerializeAfter']) 1175 header_output += ImmOpDeclare.subst(dsbIop) 1176 decoder_output += ImmOpConstructor.subst(dsbIop) 1177 exec_output += PredOpExecute.subst(dsbIop) 1178 1179 dmbCode = ''' 1180 // If the barrier is due to a CP15 access check for hyp traps 1181 if ((imm != 0) && mcrMrc15TrapToHyp(MISCREG_CP15DMB, Hcr, Cpsr, Scr, 1182 Hdcr, Hstr, Hcptr, imm)) { 1183 return std::make_shared<HypervisorTrap>(machInst, imm, 1184 EC_TRAPPED_CP15_MCR_MRC); 1185 } 1186 ''' 1187 dmbIop = InstObjParams("dmb", "Dmb", "ImmOp", 1188 {"code": dmbCode, 1189 "predicate_test": predicateTest}, 1190 ['IsMemBarrier']) 1191 header_output += ImmOpDeclare.subst(dmbIop) 1192 decoder_output += ImmOpConstructor.subst(dmbIop) 1193 exec_output += PredOpExecute.subst(dmbIop) 1194 1195 dbgCode = ''' 1196 ''' 1197 dbgIop = InstObjParams("dbg", "Dbg", "PredOp", 1198 {"code": dbgCode, 1199 "predicate_test": predicateTest}) 1200 header_output += BasicDeclare.subst(dbgIop) 1201 decoder_output += BasicConstructor.subst(dbgIop) 1202 exec_output += PredOpExecute.subst(dbgIop) 1203 1204 cpsCode = ''' 1205 uint32_t mode = bits(imm, 4, 0); 1206 uint32_t f = bits(imm, 5); 1207 uint32_t i = bits(imm, 6); 1208 uint32_t a = bits(imm, 7); 1209 bool setMode = bits(imm, 8); 1210 bool enable = bits(imm, 9); 1211 CPSR cpsr = Cpsr; 1212 SCTLR sctlr = Sctlr; 1213 if (cpsr.mode != MODE_USER) { 1214 if (enable) { 1215 if (f) cpsr.f = 0; 1216 if (i) cpsr.i = 0; 1217 if (a) cpsr.a = 0; 1218 } else { 1219 if (f && !sctlr.nmfi) cpsr.f = 1; 1220 if (i) cpsr.i = 1; 1221 if (a) cpsr.a = 1; 1222 } 1223 if (setMode) { 1224 cpsr.mode = mode; 1225 } 1226 } 1227 Cpsr = cpsr; 1228 ''' 1229 cpsIop = InstObjParams("cps", "Cps", "ImmOp", 1230 { "code": cpsCode, 1231 "predicate_test": predicateTest }, 1232 ["IsSerializeAfter","IsNonSpeculative"]) 1233 header_output += ImmOpDeclare.subst(cpsIop) 1234 decoder_output += ImmOpConstructor.subst(cpsIop) 1235 exec_output += PredOpExecute.subst(cpsIop) 1236}}; 1237