3 // Copyright (c) 2006 The Regents of The University of Michigan
4 // All rights reserved.
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.
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.
29 // Authors: Steve Reinhardt
32 ////////////////////////////////////////////////////////////////////
34 // Memory-format instructions
39 * Base class for general Mips memory-format instructions.
41 class Memory : public MipsStaticInst
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;
52 /// Displacement for EA calculation (signed).
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(sext<16>(OFFSET))
66 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
70 const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
71 const StaticInstPtr &memAccInst() const { return memAccPtr; }
73 unsigned memAccFlags() { return memAccessFlags; }
77 * Base class for a few miscellaneous memory-format insts
78 * that don't interpret the disp field
80 class MemoryNoDisp : public Memory
84 MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
85 StaticInstPtr _eaCompPtr = nullStaticInstPtr,
86 StaticInstPtr _memAccPtr = nullStaticInstPtr)
87 : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
92 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
99 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
101 return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
102 flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
106 MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
108 return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
109 flags[IsFloating] ? 'f' : 'r',
110 flags[IsFloating] ? FD : RD,
117 /** return data in cases where there the size of data is only
120 uint64_t getStoreData(%(CPU_exec_context)s *xc, Packet *packet) {
121 switch (packet->getSize())
124 return packet->get<uint8_t>();
127 return packet->get<uint16_t>();
130 return packet->get<uint32_t>();
133 return packet->get<uint64_t>();
136 std::cerr << "bad store data size = " << packet->getSize() << std::endl;
146 def template LoadStoreDeclare {{
148 * Static instruction class for "%(mnemonic)s".
150 class %(class_name)s : public %(base_class)s
155 * "Fake" effective address computation class for "%(mnemonic)s".
157 class EAComp : public %(base_class)s
161 EAComp(ExtMachInst machInst);
167 * "Fake" memory access instruction class for "%(mnemonic)s".
169 class MemAcc : public %(base_class)s
173 MemAcc(ExtMachInst machInst);
181 %(class_name)s(ExtMachInst machInst);
185 %(InitiateAccDeclare)s
187 %(CompleteAccDeclare)s
189 %(MemAccSizeDeclare)s
194 def template InitiateAccDeclare {{
195 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
199 def template CompleteAccDeclare {{
200 Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
203 def template MemAccSizeDeclare {{
204 int memAccSize(%(CPU_exec_context)s *xc);
207 def template EACompConstructor {{
208 /** TODO: change op_class to AddrGenOp or something (requires
209 * creating new member of OpClass enum in op_class.hh, updating
210 * config files, etc.). */
211 inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
212 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
219 def template MemAccConstructor {{
220 inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
221 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
228 def template LoadStoreConstructor {{
229 inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
230 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
231 new EAComp(machInst), new MemAcc(machInst))
238 def template EACompExecute {{
240 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
241 Trace::InstRecord *traceData) const
244 Fault fault = NoFault;
251 // NOTE: Trace Data is written using execute or completeAcc templates
252 if (fault == NoFault) {
260 def template LoadMemAccExecute {{
262 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
263 Trace::InstRecord *traceData) const
266 Fault fault = NoFault;
273 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
277 // NOTE: Write back data using execute or completeAcc templates
284 def template LoadExecute {{
285 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
286 Trace::InstRecord *traceData) const
289 Fault fault = NoFault;
296 if (fault == NoFault) {
297 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
301 if (fault == NoFault) {
310 def template LoadInitiateAcc {{
311 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
312 Trace::InstRecord *traceData) const
315 Fault fault = NoFault;
322 if (fault == NoFault) {
323 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
330 def template LoadCompleteAcc {{
331 Fault %(class_name)s::completeAcc(Packet *pkt,
332 %(CPU_exec_context)s *xc,
333 Trace::InstRecord *traceData) const
335 Fault fault = NoFault;
341 Mem = pkt->get<typeof(Mem)>();
343 if (fault == NoFault) {
347 if (fault == NoFault) {
357 def template LoadStoreMemAccSize {{
358 int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
360 // Return the memory access size in bytes
361 return (%(mem_acc_size)d / 8);
365 def template StoreMemAccExecute {{
367 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
368 Trace::InstRecord *traceData) const
371 Fault fault = NoFault;
379 if (fault == NoFault) {
383 if (fault == NoFault) {
384 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
385 memAccessFlags, NULL);
386 // @NOTE: Need to Call Complete Access to Set Trace Data
387 //if (traceData) { traceData->setData(Mem); }
394 def template StoreCondMemAccExecute {{
396 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
397 Trace::InstRecord *traceData) const
400 Fault fault = NoFault;
401 uint64_t write_result = 0;
408 if (fault == NoFault) {
412 if (fault == NoFault) {
413 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
414 memAccessFlags, &write_result);
415 if (traceData) { traceData->setData(Mem); }
418 if (fault == NoFault) {
422 if (fault == NoFault) {
430 def template StoreExecute {{
431 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
432 Trace::InstRecord *traceData) const
435 Fault fault = NoFault;
442 if (fault == NoFault) {
446 if (fault == NoFault) {
447 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
448 memAccessFlags, NULL);
449 if (traceData) { traceData->setData(Mem); }
452 if (fault == NoFault) {
456 if (fault == NoFault) {
464 def template StoreCondExecute {{
465 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
466 Trace::InstRecord *traceData) const
469 Fault fault = NoFault;
470 uint64_t write_result = 0;
477 if (fault == NoFault) {
481 if (fault == NoFault) {
482 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
483 memAccessFlags, &write_result);
484 if (traceData) { traceData->setData(Mem); }
487 if (fault == NoFault) {
491 if (fault == NoFault) {
499 def template StoreInitiateAcc {{
500 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
501 Trace::InstRecord *traceData) const
504 Fault fault = NoFault;
511 if (fault == NoFault) {
515 if (fault == NoFault) {
516 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
517 memAccessFlags, NULL);
518 if (traceData) { traceData->setData(Mem); }
526 def template StoreCompleteAcc {{
527 Fault %(class_name)s::completeAcc(Packet *pkt,
528 %(CPU_exec_context)s *xc,
529 Trace::InstRecord *traceData) const
531 Fault fault = NoFault;
536 if (fault == NoFault) {
540 if (fault == NoFault) {
543 if (traceData) { traceData->setData(getStoreData(xc, pkt)); }
550 def template StoreCondCompleteAcc {{
551 Fault %(class_name)s::completeAcc(Packet *pkt,
552 %(CPU_exec_context)s *xc,
553 Trace::InstRecord *traceData) const
555 Fault fault = NoFault;
560 uint64_t write_result = pkt->req->getExtraData();
562 if (fault == NoFault) {
566 if (fault == NoFault) {
575 def template MiscMemAccExecute {{
576 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
577 Trace::InstRecord *traceData) const
580 Fault fault = NoFault;
587 if (fault == NoFault) {
595 def template MiscExecute {{
596 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
597 Trace::InstRecord *traceData) const
600 Fault fault = NoFault;
607 if (fault == NoFault) {
615 def template MiscInitiateAcc {{
616 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
617 Trace::InstRecord *traceData) const
619 panic("Misc instruction does not support split access method!");
625 def template MiscCompleteAcc {{
626 Fault %(class_name)s::completeAcc(Packet *pkt,
627 %(CPU_exec_context)s *xc,
628 Trace::InstRecord *traceData) const
630 panic("Misc instruction does not support split access method!");
637 def template MiscMemAccSize {{
638 int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
640 panic("Misc instruction does not support split access method!");
645 def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
646 mem_flags = [], inst_flags = []) {{
647 (header_output, decoder_output, decode_block, exec_output) = \
648 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
649 decode_template = ImmNopCheckDecode,
650 exec_template_base = 'Load')
653 def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
654 mem_flags = [], inst_flags = []) {{
655 (header_output, decoder_output, decode_block, exec_output) = \
656 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
657 exec_template_base = 'Store')
660 def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
661 mem_flags = [], inst_flags = []) {{
662 (header_output, decoder_output, decode_block, exec_output) = \
663 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
664 decode_template = ImmNopCheckDecode,
665 exec_template_base = 'Load')
668 def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
669 mem_flags = [], inst_flags = []) {{
670 (header_output, decoder_output, decode_block, exec_output) = \
671 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
672 exec_template_base = 'Store')
675 def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
676 mem_flags = [], inst_flags = []) {{
677 decl_code = 'uint32_t mem_word = Mem.uw;\n'
678 decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
679 decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
680 decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
681 decl_code += '\tbyte_offset ^= 3;\n'
682 decl_code += '#endif\n'
684 memacc_code = decl_code + memacc_code
686 (header_output, decoder_output, decode_block, exec_output) = \
687 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
688 decode_template = ImmNopCheckDecode,
689 exec_template_base = 'Load')
692 def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
693 mem_flags = [], inst_flags = []) {{
694 decl_code = 'uint32_t mem_word = 0;\n'
695 decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
696 decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
697 decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
698 decl_code += '\tbyte_offset ^= 3;\n'
699 decl_code += '#endif\n'
700 decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
701 #decl_code += 'xc->readFunctional(EA,(uint32_t&)mem_word);'
702 memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
704 (header_output, decoder_output, decode_block, exec_output) = \
705 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
706 exec_template_base = 'Store')
709 def format Prefetch(ea_code = {{ EA = Rs + disp; }},
710 mem_flags = [], pf_flags = [], inst_flags = []) {{
711 pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
712 pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
713 'IsDataPrefetch', 'MemReadOp']
715 (header_output, decoder_output, decode_block, exec_output) = \
716 LoadStoreBase(name, Name, ea_code,
717 'xc->prefetch(EA, memAccessFlags);',
718 pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
722 def format StoreCond(memacc_code, postacc_code,
723 ea_code = {{ EA = Rs + disp; }},
724 mem_flags = [], inst_flags = []) {{
725 (header_output, decoder_output, decode_block, exec_output) = \
726 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
727 postacc_code, exec_template_base = 'StoreCond')