mem.isa revision 6019
1// -*- mode:c++ -*- 2 3// Copyright (c) 2007-2008 The Florida State University 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Stephen Hines 30 31//////////////////////////////////////////////////////////////////// 32// 33// Memory-format instructions 34// 35 36output header {{ 37 /** 38 * Base class for general Arm memory-format instructions. 39 */ 40 class Memory : public PredOp 41 { 42 protected: 43 44 /// Memory request flags. See mem_req_base.hh. 45 unsigned memAccessFlags; 46 /// Pointer to EAComp object. 47 const StaticInstPtr eaCompPtr; 48 /// Pointer to MemAcc object. 49 const StaticInstPtr memAccPtr; 50 51 /// Displacement for EA calculation (signed). 52 int32_t disp; 53 int32_t disp8; 54 int32_t up; 55 int32_t hilo, 56 shift_size, 57 shift; 58 59 /// Constructor 60 Memory(const char *mnem, MachInst _machInst, OpClass __opClass, 61 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 62 StaticInstPtr _memAccPtr = nullStaticInstPtr) 63 : PredOp(mnem, _machInst, __opClass), 64 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), 65 disp(IMMED_11_0), disp8(IMMED_7_0 << 2), up(UP), 66 hilo((IMMED_HI_11_8 << 4) | IMMED_LO_3_0), 67 shift_size(SHIFT_SIZE), shift(SHIFT) 68 { 69 // When Up is not set, then we must subtract by the displacement 70 if (!up) 71 { 72 disp = -disp; 73 disp8 = -disp8; 74 hilo = -hilo; 75 } 76 } 77 78 std::string 79 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 80 81 public: 82 83 const StaticInstPtr &eaCompInst() const { return eaCompPtr; } 84 const StaticInstPtr &memAccInst() const { return memAccPtr; } 85 }; 86 87 /** 88 * Base class for a few miscellaneous memory-format insts 89 * that don't interpret the disp field 90 */ 91 class MemoryNoDisp : public Memory 92 { 93 protected: 94 /// Constructor 95 MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 96 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 97 StaticInstPtr _memAccPtr = nullStaticInstPtr) 98 : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr) 99 { 100 } 101 102 std::string 103 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 104 }; 105}}; 106 107 108output decoder {{ 109 std::string 110 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 111 { 112 return csprintf("%-10s", mnemonic); 113 } 114 115 std::string 116 MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 117 { 118 return csprintf("%-10s", mnemonic); 119 } 120}}; 121 122def template LoadStoreDeclare {{ 123 /** 124 * Static instruction class for "%(mnemonic)s". 125 */ 126 class %(class_name)s : public %(base_class)s 127 { 128 protected: 129 130 /** 131 * "Fake" effective address computation class for "%(mnemonic)s". 132 */ 133 class EAComp : public %(base_class)s 134 { 135 public: 136 /// Constructor 137 EAComp(MachInst machInst); 138 139 %(BasicExecDeclare)s 140 }; 141 142 /** 143 * "Fake" memory access instruction class for "%(mnemonic)s". 144 */ 145 class MemAcc : public %(base_class)s 146 { 147 public: 148 /// Constructor 149 MemAcc(MachInst machInst); 150 151 %(BasicExecDeclare)s 152 }; 153 154 public: 155 156 /// Constructor. 157 %(class_name)s(MachInst machInst); 158 159 %(BasicExecDeclare)s 160 161 %(InitiateAccDeclare)s 162 163 %(CompleteAccDeclare)s 164 }; 165}}; 166 167 168def template InitiateAccDeclare {{ 169 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 170}}; 171 172 173def template CompleteAccDeclare {{ 174 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; 175}}; 176 177 178def template EACompConstructor {{ 179 inline %(class_name)s::EAComp::EAComp(MachInst machInst) 180 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 181 { 182 %(constructor)s; 183 } 184}}; 185 186 187def template MemAccConstructor {{ 188 inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) 189 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 190 { 191 %(constructor)s; 192 } 193}}; 194 195 196def template LoadStoreConstructor {{ 197 inline %(class_name)s::%(class_name)s(MachInst machInst) 198 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 199 new EAComp(machInst), new MemAcc(machInst)) 200 { 201 %(constructor)s; 202 } 203}}; 204 205 206def template EACompExecute {{ 207 Fault 208 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 209 Trace::InstRecord *traceData) const 210 { 211 Addr EA; 212 Fault fault = NoFault; 213 214 %(fp_enable_check)s; 215 %(op_decl)s; 216 %(op_rd)s; 217 %(ea_code)s; 218 219 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 220 { 221 if (fault == NoFault) { 222 %(op_wb)s; 223 xc->setEA(EA); 224 } 225 } 226 227 return fault; 228 } 229}}; 230 231def template LoadMemAccExecute {{ 232 Fault 233 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 234 Trace::InstRecord *traceData) const 235 { 236 Addr EA; 237 Fault fault = NoFault; 238 239 %(fp_enable_check)s; 240 %(op_decl)s; 241 %(op_rd)s; 242 EA = xc->getEA(); 243 244 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 245 { 246 if (fault == NoFault) { 247 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 248 %(memacc_code)s; 249 } 250 251 if (fault == NoFault) { 252 %(op_wb)s; 253 } 254 } 255 256 return fault; 257 } 258}}; 259 260 261def template LoadExecute {{ 262 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 263 Trace::InstRecord *traceData) const 264 { 265 Addr EA; 266 Fault fault = NoFault; 267 268 %(fp_enable_check)s; 269 %(op_decl)s; 270 %(op_rd)s; 271 %(ea_code)s; 272 273 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 274 { 275 if (fault == NoFault) { 276 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 277 %(memacc_code)s; 278 } 279 280 if (fault == NoFault) { 281 %(op_wb)s; 282 } 283 } 284 285 return fault; 286 } 287}}; 288 289 290def template LoadInitiateAcc {{ 291 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 292 Trace::InstRecord *traceData) const 293 { 294 Addr EA; 295 Fault fault = NoFault; 296 297 %(fp_enable_check)s; 298 %(op_src_decl)s; 299 %(op_rd)s; 300 %(ea_code)s; 301 302 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 303 { 304 if (fault == NoFault) { 305 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 306 } 307 } 308 309 return fault; 310 } 311}}; 312 313 314def template LoadCompleteAcc {{ 315 Fault %(class_name)s::completeAcc(PacketPtr pkt, 316 %(CPU_exec_context)s *xc, 317 Trace::InstRecord *traceData) const 318 { 319 Fault fault = NoFault; 320 321 %(fp_enable_check)s; 322 %(op_decl)s; 323 %(op_rd)s; 324 325 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 326 { 327 // ARM instructions will not have a pkt if the predicate is false 328 Mem = pkt->get<typeof(Mem)>(); 329 330 if (fault == NoFault) { 331 %(memacc_code)s; 332 } 333 334 if (fault == NoFault) { 335 %(op_wb)s; 336 } 337 } 338 339 return fault; 340 } 341}}; 342 343 344def template StoreMemAccExecute {{ 345 Fault 346 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 347 Trace::InstRecord *traceData) const 348 { 349 Addr EA; 350 Fault fault = NoFault; 351 352 %(fp_enable_check)s; 353 %(op_decl)s; 354 %(op_rd)s; 355 356 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 357 { 358 EA = xc->getEA(); 359 360 if (fault == NoFault) { 361 %(postacc_code)s; 362 } 363 364 if (fault == NoFault) { 365 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 366 memAccessFlags, NULL); 367 if (traceData) { traceData->setData(Mem); } 368 } 369 370 if (fault == NoFault) { 371 %(postacc_code)s; 372 } 373 374 if (fault == NoFault) { 375 %(op_wb)s; 376 } 377 } 378 379 return fault; 380 } 381}}; 382 383 384def template StoreExecute {{ 385 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 386 Trace::InstRecord *traceData) const 387 { 388 Addr EA; 389 Fault fault = NoFault; 390 391 %(fp_enable_check)s; 392 %(op_decl)s; 393 %(op_rd)s; 394 %(ea_code)s; 395 396 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 397 { 398 if (fault == NoFault) { 399 %(memacc_code)s; 400 } 401 402 if (fault == NoFault) { 403 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 404 memAccessFlags, NULL); 405 if (traceData) { traceData->setData(Mem); } 406 } 407 408 if (fault == NoFault) { 409 %(postacc_code)s; 410 } 411 412 if (fault == NoFault) { 413 %(op_wb)s; 414 } 415 } 416 417 return fault; 418 } 419}}; 420 421def template StoreInitiateAcc {{ 422 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 423 Trace::InstRecord *traceData) const 424 { 425 Addr EA; 426 Fault fault = NoFault; 427 428 %(fp_enable_check)s; 429 %(op_decl)s; 430 %(op_rd)s; 431 %(ea_code)s; 432 433 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 434 { 435 if (fault == NoFault) { 436 %(memacc_code)s; 437 } 438 439 if (fault == NoFault) { 440 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 441 memAccessFlags, NULL); 442 if (traceData) { traceData->setData(Mem); } 443 } 444 445 // Need to write back any potential address register update 446 if (fault == NoFault) { 447 %(op_wb)s; 448 } 449 } 450 451 return fault; 452 } 453}}; 454 455 456def template StoreCompleteAcc {{ 457 Fault %(class_name)s::completeAcc(PacketPtr pkt, 458 %(CPU_exec_context)s *xc, 459 Trace::InstRecord *traceData) const 460 { 461 Fault fault = NoFault; 462 463 %(fp_enable_check)s; 464 %(op_dest_decl)s; 465 466 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 467 { 468 if (fault == NoFault) { 469 %(postacc_code)s; 470 } 471 472 if (fault == NoFault) { 473 %(op_wb)s; 474 } 475 } 476 477 return fault; 478 } 479}}; 480 481def template StoreCondCompleteAcc {{ 482 Fault %(class_name)s::completeAcc(PacketPtr pkt, 483 %(CPU_exec_context)s *xc, 484 Trace::InstRecord *traceData) const 485 { 486 Fault fault = NoFault; 487 488 %(fp_enable_check)s; 489 %(op_dest_decl)s; 490 491 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 492 { 493 if (fault == NoFault) { 494 %(postacc_code)s; 495 } 496 497 if (fault == NoFault) { 498 %(op_wb)s; 499 } 500 } 501 502 return fault; 503 } 504}}; 505 506 507def template MiscMemAccExecute {{ 508 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 509 Trace::InstRecord *traceData) const 510 { 511 Addr EA; 512 Fault fault = NoFault; 513 514 %(fp_enable_check)s; 515 %(op_decl)s; 516 %(op_rd)s; 517 518 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 519 { 520 EA = xc->getEA(); 521 522 if (fault == NoFault) { 523 %(memacc_code)s; 524 } 525 } 526 527 return NoFault; 528 } 529}}; 530 531def template MiscExecute {{ 532 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 533 Trace::InstRecord *traceData) const 534 { 535 Addr EA; 536 Fault fault = NoFault; 537 538 %(fp_enable_check)s; 539 %(op_decl)s; 540 %(op_rd)s; 541 %(ea_code)s; 542 543 if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) 544 { 545 if (fault == NoFault) { 546 %(memacc_code)s; 547 } 548 } 549 550 return NoFault; 551 } 552}}; 553 554def template MiscInitiateAcc {{ 555 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 556 Trace::InstRecord *traceData) const 557 { 558 panic("Misc instruction does not support split access method!"); 559 return NoFault; 560 } 561}}; 562 563 564def template MiscCompleteAcc {{ 565 Fault %(class_name)s::completeAcc(PacketPtr pkt, 566 %(CPU_exec_context)s *xc, 567 Trace::InstRecord *traceData) const 568 { 569 panic("Misc instruction does not support split access method!"); 570 571 return NoFault; 572 } 573}}; 574 575def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, 576 mem_flags = [], inst_flags = []) {{ 577 ea_code = ArmGenericCodeSubs(ea_code) 578 memacc_code = ArmGenericCodeSubs(memacc_code) 579 (header_output, decoder_output, decode_block, exec_output) = \ 580 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 581 decode_template = BasicDecode, 582 exec_template_base = 'Load') 583}}; 584 585def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, 586 mem_flags = [], inst_flags = []) {{ 587 ea_code = ArmGenericCodeSubs(ea_code) 588 memacc_code = ArmGenericCodeSubs(memacc_code) 589 (header_output, decoder_output, decode_block, exec_output) = \ 590 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 591 exec_template_base = 'Store') 592}}; 593 594