58280bf622ecf5604d532bfe92071727d5f11e13
[gem5.git] / src / cpu / inorder / inorder_dyn_inst.cc
1 /*
2 * Copyright (c) 2007 MIPS Technologies, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Korey Sewell
29 *
30 */
31
32 #include <iostream>
33 #include <set>
34 #include <sstream>
35 #include <string>
36
37 #include "arch/faults.hh"
38 #include "base/bigint.hh"
39 #include "base/cp_annotate.hh"
40 #include "base/cprintf.hh"
41 #include "base/trace.hh"
42 #include "config/the_isa.hh"
43 #include "cpu/inorder/cpu.hh"
44 #include "cpu/inorder/inorder_dyn_inst.hh"
45 #include "cpu/exetrace.hh"
46 #include "debug/InOrderDynInst.hh"
47 #include "mem/request.hh"
48
49 using namespace std;
50 using namespace TheISA;
51 using namespace ThePipeline;
52
53 InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
54 InOrderThreadState *state,
55 InstSeqNum seq_num,
56 ThreadID tid,
57 unsigned _asid)
58 : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid),
59 virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu),
60 thread(state), fault(NoFault), memData(NULL), loadData(0),
61 storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
62 readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0),
63 memTime(0), splitMemData(NULL), splitMemReq(NULL), totalSize(0),
64 split2ndSize(0), split2ndAddr(0), split2ndAccess(false),
65 split2ndDataPtr(NULL), split2ndFlags(0), splitInst(false),
66 splitFinishCnt(0), split2ndStoreDataPtr(NULL), splitInstSked(false),
67 inFrontEnd(true), frontSked(NULL), backSked(NULL),
68 squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
69 fetchMemReq(NULL), dataMemReq(NULL), instEffAddr(0), eaCalcDone(false),
70 lqIdx(0), sqIdx(0), instListIt(NULL), onInstList(false)
71 {
72 for(int i = 0; i < MaxInstSrcRegs; i++) {
73 _readySrcRegIdx[i] = false;
74 _srcRegIdx[i] = 0;
75 }
76
77 for(int j = 0; j < MaxInstDestRegs; j++) {
78 _destRegIdx[j] = 0;
79 _prevDestRegIdx[j] = 0;
80 }
81
82 ++instcount;
83 DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction created."
84 " (active insts: %i)\n", threadNumber, seqNum, instcount);
85
86 }
87
88 int InOrderDynInst::instcount = 0;
89
90 void
91 InOrderDynInst::setMachInst(ExtMachInst machInst)
92 {
93 staticInst = StaticInst::decode(machInst, pc.instAddr());
94
95 for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
96 _destRegIdx[i] = this->staticInst->destRegIdx(i);
97 }
98
99 for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
100 _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
101 this->_readySrcRegIdx[i] = 0;
102 }
103 }
104
105 void
106 InOrderDynInst::initVars()
107 {
108 inFrontEnd = true;
109
110 fetchMemReq = NULL;
111 dataMemReq = NULL;
112 splitMemData = NULL;
113 split2ndAddr = 0;
114 split2ndAccess = false;
115 splitInst = false;
116 splitInstSked = false;
117 splitFinishCnt = 0;
118
119 effAddr = 0;
120 physEffAddr = 0;
121
122 readyRegs = 0;
123
124 nextStage = 0;
125
126 status.reset();
127
128 memAddrReady = false;
129 eaCalcDone = false;
130
131 predictTaken = false;
132 procDelaySlotOnMispred = false;
133
134 lqIdx = -1;
135 sqIdx = -1;
136
137 // Also make this a parameter, or perhaps get it from xc or cpu.
138 asid = 0;
139
140 virtProcNumber = 0;
141
142 // Initialize the fault to be NoFault.
143 fault = NoFault;
144
145 // Make sure to have the renamed register entries set to the same
146 // as the normal register entries. It will allow the IQ to work
147 // without any modifications.
148 if (this->staticInst) {
149 for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
150 _destRegIdx[i] = this->staticInst->destRegIdx(i);
151 }
152
153 for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
154 _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
155 this->_readySrcRegIdx[i] = 0;
156 }
157 }
158
159 // Update Instruction Count for this instruction
160 if (instcount > 100) {
161 fatal("Number of Active Instructions in CPU is too high. "
162 "(Not Dereferencing Ptrs. Correctly?)\n");
163 }
164 }
165
166 void
167 InOrderDynInst::resetInstCount()
168 {
169 instcount = 0;
170 }
171
172
173 InOrderDynInst::~InOrderDynInst()
174 {
175 if (traceData)
176 delete traceData;
177
178 if (splitMemData)
179 delete [] splitMemData;
180
181 fault = NoFault;
182
183 --instcount;
184
185 DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
186 " (active insts: %i)\n", threadNumber, seqNum, instcount);
187 }
188
189 void
190 InOrderDynInst::setStaticInst(StaticInstPtr &static_inst)
191 {
192 this->staticInst = static_inst;
193
194 // Make sure to have the renamed register entries set to the same
195 // as the normal register entries. It will allow the IQ to work
196 // without any modifications.
197 if (this->staticInst) {
198 for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
199 _destRegIdx[i] = this->staticInst->destRegIdx(i);
200 }
201
202 for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
203 _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
204 this->_readySrcRegIdx[i] = 0;
205 }
206 }
207 }
208
209 Fault
210 InOrderDynInst::execute()
211 {
212 // @todo: Pretty convoluted way to avoid squashing from happening
213 // when using the TC during an instruction's execution
214 // (specifically for instructions that have side-effects that use
215 // the TC). Fix this.
216 bool in_syscall = this->thread->inSyscall;
217 this->thread->inSyscall = true;
218
219 this->fault = this->staticInst->execute(this, this->traceData);
220
221 this->thread->inSyscall = in_syscall;
222
223 return this->fault;
224 }
225
226 Fault
227 InOrderDynInst::calcEA()
228 {
229 this->fault = this->staticInst->eaComp(this, this->traceData);
230 return this->fault;
231 }
232
233 Fault
234 InOrderDynInst::initiateAcc()
235 {
236 // @todo: Pretty convoluted way to avoid squashing from happening
237 // when using the TC during an instruction's execution
238 // (specifically for instructions that have side-effects that use
239 // the TC). Fix this.
240 bool in_syscall = this->thread->inSyscall;
241 this->thread->inSyscall = true;
242
243 this->fault = this->staticInst->initiateAcc(this, this->traceData);
244
245 this->thread->inSyscall = in_syscall;
246
247 return this->fault;
248 }
249
250
251 Fault
252 InOrderDynInst::completeAcc(Packet *pkt)
253 {
254 this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
255
256 return this->fault;
257 }
258
259 Fault
260 InOrderDynInst::memAccess()
261 {
262 return initiateAcc();
263 }
264
265
266 #if FULL_SYSTEM
267
268 Fault
269 InOrderDynInst::hwrei()
270 {
271 #if THE_ISA == ALPHA_ISA
272 // Can only do a hwrei when in pal mode.
273 if (!(this->instAddr() & 0x3))
274 return new AlphaISA::UnimplementedOpcodeFault;
275
276 // Set the next PC based on the value of the EXC_ADDR IPR.
277 AlphaISA::PCState pc = this->pcState();
278 pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
279 this->threadNumber));
280 this->pcState(pc);
281 if (CPA::available()) {
282 ThreadContext *tc = this->cpu->tcBase(this->threadNumber);
283 CPA::cpa()->swAutoBegin(tc, this->nextInstAddr());
284 }
285
286 // Tell CPU to clear any state it needs to if a hwrei is taken.
287 this->cpu->hwrei(this->threadNumber);
288 #endif
289 return NoFault;
290 }
291
292
293 void
294 InOrderDynInst::trap(Fault fault)
295 {
296 this->cpu->trap(fault, this->threadNumber, this);
297 }
298
299
300 bool
301 InOrderDynInst::simPalCheck(int palFunc)
302 {
303 #if THE_ISA != ALPHA_ISA
304 panic("simPalCheck called, but PAL only exists in Alpha!\n");
305 #endif
306 return this->cpu->simPalCheck(palFunc, this->threadNumber);
307 }
308 #else
309 void
310 InOrderDynInst::syscall(int64_t callnum)
311 {
312 syscallNum = callnum;
313 cpu->syscallContext(NoFault, this->threadNumber, this);
314 }
315 #endif
316
317 void
318 InOrderDynInst::setSquashInfo(unsigned stage_num)
319 {
320 squashingStage = stage_num;
321
322 // If it's a fault, then we need to squash
323 // the faulting instruction too. Squash
324 // functions squash above a seqNum, so we
325 // decrement here for that case
326 if (fault != NoFault) {
327 squashSeqNum = seqNum - 1;
328 return;
329 } else
330 squashSeqNum = seqNum;
331
332 #if ISA_HAS_DELAY_SLOT
333 if (isControl()) {
334 TheISA::PCState nextPC = pc;
335 TheISA::advancePC(nextPC, staticInst);
336
337 // Check to see if we should squash after the
338 // branch or after a branch delay slot.
339 if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
340 squashSeqNum = seqNum + 1;
341 else
342 squashSeqNum = seqNum;
343 }
344 #endif
345 }
346
347 void
348 InOrderDynInst::releaseReq(ResourceRequest* req)
349 {
350 std::list<ResourceRequest*>::iterator list_it = reqList.begin();
351 std::list<ResourceRequest*>::iterator list_end = reqList.end();
352
353 while(list_it != list_end) {
354 if((*list_it)->getResIdx() == req->getResIdx() &&
355 (*list_it)->getSlot() == req->getSlot()) {
356 DPRINTF(InOrderDynInst, "[tid:%u]: [sn:%i] Done with request "
357 "to %s.\n", threadNumber, seqNum, req->res->name());
358 reqList.erase(list_it);
359 return;
360 }
361 list_it++;
362 }
363
364 panic("Releasing Res. Request That Isnt There!\n");
365 }
366
367 /** Records an integer source register being set to a value. */
368 void
369 InOrderDynInst::setIntSrc(int idx, uint64_t val)
370 {
371 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] Int being set "
372 "to %#x.\n", threadNumber, seqNum, idx, val);
373 instSrc[idx].intVal = val;
374 }
375
376 /** Records an fp register being set to a value. */
377 void
378 InOrderDynInst::setFloatSrc(int idx, FloatReg val)
379 {
380 instSrc[idx].fpVal.f = val;
381 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FP being set "
382 "to %x, %08f...%08f\n", threadNumber, seqNum, idx,
383 instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val);
384 }
385
386 /** Records an fp register being set to an integer value. */
387 void
388 InOrderDynInst::setFloatRegBitsSrc(int idx, FloatRegBits val)
389 {
390 instSrc[idx].fpVal.i = val;
391 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being set "
392 "to %x, %08f...%x\n", threadNumber, seqNum, idx,
393 instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val);
394 }
395
396 /** Reads a integer register. */
397 IntReg
398 InOrderDynInst::readIntRegOperand(const StaticInst *si, int idx, ThreadID tid)
399 {
400 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] IntVal read as %#x.\n",
401 threadNumber, seqNum, idx, instSrc[idx].intVal);
402 return instSrc[idx].intVal;
403 }
404
405 /** Reads a FP register. */
406 FloatReg
407 InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx)
408 {
409 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPVal being read "
410 "as %x, %08f.\n", threadNumber, seqNum, idx,
411 instSrc[idx].fpVal.i, instSrc[idx].fpVal.f);
412 return instSrc[idx].fpVal.f;
413 }
414
415
416 /** Reads a FP register as a integer. */
417 FloatRegBits
418 InOrderDynInst::readFloatRegOperandBits(const StaticInst *si, int idx)
419 {
420 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being read "
421 "as %x, %08f.\n", threadNumber, seqNum, idx,
422 instSrc[idx].fpVal.i, instSrc[idx].fpVal.f);
423 return instSrc[idx].fpVal.i;
424 }
425
426 /** Reads a miscellaneous register. */
427 MiscReg
428 InOrderDynInst::readMiscReg(int misc_reg)
429 {
430 return this->cpu->readMiscReg(misc_reg, threadNumber);
431 }
432
433
434 /** Reads a misc. register, including any side-effects the read
435 * might have as defined by the architecture.
436 */
437 MiscReg
438 InOrderDynInst::readMiscRegOperand(const StaticInst *si, int idx)
439 {
440 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
441 " read as %#x.\n", threadNumber, seqNum, idx,
442 instSrc[idx].intVal);
443 return instSrc[idx].intVal;
444 }
445
446
447 /** Sets a misc. register, including any side-effects the write
448 * might have as defined by the architecture.
449 */
450 void
451 InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx,
452 const MiscReg &val)
453 {
454 instResult[idx].type = Integer;
455 instResult[idx].res.intVal = val;
456 instResult[idx].tick = curTick();
457
458 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
459 "being set to %#x.\n", threadNumber, seqNum, idx, val);
460 }
461
462 MiscReg
463 InOrderDynInst::readRegOtherThread(unsigned reg_idx, ThreadID tid)
464 {
465 if (tid == -1) {
466 tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
467 }
468
469 if (reg_idx < FP_Base_DepTag) { // Integer Register File
470 return this->cpu->readIntReg(reg_idx, tid);
471 } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File
472 reg_idx -= FP_Base_DepTag;
473 return this->cpu->readFloatRegBits(reg_idx, tid);
474 } else {
475 reg_idx -= Ctrl_Base_DepTag;
476 return this->cpu->readMiscReg(reg_idx, tid); // Misc. Register File
477 }
478 }
479
480 /** Sets a Integer register. */
481 void
482 InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val)
483 {
484 instResult[idx].type = Integer;
485 instResult[idx].res.intVal = val;
486 instResult[idx].tick = curTick();
487
488 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
489 "being set to %#x (result-tick:%i).\n",
490 threadNumber, seqNum, idx, val, instResult[idx].tick);
491 }
492
493 /** Sets a FP register. */
494 void
495 InOrderDynInst::setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
496 {
497 instResult[idx].res.fpVal.f = val;
498 instResult[idx].type = Float;
499 instResult[idx].tick = curTick();
500
501 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. %i "
502 "being set to %#x, %08f (result-tick:%i).\n",
503 threadNumber, seqNum, idx, val, val, instResult[idx].tick);
504 }
505
506 /** Sets a FP register as a integer. */
507 void
508 InOrderDynInst::setFloatRegOperandBits(const StaticInst *si, int idx,
509 FloatRegBits val)
510 {
511 instResult[idx].type = Integer;
512 instResult[idx].res.fpVal.i = val;
513 instResult[idx].tick = curTick();
514
515 DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. Bits %i "
516 "being set to %#x (result-tick:%i).\n",
517 threadNumber, seqNum, idx, val, instResult[idx].tick);
518 }
519
520 /** Sets a misc. register, including any side-effects the write
521 * might have as defined by the architecture.
522 */
523 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
524 void
525 InOrderDynInst::setMiscReg(int misc_reg, const MiscReg &val)
526 {
527 this->cpu->setMiscReg(misc_reg, val, threadNumber);
528 }
529
530 void
531 InOrderDynInst::setRegOtherThread(unsigned reg_idx, const MiscReg &val,
532 ThreadID tid)
533 {
534 if (tid == InvalidThreadID) {
535 tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
536 }
537
538 if (reg_idx < FP_Base_DepTag) { // Integer Register File
539 this->cpu->setIntReg(reg_idx, val, tid);
540 } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File
541 reg_idx -= FP_Base_DepTag;
542 this->cpu->setFloatRegBits(reg_idx, val, tid);
543 } else {
544 reg_idx -= Ctrl_Base_DepTag;
545 this->cpu->setMiscReg(reg_idx, val, tid); // Misc. Register File
546 }
547 }
548
549 void
550 InOrderDynInst::deallocateContext(int thread_num)
551 {
552 this->cpu->deallocateContext(thread_num);
553 }
554
555 Fault
556 InOrderDynInst::readBytes(Addr addr, uint8_t *data,
557 unsigned size, unsigned flags)
558 {
559 return cpu->read(this, addr, data, size, flags);
560 }
561
562 template<class T>
563 inline Fault
564 InOrderDynInst::read(Addr addr, T &data, unsigned flags)
565 {
566 if (traceData) {
567 traceData->setAddr(addr);
568 traceData->setData(data);
569 }
570 Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
571 //@todo: the below lines should be unnecessary, timing access
572 // wont have valid data right here
573 DPRINTF(InOrderDynInst, "[sn:%i] (1) Received Bytes %x\n", seqNum, data);
574 data = TheISA::gtoh(data);
575 DPRINTF(InOrderDynInst, "[sn%:i] (2) Received Bytes %x\n", seqNum, data);
576
577 if (traceData)
578 traceData->setData(data);
579 return fault;
580 }
581
582 #ifndef DOXYGEN_SHOULD_SKIP_THIS
583
584 template
585 Fault
586 InOrderDynInst::read(Addr addr, Twin32_t &data, unsigned flags);
587
588 template
589 Fault
590 InOrderDynInst::read(Addr addr, Twin64_t &data, unsigned flags);
591
592 template
593 Fault
594 InOrderDynInst::read(Addr addr, uint64_t &data, unsigned flags);
595
596 template
597 Fault
598 InOrderDynInst::read(Addr addr, uint32_t &data, unsigned flags);
599
600 template
601 Fault
602 InOrderDynInst::read(Addr addr, uint16_t &data, unsigned flags);
603
604 template
605 Fault
606 InOrderDynInst::read(Addr addr, uint8_t &data, unsigned flags);
607
608 #endif //DOXYGEN_SHOULD_SKIP_THIS
609
610 template<>
611 Fault
612 InOrderDynInst::read(Addr addr, double &data, unsigned flags)
613 {
614 return read(addr, *(uint64_t*)&data, flags);
615 }
616
617 template<>
618 Fault
619 InOrderDynInst::read(Addr addr, float &data, unsigned flags)
620 {
621 return read(addr, *(uint32_t*)&data, flags);
622 }
623
624 template<>
625 Fault
626 InOrderDynInst::read(Addr addr, int32_t &data, unsigned flags)
627 {
628 return read(addr, (uint32_t&)data, flags);
629 }
630
631 Fault
632 InOrderDynInst::writeBytes(uint8_t *data, unsigned size,
633 Addr addr, unsigned flags, uint64_t *res)
634 {
635 return cpu->write(this, data, size, addr, flags, res);
636 }
637
638 template<class T>
639 inline Fault
640 InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
641 {
642 if (traceData) {
643 traceData->setAddr(addr);
644 traceData->setData(data);
645 }
646 data = TheISA::htog(data);
647 return writeBytes((uint8_t*)&data, sizeof(T), addr, flags, res);
648 }
649
650 #ifndef DOXYGEN_SHOULD_SKIP_THIS
651
652 template
653 Fault
654 InOrderDynInst::write(Twin32_t data, Addr addr,
655 unsigned flags, uint64_t *res);
656
657 template
658 Fault
659 InOrderDynInst::write(Twin64_t data, Addr addr,
660 unsigned flags, uint64_t *res);
661 template
662 Fault
663 InOrderDynInst::write(uint64_t data, Addr addr,
664 unsigned flags, uint64_t *res);
665
666 template
667 Fault
668 InOrderDynInst::write(uint32_t data, Addr addr,
669 unsigned flags, uint64_t *res);
670
671 template
672 Fault
673 InOrderDynInst::write(uint16_t data, Addr addr,
674 unsigned flags, uint64_t *res);
675
676 template
677 Fault
678 InOrderDynInst::write(uint8_t data, Addr addr,
679 unsigned flags, uint64_t *res);
680
681 #endif //DOXYGEN_SHOULD_SKIP_THIS
682
683 template<>
684 Fault
685 InOrderDynInst::write(double data, Addr addr, unsigned flags, uint64_t *res)
686 {
687 return write(*(uint64_t*)&data, addr, flags, res);
688 }
689
690 template<>
691 Fault
692 InOrderDynInst::write(float data, Addr addr, unsigned flags, uint64_t *res)
693 {
694 return write(*(uint32_t*)&data, addr, flags, res);
695 }
696
697
698 template<>
699 Fault
700 InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
701 {
702 return write((uint32_t)data, addr, flags, res);
703 }
704
705
706 void
707 InOrderDynInst::dump()
708 {
709 cprintf("T%d : %#08d `", threadNumber, pc.instAddr());
710 cout << staticInst->disassemble(pc.instAddr());
711 cprintf("'\n");
712 }
713
714 void
715 InOrderDynInst::dump(std::string &outstring)
716 {
717 std::ostringstream s;
718 s << "T" << threadNumber << " : " << pc << " "
719 << staticInst->disassemble(pc.instAddr());
720
721 outstring = s.str();
722 }
723
724
725 #define NOHASH
726 #ifndef NOHASH
727
728 #include "base/hashmap.hh"
729
730 unsigned int MyHashFunc(const InOrderDynInst *addr)
731 {
732 unsigned a = (unsigned)addr;
733 unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
734
735 return hash;
736 }
737
738 typedef m5::hash_map<const InOrderDynInst *, const InOrderDynInst *,
739 MyHashFunc>
740 my_hash_t;
741
742 my_hash_t thishash;
743 #endif