ARM: Fix a memory leak with the table walker.
[gem5.git] / src / arch / arm / predecoder.cc
index 20c7058b0d5bd4aeb81255c2172f311a3557c00c..a221f4e3016f6aa34b6049f5fceaffe6aab88c78 100644 (file)
 
 #include "arch/arm/isa_traits.hh"
 #include "arch/arm/predecoder.hh"
+#include "arch/arm/utility.hh"
 #include "base/trace.hh"
 #include "cpu/thread_context.hh"
+#include "debug/Predecoder.hh"
 
 namespace ArmISA
 {
 
-void
-Predecoder::advanceThumbCond()
-{
-    uint8_t condMask = itstate.mask;
-    uint8_t thumbCond = itstate.cond;
-    DPRINTF(Predecoder, "Advancing ITSTATE from %#x, %#x.\n",
-            thumbCond, condMask);
-    condMask = condMask << 1;
-    uint8_t newBit = bits(condMask, 4);
-    condMask &= mask(4);
-    if (condMask == 0) {
-        thumbCond = 0;
-    } else {
-        replaceBits(thumbCond, 0, newBit);
-    }
-    DPRINTF(Predecoder, "Advancing ITSTATE to %#x, %#x.\n",
-            thumbCond, condMask);
-    itstate.mask = condMask;
-    itstate.cond = thumbCond;
-}
-
 void
 Predecoder::process()
 {
+    // emi is typically ready, with some caveats below...
+    emiReady = true;
+
     if (!emi.thumb) {
         emi.instBits = data;
         emi.sevenAndFour = bits(data, 7) && bits(data, 4);
         emi.isMisc = (bits(data, 24, 23) == 0x2 &&
                       bits(data, 20) == 0);
+        consumeBytes(4);
         DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi);
     } else {
         uint16_t word = (data >> (offset * 8));
@@ -85,14 +70,9 @@ Predecoder::process()
             // A 32 bit thumb inst is half collected.
             emi.instBits = emi.instBits | word;
             bigThumb = false;
-            offset += 2;
+            consumeBytes(2);
             DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
                     emi.instBits);
-            if (itstate.mask) {
-                emi.itstate = itstate;
-                advanceThumbCond();
-                emi.newItstate = itstate;
-            }
         } else {
             uint16_t highBits = word & 0xF800;
             if (highBits == 0xE800 || highBits == 0xF000 ||
@@ -104,23 +84,20 @@ Predecoder::process()
                     emi.instBits = (data >> 16) | (data << 16);
                     DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
                             emi.instBits);
-                    offset += 4;
-                    if (itstate.mask) {
-                        emi.itstate = itstate;
-                        advanceThumbCond();
-                        emi.newItstate = itstate;
-                    }
+                    consumeBytes(4);
                 } else {
                     // We only have the first half word.
                     DPRINTF(Predecoder,
                             "First half of 32 bit Thumb.\n");
                     emi.instBits = (uint32_t)word << 16;
                     bigThumb = true;
-                    offset += 2;
+                    consumeBytes(2);
+                    // emi not ready yet.
+                    emiReady = false;
                 }
             } else {
                 // A 16 bit thumb inst.
-                offset += 2;
+                consumeBytes(2);
                 emi.instBits = word;
                 // Set the condition code field artificially.
                 emi.condCode = COND_UC;
@@ -128,16 +105,11 @@ Predecoder::process()
                         emi.instBits);
                 if (bits(word, 15, 8) == 0xbf &&
                         bits(word, 3, 0) != 0x0) {
-                    emi.itstate = itstate;
-                    itstate = bits(word, 7, 0);
-                    emi.newItstate = itstate;
+                    foundIt = true;
+                    itBits = bits(word, 7, 0);
                     DPRINTF(Predecoder,
                             "IT detected, cond = %#x, mask = %#x\n",
-                            itstate.cond, itstate.mask);
-                } else if (itstate.mask) {
-                    emi.itstate = itstate;
-                    advanceThumbCond();
-                    emi.newItstate = itstate;
+                            itBits.cond, itBits.mask);
                 }
             }
         }
@@ -147,17 +119,16 @@ Predecoder::process()
 //Use this to give data to the predecoder. This should be used
 //when there is control flow.
 void
-Predecoder::moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
 {
     data = inst;
-    offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
-    emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0;
+    offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
+    emi.thumb = pc.thumb();
     FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
     emi.fpscrLen = fpscr.len;
     emi.fpscrStride = fpscr.stride;
-    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
-    itstate.top6 = cpsr.it2;
-    itstate.bottom2 = cpsr.it1;
+
+    outOfBytes = false;
     process();
 }