Yet another merge with the main repository.
[gem5.git] / src / cpu / inorder / inorder_dyn_inst.cc
index 90134f533b9d281a87376ab828a40ad7cfff3654..b61beece2558fe1bdf8c76977810d5fb3a1acd7e 100644 (file)
 #include <string>
 
 #include "arch/faults.hh"
+#include "base/bigint.hh"
+#include "base/cp_annotate.hh"
 #include "base/cprintf.hh"
 #include "base/trace.hh"
 #include "config/the_isa.hh"
 #include "cpu/inorder/cpu.hh"
 #include "cpu/inorder/inorder_dyn_inst.hh"
 #include "cpu/exetrace.hh"
+#include "debug/InOrderDynInst.hh"
 #include "mem/request.hh"
+#include "sim/full_system.hh"
 
 using namespace std;
 using namespace TheISA;
@@ -52,7 +56,7 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
                                InstSeqNum seq_num,
                                ThreadID tid,
                                unsigned _asid)
-  : seqNum(seq_num), bdelaySeqNum(0), threadNumber(tid), asid(_asid),
+  : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid),
     virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu),
     thread(state), fault(NoFault), memData(NULL), loadData(0),
     storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
@@ -64,11 +68,9 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
     inFrontEnd(true), frontSked(NULL), backSked(NULL),
     squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
     fetchMemReq(NULL), dataMemReq(NULL), instEffAddr(0), eaCalcDone(false),
-    lqIdx(0), sqIdx(0), instListIt(NULL)
+    lqIdx(0), sqIdx(0), instListIt(NULL), onInstList(false)
 {
     for(int i = 0; i < MaxInstSrcRegs; i++) {
-        instSrc[i].integer = 0;
-        instSrc[i].dbl = 0;
         _readySrcRegIdx[i] = false;
         _srcRegIdx[i] = 0;
     }
@@ -86,10 +88,16 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
 
 int InOrderDynInst::instcount = 0;
 
+int
+InOrderDynInst::cpuId()
+{
+    return cpu->cpuId();
+}
+
 void
-InOrderDynInst::setMachInst(ExtMachInst machInst)
+InOrderDynInst::setStaticInst(StaticInstPtr si)
 {
-    staticInst = StaticInst::decode(machInst, pc.instAddr());
+    staticInst = si;
 
     for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
         _destRegIdx[i] = this->staticInst->destRegIdx(i);
@@ -122,9 +130,6 @@ InOrderDynInst::initVars()
 
     nextStage = 0;
 
-    for(int i = 0; i < MaxInstDestRegs; i++)
-        instResult[i].val.integer = 0;
-
     status.reset();
 
     memAddrReady = false;
@@ -174,21 +179,6 @@ InOrderDynInst::resetInstCount()
 
 InOrderDynInst::~InOrderDynInst()
 {
-    if (fetchMemReq != 0x0) {
-        delete fetchMemReq;
-        fetchMemReq = NULL;
-    }
-
-    if (dataMemReq != 0x0) {
-        delete dataMemReq;
-        dataMemReq = NULL;
-    }
-
-    if (splitMemReq != 0x0) {
-        delete dataMemReq;
-        dataMemReq = NULL;
-    }
-
     if (traceData)
         delete traceData;
 
@@ -280,12 +270,27 @@ InOrderDynInst::memAccess()
 }
 
 
-#if FULL_SYSTEM
-
 Fault
 InOrderDynInst::hwrei()
 {
-    panic("InOrderDynInst: hwrei: unimplemented\n");    
+#if THE_ISA == ALPHA_ISA
+    // Can only do a hwrei when in pal mode.
+    if (!(this->instAddr() & 0x3))
+        return new AlphaISA::UnimplementedOpcodeFault;
+
+    // Set the next PC based on the value of the EXC_ADDR IPR.
+    AlphaISA::PCState pc = this->pcState();
+    pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
+                                          this->threadNumber));
+    this->pcState(pc);
+    if (CPA::available()) {
+        ThreadContext *tc = this->cpu->tcBase(this->threadNumber);
+        CPA::cpa()->swAutoBegin(tc, this->nextInstAddr());
+    }
+
+    // Tell CPU to clear any state it needs to if a hwrei is taken.
+    this->cpu->hwrei(this->threadNumber);
+#endif
     return NoFault;
 }
 
@@ -305,13 +310,46 @@ InOrderDynInst::simPalCheck(int palFunc)
 #endif
     return this->cpu->simPalCheck(palFunc, this->threadNumber);
 }
-#else
+
 void
 InOrderDynInst::syscall(int64_t callnum)
 {
-    cpu->syscall(callnum, this->threadNumber);
+    if (FullSystem)
+        panic("Syscall emulation isn't available in FS mode.\n");
+
+    syscallNum = callnum;
+    cpu->syscallContext(NoFault, this->threadNumber, this);
 }
+
+void
+InOrderDynInst::setSquashInfo(unsigned stage_num)
+{
+    squashingStage = stage_num;
+
+    // If it's a fault, then we need to squash
+    // the faulting instruction too. Squash
+    // functions squash above a seqNum, so we
+    // decrement here for that case
+    if (fault != NoFault) {
+        squashSeqNum = seqNum - 1;
+        return;
+    } else
+        squashSeqNum = seqNum;
+
+#if ISA_HAS_DELAY_SLOT
+    if (staticInst && isControl()) {
+        TheISA::PCState nextPC = pc;
+        TheISA::advancePC(nextPC, staticInst);
+
+        // Check to see if we should squash after the
+        // branch or after a branch delay slot.
+        if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
+            squashSeqNum = seqNum + 1;
+        else
+            squashSeqNum = seqNum;
+    }
 #endif
+}
 
 void
 InOrderDynInst::releaseReq(ResourceRequest* req)
@@ -337,39 +375,48 @@ InOrderDynInst::releaseReq(ResourceRequest* req)
 void
 InOrderDynInst::setIntSrc(int idx, uint64_t val)
 {
-    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Source Value %i being set "
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] Int being set "
             "to %#x.\n", threadNumber, seqNum, idx, val);
-    instSrc[idx].integer = val;
+    instSrc[idx].intVal = val;
 }
 
 /** Records an fp register being set to a value. */
 void
 InOrderDynInst::setFloatSrc(int idx, FloatReg val)
 {
-    instSrc[idx].dbl = val;
+    instSrc[idx].fpVal.f = val;
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FP being set "
+            "to %x, %08f...%08f\n", threadNumber, seqNum, idx,
+            instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val);
 }
 
 /** Records an fp register being set to an integer value. */
 void
-InOrderDynInst::setFloatRegBitsSrc(int idx, uint64_t val)
+InOrderDynInst::setFloatRegBitsSrc(int idx, FloatRegBits val)
 {
-    instSrc[idx].integer = val;
+    instSrc[idx].fpVal.i = val;
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being set "
+            "to %x, %08f...%x\n", threadNumber, seqNum, idx,
+            instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val);
 }
 
 /** Reads a integer register. */
 IntReg
 InOrderDynInst::readIntRegOperand(const StaticInst *si, int idx, ThreadID tid)
 {
-    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
-            threadNumber, seqNum, idx, instSrc[idx].integer);
-    return instSrc[idx].integer;
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] IntVal read as %#x.\n",
+            threadNumber, seqNum, idx, instSrc[idx].intVal);
+    return instSrc[idx].intVal;
 }
 
 /** Reads a FP register. */
 FloatReg
 InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx)
 {
-    return instSrc[idx].dbl;
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPVal being read "
+            "as %x, %08f.\n", threadNumber, seqNum, idx,
+            instSrc[idx].fpVal.i, instSrc[idx].fpVal.f);
+    return instSrc[idx].fpVal.f;
 }
 
 
@@ -377,7 +424,10 @@ InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx)
 FloatRegBits
 InOrderDynInst::readFloatRegOperandBits(const StaticInst *si, int idx)
 {
-    return instSrc[idx].integer;
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being read "
+            "as %x, %08f.\n", threadNumber, seqNum, idx,
+            instSrc[idx].fpVal.i, instSrc[idx].fpVal.f);
+    return instSrc[idx].fpVal.i;
 }
 
 /** Reads a miscellaneous register. */
@@ -396,8 +446,8 @@ InOrderDynInst::readMiscRegOperand(const StaticInst *si, int idx)
 {
     DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
             " read as %#x.\n", threadNumber, seqNum, idx,
-            instSrc[idx].integer);
-    return instSrc[idx].integer;
+            instSrc[idx].intVal);
+    return instSrc[idx].intVal;
 }
 
 
@@ -409,7 +459,7 @@ InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx,
                        const MiscReg &val)
 {
     instResult[idx].type = Integer;
-    instResult[idx].val.integer = val;
+    instResult[idx].res.intVal = val;
     instResult[idx].tick = curTick();
 
     DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
@@ -439,7 +489,7 @@ void
 InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val)
 {
     instResult[idx].type = Integer;
-    instResult[idx].val.integer = val;
+    instResult[idx].res.intVal = val;
     instResult[idx].tick = curTick();
 
     DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
@@ -451,13 +501,13 @@ InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val)
 void
 InOrderDynInst::setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
 {
-    instResult[idx].val.dbl = val;
     instResult[idx].type = Float;
+    instResult[idx].res.fpVal.f = val;
     instResult[idx].tick = curTick();
 
-    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
-            "being set to %#x (result-tick:%i).\n",
-            threadNumber, seqNum, idx, val, instResult[idx].tick);
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. %i "
+            "being set to %#x, %08f (result-tick:%i).\n",
+            threadNumber, seqNum, idx, val, val, instResult[idx].tick);
 }
 
 /** Sets a FP register as a integer. */
@@ -465,11 +515,11 @@ void
 InOrderDynInst::setFloatRegOperandBits(const StaticInst *si, int idx,
                               FloatRegBits val)
 {
-    instResult[idx].type = Integer;
-    instResult[idx].val.integer = val;
+    instResult[idx].type = FloatBits;
+    instResult[idx].res.fpVal.i = val;
     instResult[idx].tick = curTick();
 
-    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
+    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. Bits %i "
             "being set to %#x (result-tick:%i).\n",
             threadNumber, seqNum, idx, val, instResult[idx].tick);
 }
@@ -510,136 +560,17 @@ InOrderDynInst::deallocateContext(int thread_num)
 }
 
 Fault
-InOrderDynInst::readBytes(Addr addr, uint8_t *data,
-                          unsigned size, unsigned flags)
+InOrderDynInst::readMem(Addr addr, uint8_t *data,
+                        unsigned size, unsigned flags)
 {
     return cpu->read(this, addr, data, size, flags);
 }
 
-template<class T>
-inline Fault
-InOrderDynInst::read(Addr addr, T &data, unsigned flags)
-{
-    if (traceData) {
-        traceData->setAddr(addr);
-        traceData->setData(data);
-    }
-    Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
-    data = TheISA::gtoh(data);
-    if (traceData)
-        traceData->setData(data);
-    return fault;
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-InOrderDynInst::read(Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-InOrderDynInst::read(Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-InOrderDynInst::read(Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-InOrderDynInst::read(Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-InOrderDynInst::read(Addr addr, double &data, unsigned flags)
-{
-    return read(addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-InOrderDynInst::read(Addr addr, float &data, unsigned flags)
-{
-    return read(addr, *(uint32_t*)&data, flags);
-}
-
-template<>
-Fault
-InOrderDynInst::read(Addr addr, int32_t &data, unsigned flags)
-{
-    return read(addr, (uint32_t&)data, flags);
-}
-
-Fault
-InOrderDynInst::writeBytes(uint8_t *data, unsigned size,
-                           Addr addr, unsigned flags, uint64_t *res)
-{
-    assert(sizeof(storeData) >= size);
-    memcpy(&storeData, data, size);
-    return cpu->write(this, (uint8_t *)&storeData, size, addr, flags, res);
-}
-
-template<class T>
-inline Fault
-InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
-    storeData  = data;
-
-    DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
-            threadNumber, seqNum, storeData);
-    if (traceData) {
-        traceData->setAddr(addr);
-        traceData->setData(data);
-    }
-    storeData = TheISA::htog(data);
-    return writeBytes((uint8_t*)&data, sizeof(T), addr, flags, res);
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template
-Fault
-InOrderDynInst::write(uint64_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderDynInst::write(uint32_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderDynInst::write(uint16_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-template
-Fault
-InOrderDynInst::write(uint8_t data, Addr addr,
-                       unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-InOrderDynInst::write(double data, Addr addr, unsigned flags, uint64_t *res)
-{
-    return write(*(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-InOrderDynInst::write(float data, Addr addr, unsigned flags, uint64_t *res)
-{
-    return write(*(uint32_t*)&data, addr, flags, res);
-}
-
-
-template<>
 Fault
-InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
+InOrderDynInst::writeMem(uint8_t *data, unsigned size,
+                         Addr addr, unsigned flags, uint64_t *res)
 {
-    return write((uint32_t)data, addr, flags, res);
+    return cpu->write(this, data, size, addr, flags, res);
 }