mem.isa revision 6192
12SN/A// -*- mode:c++ -*- 211071SN/A 311071SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan 411071SN/A// All rights reserved. 511071SN/A// 611071SN/A// Redistribution and use in source and binary forms, with or without 711071SN/A// modification, are permitted provided that the following conditions are 811071SN/A// met: redistributions of source code must retain the above copyright 911071SN/A// notice, this list of conditions and the following disclaimer; 1011071SN/A// redistributions in binary form must reproduce the above copyright 1111071SN/A// notice, this list of conditions and the following disclaimer in the 1211071SN/A// documentation and/or other materials provided with the distribution; 1311071SN/A// neither the name of the copyright holders nor the names of its 141762SN/A// contributors may be used to endorse or promote products derived from 152SN/A// this software without specific prior written permission. 162SN/A// 172SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282SN/A// 292SN/A// Authors: Steve Reinhardt 302SN/A// Kevin Lim 312SN/A 322SN/A//////////////////////////////////////////////////////////////////// 332SN/A// 342SN/A// Memory-format instructions: LoadAddress, Load, Store 352SN/A// 362SN/A 372SN/Aoutput header {{ 382SN/A /** 392665SN/A * Base class for general Alpha memory-format instructions. 402665SN/A */ 412665SN/A class Memory : public AlphaStaticInst 422SN/A { 432SN/A protected: 442SN/A 452SN/A /// Memory request flags. See mem_req_base.hh. 462SN/A Request::Flags memAccessFlags; 472SN/A 4811263Sandreas.sandberg@arm.com /// Constructor 4911263Sandreas.sandberg@arm.com Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 50146SN/A : AlphaStaticInst(mnem, _machInst, __opClass) 512SN/A { 522SN/A } 532SN/A 542SN/A std::string 551954SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 56146SN/A }; 578232SN/A 588232SN/A /** 5911263Sandreas.sandberg@arm.com * Base class for memory-format instructions using a 32-bit 6011263Sandreas.sandberg@arm.com * displacement (i.e. most of them). 6111263Sandreas.sandberg@arm.com */ 624762SN/A class MemoryDisp32 : public Memory 638229SN/A { 641078SN/A protected: 651078SN/A /// Displacement for EA calculation (signed). 662SN/A int32_t disp; 672SN/A 682SN/A /// Constructor. 694981SN/A MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 704981SN/A : Memory(mnem, _machInst, __opClass), 712SN/A disp(MEMDISP) 725034SN/A { 735034SN/A } 745034SN/A }; 755034SN/A 762SN/A 774981SN/A /** 784981SN/A * Base class for a few miscellaneous memory-format insts 794981SN/A * that don't interpret the disp field: wh64, fetch, fetch_m, ecb. 802SN/A * None of these instructions has a destination register either. 812SN/A */ 822SN/A class MemoryNoDisp : public Memory 832SN/A { 841435SN/A protected: 851435SN/A /// Constructor 862SN/A MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) 871435SN/A : Memory(mnem, _machInst, __opClass) 881435SN/A { 892SN/A } 902SN/A 914981SN/A std::string 924981SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 934981SN/A }; 944981SN/A}}; 954981SN/A 964981SN/A 974981SN/Aoutput decoder {{ 984981SN/A std::string 994981SN/A Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1004981SN/A { 1014981SN/A return csprintf("%-10s %c%d,%d(r%d)", mnemonic, 1024981SN/A flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB); 1034981SN/A } 1044981SN/A 1054981SN/A std::string 1064981SN/A MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1074981SN/A { 108633SN/A return csprintf("%-10s (r%d)", mnemonic, RB); 1092SN/A } 1102SN/A}}; 1112SN/A 1122SN/Adef format LoadAddress(code) {{ 1132SN/A iop = InstObjParams(name, Name, 'MemoryDisp32', code) 1142SN/A header_output = BasicDeclare.subst(iop) 1151435SN/A decoder_output = BasicConstructor.subst(iop) 1161954SN/A decode_block = BasicDecode.subst(iop) 1171435SN/A exec_output = BasicExecute.subst(iop) 1181954SN/A}}; 11912087Sspwilson2@wisc.edu 12012087Sspwilson2@wisc.edu 1211435SN/Adef template LoadStoreDeclare {{ 1222SN/A /** 1232SN/A * Static instruction class for "%(mnemonic)s". 12410905SN/A */ 125558SN/A class %(class_name)s : public %(base_class)s 12610905SN/A { 12710905SN/A public: 128558SN/A 129558SN/A /// Constructor. 130558SN/A %(class_name)s(ExtMachInst machInst); 13110905SN/A 132558SN/A %(BasicExecDeclare)s 13310905SN/A 13410905SN/A %(EACompDeclare)s 135558SN/A 136558SN/A %(InitiateAccDeclare)s 137558SN/A 1382566SN/A %(CompleteAccDeclare)s 139633SN/A }; 140633SN/A}}; 141633SN/A 142633SN/A 143633SN/Adef template EACompDeclare {{ 144633SN/A Fault eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const; 145633SN/A}}; 1462SN/A 1472SN/Adef template InitiateAccDeclare {{ 1482SN/A Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 1492SN/A}}; 1502SN/A 151633SN/A 152633SN/Adef template CompleteAccDeclare {{ 15311071SN/A Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, 15411071SN/A Trace::InstRecord *) const; 15511071SN/A}}; 156633SN/A 15711071SN/Adef template LoadStoreConstructor {{ 158633SN/A inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 159633SN/A : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 160195SN/A { 1612SN/A %(constructor)s; 1622SN/A } 1632SN/A}}; 1642SN/A 1652SN/Adef template EACompExecute {{ 1662SN/A Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc, 16711071SN/A Trace::InstRecord *traceData) const 16811071SN/A { 16911071SN/A Addr EA; 17011071SN/A Fault fault = NoFault; 17111071SN/A 17211071SN/A %(fp_enable_check)s; 17311071SN/A %(op_decl)s; 17411071SN/A %(op_rd)s; 17511071SN/A %(ea_code)s; 17611071SN/A 17711071SN/A if (fault == NoFault) { 17811071SN/A %(op_wb)s; 17911071SN/A xc->setEA(EA); 18011071SN/A } 18111071SN/A 18211071SN/A return fault; 18311071SN/A } 1842SN/A}}; 1852566SN/A 1862SN/A 1872SN/Adef template LoadExecute {{ 188633SN/A Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 1892SN/A Trace::InstRecord *traceData) const 1902SN/A { 1912SN/A Addr EA; 192633SN/A Fault fault = NoFault; 1932SN/A 1942SN/A %(fp_enable_check)s; 1952SN/A %(op_decl)s; 19611701Smichael.lebeane@amd.com %(op_rd)s; 1975190SN/A %(ea_code)s; 1985190SN/A 1995190SN/A if (fault == NoFault) { 200633SN/A fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 201633SN/A %(memacc_code)s; 2027823SN/A } 2032SN/A 2042SN/A if (fault == NoFault) { 2052SN/A %(op_wb)s; 2062SN/A } 207558SN/A 20810905SN/A return fault; 209558SN/A } 21010469SN/A}}; 21110905SN/A 2121435SN/A 21310905SN/Adef template LoadInitiateAcc {{ 214558SN/A Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 215633SN/A Trace::InstRecord *traceData) const 21610905SN/A { 217558SN/A Addr EA; 218633SN/A Fault fault = NoFault; 21910905SN/A 220574SN/A %(fp_enable_check)s; 221574SN/A %(op_src_decl)s; 22211071SN/A %(op_rd)s; 22311071SN/A %(ea_code)s; 22411071SN/A 22511071SN/A if (fault == NoFault) { 22611071SN/A fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 22711071SN/A } 22811071SN/A 22911071SN/A return fault; 23011071SN/A } 231558SN/A}}; 232558SN/A 233558SN/A 23410905SN/Adef template LoadCompleteAcc {{ 235558SN/A Fault %(class_name)s::completeAcc(PacketPtr pkt, 236574SN/A %(CPU_exec_context)s *xc, 23710905SN/A Trace::InstRecord *traceData) const 238574SN/A { 23911701Smichael.lebeane@amd.com Fault fault = NoFault; 24010905SN/A 241558SN/A %(fp_enable_check)s; 242558SN/A %(op_decl)s; 243574SN/A 24410905SN/A Mem = pkt->get<typeof(Mem)>(); 245558SN/A 246574SN/A if (fault == NoFault) { 24710905SN/A %(memacc_code)s; 2485606SN/A } 249558SN/A 25011071SN/A if (fault == NoFault) { 25111071SN/A %(op_wb)s; 25211071SN/A } 25311071SN/A 25411071SN/A return fault; 25511701Smichael.lebeane@amd.com } 25611071SN/A}}; 25711071SN/A 25811071SN/A 25911071SN/Adef template StoreExecute {{ 26011071SN/A Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 26111071SN/A Trace::InstRecord *traceData) const 26211071SN/A { 26311071SN/A Addr EA; 26411071SN/A Fault fault = NoFault; 26511071SN/A 26611071SN/A %(fp_enable_check)s; 26711071SN/A %(op_decl)s; 26811071SN/A %(op_rd)s; 26911071SN/A %(ea_code)s; 27011071SN/A 27111071SN/A if (fault == NoFault) { 27211071SN/A %(memacc_code)s; 27311071SN/A } 27411071SN/A 275558SN/A if (fault == NoFault) { 276558SN/A fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 2774762SN/A memAccessFlags, NULL); 2784762SN/A if (traceData) { traceData->setData(Mem); } 2792SN/A } 2804981SN/A 2812SN/A if (fault == NoFault) { 282 %(postacc_code)s; 283 } 284 285 if (fault == NoFault) { 286 %(op_wb)s; 287 } 288 289 return fault; 290 } 291}}; 292 293def template StoreCondExecute {{ 294 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 295 Trace::InstRecord *traceData) const 296 { 297 Addr EA; 298 Fault fault = NoFault; 299 uint64_t write_result = 0; 300 301 %(fp_enable_check)s; 302 %(op_decl)s; 303 %(op_rd)s; 304 %(ea_code)s; 305 306 if (fault == NoFault) { 307 %(memacc_code)s; 308 } 309 310 if (fault == NoFault) { 311 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 312 memAccessFlags, &write_result); 313 if (traceData) { traceData->setData(Mem); } 314 } 315 316 if (fault == NoFault) { 317 %(postacc_code)s; 318 } 319 320 if (fault == NoFault) { 321 %(op_wb)s; 322 } 323 324 return fault; 325 } 326}}; 327 328def template StoreInitiateAcc {{ 329 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 330 Trace::InstRecord *traceData) const 331 { 332 Addr EA; 333 Fault fault = NoFault; 334 335 %(fp_enable_check)s; 336 %(op_decl)s; 337 %(op_rd)s; 338 %(ea_code)s; 339 340 if (fault == NoFault) { 341 %(memacc_code)s; 342 } 343 344 if (fault == NoFault) { 345 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 346 memAccessFlags, NULL); 347 if (traceData) { traceData->setData(Mem); } 348 } 349 350 return fault; 351 } 352}}; 353 354 355def template StoreCompleteAcc {{ 356 Fault %(class_name)s::completeAcc(PacketPtr pkt, 357 %(CPU_exec_context)s *xc, 358 Trace::InstRecord *traceData) const 359 { 360 Fault fault = NoFault; 361 362 %(fp_enable_check)s; 363 %(op_dest_decl)s; 364 365 if (fault == NoFault) { 366 %(postacc_code)s; 367 } 368 369 if (fault == NoFault) { 370 %(op_wb)s; 371 } 372 373 return fault; 374 } 375}}; 376 377 378def template StoreCondCompleteAcc {{ 379 Fault %(class_name)s::completeAcc(PacketPtr pkt, 380 %(CPU_exec_context)s *xc, 381 Trace::InstRecord *traceData) const 382 { 383 Fault fault = NoFault; 384 385 %(fp_enable_check)s; 386 %(op_dest_decl)s; 387 388 uint64_t write_result = pkt->req->getExtraData(); 389 390 if (fault == NoFault) { 391 %(postacc_code)s; 392 } 393 394 if (fault == NoFault) { 395 %(op_wb)s; 396 } 397 398 return fault; 399 } 400}}; 401 402 403def template MiscExecute {{ 404 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 405 Trace::InstRecord *traceData) const 406 { 407 Addr EA; 408 Fault fault = NoFault; 409 410 %(fp_enable_check)s; 411 %(op_decl)s; 412 %(op_rd)s; 413 %(ea_code)s; 414 415 if (fault == NoFault) { 416 %(memacc_code)s; 417 } 418 419 return NoFault; 420 } 421}}; 422 423def template MiscInitiateAcc {{ 424 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 425 Trace::InstRecord *traceData) const 426 { 427 warn("initiateAcc undefined: Misc instruction does not support split " 428 "access method!"); 429 return NoFault; 430 } 431}}; 432 433 434def template MiscCompleteAcc {{ 435 Fault %(class_name)s::completeAcc(PacketPtr pkt, 436 %(CPU_exec_context)s *xc, 437 Trace::InstRecord *traceData) const 438 { 439 warn("completeAcc undefined: Misc instruction does not support split " 440 "access method!"); 441 442 return NoFault; 443 } 444}}; 445 446 447// load instructions use Ra as dest, so check for 448// Ra == 31 to detect nops 449def template LoadNopCheckDecode {{ 450 { 451 AlphaStaticInst *i = new %(class_name)s(machInst); 452 if (RA == 31) { 453 i = makeNop(i); 454 } 455 return i; 456 } 457}}; 458 459 460// for some load instructions, Ra == 31 indicates a prefetch (not a nop) 461def template LoadPrefetchCheckDecode {{ 462 { 463 if (RA != 31) { 464 return new %(class_name)s(machInst); 465 } 466 else { 467 return new %(class_name)sPrefetch(machInst); 468 } 469 } 470}}; 471 472 473let {{ 474def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 475 postacc_code = '', base_class = 'MemoryDisp32', 476 decode_template = BasicDecode, exec_template_base = ''): 477 # Make sure flags are in lists (convert to lists if not). 478 mem_flags = makeList(mem_flags) 479 inst_flags = makeList(inst_flags) 480 481 # add hook to get effective addresses into execution trace output. 482 ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' 483 484 # Some CPU models execute the memory operation as an atomic unit, 485 # while others want to separate them into an effective address 486 # computation and a memory access operation. As a result, we need 487 # to generate three StaticInst objects. Note that the latter two 488 # are nested inside the larger "atomic" one. 489 490 # Generate InstObjParams for each of the three objects. Note that 491 # they differ only in the set of code objects contained (which in 492 # turn affects the object's overall operand list). 493 iop = InstObjParams(name, Name, base_class, 494 { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 495 inst_flags) 496 memacc_iop = InstObjParams(name, Name, base_class, 497 { 'memacc_code':memacc_code, 'postacc_code':postacc_code }, 498 inst_flags) 499 500 if mem_flags: 501 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] 502 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' 503 iop.constructor += s 504 memacc_iop.constructor += s 505 506 # select templates 507 508 # The InitiateAcc template is the same for StoreCond templates as the 509 # corresponding Store template.. 510 StoreCondInitiateAcc = StoreInitiateAcc 511 512 fullExecTemplate = eval(exec_template_base + 'Execute') 513 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') 514 completeAccTemplate = eval(exec_template_base + 'CompleteAcc') 515 516 # (header_output, decoder_output, decode_block, exec_output) 517 return (LoadStoreDeclare.subst(iop), 518 LoadStoreConstructor.subst(iop), 519 decode_template.subst(iop), 520 fullExecTemplate.subst(iop) 521 + EACompExecute.subst(iop) 522 + initiateAccTemplate.subst(iop) 523 + completeAccTemplate.subst(iop)) 524}}; 525 526def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, 527 mem_flags = [], inst_flags = []) {{ 528 (header_output, decoder_output, decode_block, exec_output) = \ 529 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 530 decode_template = LoadNopCheckDecode, 531 exec_template_base = 'Load') 532}}; 533 534 535// Note that the flags passed in apply only to the prefetch version 536def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }}, 537 mem_flags = [], pf_flags = [], inst_flags = []) {{ 538 # declare the load instruction object and generate the decode block 539 (header_output, decoder_output, decode_block, exec_output) = \ 540 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 541 decode_template = LoadPrefetchCheckDecode, 542 exec_template_base = 'Load') 543 544 # Declare the prefetch instruction object. 545 546 # Make sure flag args are lists so we can mess with them. 547 mem_flags = makeList(mem_flags) 548 pf_flags = makeList(pf_flags) 549 inst_flags = makeList(inst_flags) 550 551 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT'] 552 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad', 553 'IsDataPrefetch', 'MemReadOp'] 554 555 (pf_header_output, pf_decoder_output, _, pf_exec_output) = \ 556 LoadStoreBase(name, Name + 'Prefetch', ea_code, 557 'xc->prefetch(EA, memAccessFlags);', 558 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc') 559 560 header_output += pf_header_output 561 decoder_output += pf_decoder_output 562 exec_output += pf_exec_output 563}}; 564 565 566def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }}, 567 mem_flags = [], inst_flags = []) {{ 568 (header_output, decoder_output, decode_block, exec_output) = \ 569 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 570 exec_template_base = 'Store') 571}}; 572 573 574def format StoreCond(memacc_code, postacc_code, 575 ea_code = {{ EA = Rb + disp; }}, 576 mem_flags = [], inst_flags = []) {{ 577 (header_output, decoder_output, decode_block, exec_output) = \ 578 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 579 postacc_code, exec_template_base = 'StoreCond') 580}}; 581 582 583// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb 584def format MiscPrefetch(ea_code, memacc_code, 585 mem_flags = [], inst_flags = []) {{ 586 (header_output, decoder_output, decode_block, exec_output) = \ 587 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 588 base_class = 'MemoryNoDisp', exec_template_base = 'Misc') 589}}; 590 591 592