mem.isa revision 2686
1// -*- mode:c++ -*- 2 3// Copyright (c) 2003-2005 The Regents of The University of Michigan 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: Gabe Black 30// Korey Sewell 31 32//////////////////////////////////////////////////////////////////// 33// 34// Memory-format instructions: LoadAddress, Load, Store 35// 36 37output header {{ 38 /** 39 * Base class for general Mips memory-format instructions. 40 */ 41 class Memory : public MipsStaticInst 42 { 43 protected: 44 45 /// Memory request flags. See mem_req_base.hh. 46 unsigned memAccessFlags; 47 /// Pointer to EAComp object. 48 const StaticInstPtr eaCompPtr; 49 /// Pointer to MemAcc object. 50 const StaticInstPtr memAccPtr; 51 52 /// Displacement for EA calculation (signed). 53 int32_t disp; 54 55 /// Constructor 56 Memory(const char *mnem, MachInst _machInst, OpClass __opClass, 57 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 58 StaticInstPtr _memAccPtr = nullStaticInstPtr) 59 : MipsStaticInst(mnem, _machInst, __opClass), 60 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), 61 disp(OFFSET) 62 { 63 //If Bit 15 is 1 then Sign Extend 64 int32_t temp = disp & 0x00008000; 65 66 if (temp > 0) { 67 disp |= 0xFFFF0000; 68 } 69 } 70 71 std::string 72 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 73 74 public: 75 76 const StaticInstPtr &eaCompInst() const { return eaCompPtr; } 77 const StaticInstPtr &memAccInst() const { return memAccPtr; } 78 }; 79 80}}; 81 82 83output decoder {{ 84 std::string 85 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 86 { 87 return csprintf("%-10s %c%d,%d(r%d)", mnemonic, 88 flags[IsFloating] ? 'f' : 'r', RT, disp, RS); 89 } 90 91}}; 92 93def template LoadStoreDeclare {{ 94 /** 95 * Static instruction class for "%(mnemonic)s". 96 */ 97 class %(class_name)s : public %(base_class)s 98 { 99 protected: 100 101 /** 102 * "Fake" effective address computation class for "%(mnemonic)s". 103 */ 104 class EAComp : public %(base_class)s 105 { 106 public: 107 /// Constructor 108 EAComp(MachInst machInst); 109 110 %(BasicExecDeclare)s 111 }; 112 113 /** 114 * "Fake" memory access instruction class for "%(mnemonic)s". 115 */ 116 class MemAcc : public %(base_class)s 117 { 118 public: 119 /// Constructor 120 MemAcc(MachInst machInst); 121 122 %(BasicExecDeclare)s 123 }; 124 125 public: 126 127 /// Constructor. 128 %(class_name)s(MachInst machInst); 129 130 %(BasicExecDeclare)s 131 132 %(InitiateAccDeclare)s 133 134 %(CompleteAccDeclare)s 135 }; 136}}; 137 138 139def template InitiateAccDeclare {{ 140 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 141}}; 142 143 144def template CompleteAccDeclare {{ 145 Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; 146}}; 147 148 149def template LoadStoreConstructor {{ 150 /** TODO: change op_class to AddrGenOp or something (requires 151 * creating new member of OpClass enum in op_class.hh, updating 152 * config files, etc.). */ 153 inline %(class_name)s::EAComp::EAComp(MachInst machInst) 154 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 155 { 156 %(ea_constructor)s; 157 } 158 159 inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) 160 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 161 { 162 %(memacc_constructor)s; 163 } 164 165 inline %(class_name)s::%(class_name)s(MachInst machInst) 166 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 167 new EAComp(machInst), new MemAcc(machInst)) 168 { 169 %(constructor)s; 170 } 171}}; 172 173 174def template EACompExecute {{ 175 Fault 176 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 177 Trace::InstRecord *traceData) const 178 { 179 Addr EA; 180 Fault fault = NoFault; 181 182 %(fp_enable_check)s; 183 %(op_decl)s; 184 %(op_rd)s; 185 %(code)s; 186 187 if (fault == NoFault) { 188 %(op_wb)s; 189 xc->setEA(EA); 190 } 191 192 return fault; 193 } 194}}; 195 196def template LoadMemAccExecute {{ 197 Fault 198 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 199 Trace::InstRecord *traceData) const 200 { 201 Addr EA; 202 Fault fault = NoFault; 203 204 %(fp_enable_check)s; 205 %(op_decl)s; 206 %(op_rd)s; 207 EA = xc->getEA(); 208 209 if (fault == NoFault) { 210 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 211 %(code)s; 212 } 213 214 if (fault == NoFault) { 215 %(op_wb)s; 216 } 217 218 return fault; 219 } 220}}; 221 222 223def template LoadExecute {{ 224 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 225 Trace::InstRecord *traceData) const 226 { 227 Addr EA; 228 Fault fault = NoFault; 229 230 %(fp_enable_check)s; 231 %(op_decl)s; 232 %(op_rd)s; 233 %(ea_code)s; 234 235 if (fault == NoFault) { 236 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 237 %(memacc_code)s; 238 } 239 240 if (fault == NoFault) { 241 %(op_wb)s; 242 } 243 244 return fault; 245 } 246}}; 247 248 249def template LoadInitiateAcc {{ 250 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 251 Trace::InstRecord *traceData) const 252 { 253 Addr EA; 254 Fault fault = NoFault; 255 256 %(fp_enable_check)s; 257 %(op_src_decl)s; 258 %(op_rd)s; 259 %(ea_code)s; 260 261 if (fault == NoFault) { 262 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 263 } 264 265 return fault; 266 } 267}}; 268 269 270def template LoadCompleteAcc {{ 271 Fault %(class_name)s::completeAcc(uint8_t *data, 272 %(CPU_exec_context)s *xc, 273 Trace::InstRecord *traceData) const 274 { 275 Fault fault = NoFault; 276 277 %(fp_enable_check)s; 278 %(op_decl)s; 279 280 memcpy(&Mem, data, sizeof(Mem)); 281 282 if (fault == NoFault) { 283 %(memacc_code)s; 284 } 285 286 if (fault == NoFault) { 287 %(op_wb)s; 288 } 289 290 return fault; 291 } 292}}; 293 294 295def template StoreMemAccExecute {{ 296 Fault 297 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 298 Trace::InstRecord *traceData) const 299 { 300 Addr EA; 301 Fault fault = NoFault; 302 uint64_t write_result = 0; 303 304 %(fp_enable_check)s; 305 %(op_decl)s; 306 %(op_rd)s; 307 EA = xc->getEA(); 308 309 if (fault == NoFault) { 310 %(code)s; 311 } 312 313 if (fault == NoFault) { 314 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 315 memAccessFlags, &write_result); 316 if (traceData) { traceData->setData(Mem); } 317 } 318 319 if (fault == NoFault) { 320 %(postacc_code)s; 321 } 322 323 if (fault == NoFault) { 324 %(op_wb)s; 325 } 326 327 return fault; 328 } 329}}; 330 331 332def template StoreExecute {{ 333 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 334 Trace::InstRecord *traceData) const 335 { 336 Addr EA; 337 Fault fault = NoFault; 338 uint64_t write_result = 0; 339 340 %(fp_enable_check)s; 341 %(op_decl)s; 342 %(op_rd)s; 343 %(ea_code)s; 344 345 if (fault == NoFault) { 346 %(memacc_code)s; 347 } 348 349 if (fault == NoFault) { 350 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 351 memAccessFlags, &write_result); 352 if (traceData) { traceData->setData(Mem); } 353 } 354 355 if (fault == NoFault) { 356 %(postacc_code)s; 357 } 358 359 if (fault == NoFault) { 360 %(op_wb)s; 361 } 362 363 return fault; 364 } 365}}; 366 367def template StoreInitiateAcc {{ 368 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 369 Trace::InstRecord *traceData) const 370 { 371 Addr EA; 372 Fault fault = NoFault; 373 uint64_t write_result = 0; 374 375 %(fp_enable_check)s; 376 %(op_decl)s; 377 %(op_rd)s; 378 %(ea_code)s; 379 380 if (fault == NoFault) { 381 %(memacc_code)s; 382 } 383 384 if (fault == NoFault) { 385 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 386 memAccessFlags, &write_result); 387 if (traceData) { traceData->setData(Mem); } 388 } 389 390 return fault; 391 } 392}}; 393 394 395def template StoreCompleteAcc {{ 396 Fault %(class_name)s::completeAcc(uint8_t *data, 397 %(CPU_exec_context)s *xc, 398 Trace::InstRecord *traceData) const 399 { 400 Fault fault = NoFault; 401 uint64_t write_result = 0; 402 403 %(fp_enable_check)s; 404 %(op_dest_decl)s; 405 406 memcpy(&write_result, data, sizeof(write_result)); 407 408 if (fault == NoFault) { 409 %(postacc_code)s; 410 } 411 412 if (fault == NoFault) { 413 %(op_wb)s; 414 } 415 416 return fault; 417 } 418}}; 419 420 421def template MiscMemAccExecute {{ 422 Fault %(class_name)s::MemAcc::execute(%(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 = xc->getEA(); 432 433 if (fault == NoFault) { 434 %(code)s; 435 } 436 437 return NoFault; 438 } 439}}; 440 441def template MiscExecute {{ 442 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 443 Trace::InstRecord *traceData) const 444 { 445 Addr EA; 446 Fault fault = NoFault; 447 448 %(fp_enable_check)s; 449 %(op_decl)s; 450 %(op_rd)s; 451 %(ea_code)s; 452 453 if (fault == NoFault) { 454 %(memacc_code)s; 455 } 456 457 return NoFault; 458 } 459}}; 460 461def template MiscInitiateAcc {{ 462 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 463 Trace::InstRecord *traceData) const 464 { 465 panic("Misc instruction does not support split access method!"); 466 return NoFault; 467 } 468}}; 469 470 471def template MiscCompleteAcc {{ 472 Fault %(class_name)s::completeAcc(uint8_t *data, 473 %(CPU_exec_context)s *xc, 474 Trace::InstRecord *traceData) const 475 { 476 panic("Misc instruction does not support split access method!"); 477 478 return NoFault; 479 } 480}}; 481 482// load instructions use Rt as dest, so check for 483// Rt == 0 to detect nops 484def template LoadNopCheckDecode {{ 485 { 486 MipsStaticInst *i = new %(class_name)s(machInst); 487 if (RT == 0) { 488 i = makeNop(i); 489 } 490 return i; 491 } 492}}; 493 494def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 495 mem_flags = [], inst_flags = []) {{ 496 (header_output, decoder_output, decode_block, exec_output) = \ 497 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 498 decode_template = LoadNopCheckDecode, 499 exec_template_base = 'Load') 500}}; 501 502def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 503 mem_flags = [], inst_flags = []) {{ 504 (header_output, decoder_output, decode_block, exec_output) = \ 505 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 506 exec_template_base = 'Store') 507}}; 508 509def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }}, 510 mem_flags = [], inst_flags = []) {{ 511 (header_output, decoder_output, decode_block, exec_output) = \ 512 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 513 decode_template = LoadNopCheckDecode, 514 exec_template_base = 'Load') 515}}; 516 517def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }}, 518 mem_flags = [], inst_flags = []) {{ 519 (header_output, decoder_output, decode_block, exec_output) = \ 520 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 521 exec_template_base = 'Store') 522}}; 523 524def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }}, 525 mem_flags = [], inst_flags = []) {{ 526 decl_code = 'uint32_t mem_word = Mem.uw;\n' 527 decl_code += 'uint32_t unalign_addr = Rs + disp;\n' 528 decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n' 529 decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n' 530 decl_code += '\tbyte_offset ^= 3;\n' 531 decl_code += '#endif\n' 532 533 memacc_code = decl_code + memacc_code 534 535 (header_output, decoder_output, decode_block, exec_output) = \ 536 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 537 decode_template = LoadNopCheckDecode, 538 exec_template_base = 'Load') 539}}; 540 541def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }}, 542 mem_flags = [], inst_flags = []) {{ 543 decl_code = 'uint32_t mem_word = 0;\n' 544 decl_code += 'uint32_t unaligned_addr = Rs + disp;\n' 545 decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n' 546 decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n' 547 decl_code += '\tbyte_offset ^= 3;\n' 548 decl_code += '#endif\n' 549 decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n' 550 memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n' 551 552 (header_output, decoder_output, decode_block, exec_output) = \ 553 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 554 decode_template = LoadNopCheckDecode, 555 exec_template_base = 'Store') 556}}; 557 558def format Prefetch(ea_code = {{ EA = Rs + disp; }}, 559 mem_flags = [], pf_flags = [], inst_flags = []) {{ 560 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] 561 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 562 'IsDataPrefetch', 'MemReadOp'] 563 564 (header_output, decoder_output, decode_block, exec_output) = \ 565 LoadStoreBase(name, Name, ea_code, 566 'xc->prefetch(EA, memAccessFlags);', 567 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 568 569}}; 570 571def format StoreCond(memacc_code, postacc_code, 572 ea_code = {{ EA = Rs + disp; }}, 573 mem_flags = [], inst_flags = []) {{ 574 (header_output, decoder_output, decode_block, exec_output) = \ 575 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 576 postacc_code, exec_template_base = 'Store') 577}}; 578