summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2014-12-23 09:31:17 -0500
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2014-12-23 09:31:17 -0500
commitb33812ba430bba0ab5ff4e6372b47f4b323f0891 (patch)
tree64a538067d4daf9dbb5c4b94e7612a540af0d5b3 /src/arch
parent070b4a81dbf9cc040ecb771e128993ae519cf80f (diff)
downloadgem5-b33812ba430bba0ab5ff4e6372b47f4b323f0891.tar.xz
arm: Clean up and document decoder API
This changeset adds more documentation to the ArmISA::Decoder class and restructures it slightly to make API groups more obvious.
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/arm/decoder.cc52
-rw-r--r--src/arch/arm/decoder.hh187
2 files changed, 157 insertions, 82 deletions
diff --git a/src/arch/arm/decoder.cc b/src/arch/arm/decoder.cc
index 940d85b8e..f57e340de 100644
--- a/src/arch/arm/decoder.cc
+++ b/src/arch/arm/decoder.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2012-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -51,6 +51,23 @@ namespace ArmISA
GenericISA::BasicDecodeCache Decoder::defaultCache;
+Decoder::Decoder()
+ : data(0), fpscrLen(0), fpscrStride(0)
+{
+ reset();
+}
+
+void
+Decoder::reset()
+{
+ bigThumb = false;
+ offset = 0;
+ emi = 0;
+ instDone = false;
+ outOfBytes = true;
+ foundIt = false;
+}
+
void
Decoder::process()
{
@@ -118,8 +135,15 @@ Decoder::process()
}
}
-//Use this to give data to the decoder. This should be used
-//when there is control flow.
+void
+Decoder::consumeBytes(int numBytes)
+{
+ offset += numBytes;
+ assert(offset <= sizeof(MachInst));
+ if (offset == sizeof(MachInst))
+ outOfBytes = true;
+}
+
void
Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
@@ -134,4 +158,26 @@ Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
process();
}
+StaticInstPtr
+Decoder::decode(ArmISA::PCState &pc)
+{
+ if (!instDone)
+ return NULL;
+
+ const int inst_size((!emi.thumb || emi.bigThumb) ? 4 : 2);
+ ExtMachInst this_emi(emi);
+
+ pc.npc(pc.pc() + inst_size);
+ if (foundIt)
+ pc.nextItstate(itBits);
+ this_emi.itstate = pc.itstate();
+ pc.size(inst_size);
+
+ emi = 0;
+ instDone = false;
+ foundIt = false;
+
+ return decode(this_emi, pc.instAddr());
+}
+
}
diff --git a/src/arch/arm/decoder.hh b/src/arch/arm/decoder.hh
index 315a3b6ad..757b6d683 100644
--- a/src/arch/arm/decoder.hh
+++ b/src/arch/arm/decoder.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -70,100 +70,129 @@ class Decoder
int fpscrLen;
int fpscrStride;
- public:
- void reset()
- {
- bigThumb = false;
- offset = 0;
- emi = 0;
- instDone = false;
- outOfBytes = true;
- foundIt = false;
- }
-
- Decoder() : data(0), fpscrLen(0), fpscrStride(0)
- {
- reset();
- }
+ /// A cache of decoded instruction objects.
+ static GenericISA::BasicDecodeCache defaultCache;
+ /**
+ * Pre-decode an instruction from the current state of the
+ * decoder.
+ */
void process();
- //Use this to give data to the decoder. This should be used
- //when there is control flow.
+ /**
+ * Consume bytes by moving the offset into the data word and
+ * sanity check the results.
+ */
+ void consumeBytes(int numBytes);
+
+ public: // Decoder API
+ Decoder();
+
+ /** Reset the decoders internal state. */
+ void reset();
+
+ /**
+ * Can the decoder accept more data?
+ *
+ * A CPU model uses this method to determine if the decoder can
+ * accept more data. Note that an instruction can be ready (see
+ * instReady() even if this method returns true.
+ */
+ bool needMoreBytes() const { return outOfBytes; }
+
+ /**
+ * Is an instruction ready to be decoded?
+ *
+ * CPU models call this method to determine if decode() will
+ * return a new instruction on the next call. It typically only
+ * returns false if the decoder hasn't received enough data to
+ * decode a full instruction.
+ */
+ bool instReady() const { return instDone; }
+
+ /**
+ * Feed data to the decoder.
+ *
+ * A CPU model uses this interface to load instruction data into
+ * the decoder. Once enough data has been loaded (check with
+ * instReady()), a decoded instruction can be retrieved using
+ * decode(ArmISA::PCState).
+ *
+ * This method is intended to support both fixed-length and
+ * variable-length instructions. Instruction data is fetch in
+ * MachInst blocks (which correspond to the size of a typical
+ * insturction). The method might need to be called multiple times
+ * if the instruction spans multiple blocks, in that case
+ * needMoreBytes() will return true and instReady() will return
+ * false.
+ *
+ * The fetchPC parameter is used to indicate where in memory the
+ * instruction was fetched from. This is should be the same
+ * address as the pc. If fetching multiple blocks, it indicates
+ * where subsequent blocks are fetched from (pc + n *
+ * sizeof(MachInst)).
+ *
+ * @param pc Instruction pointer that we are decoding.
+ * @param fetchPC The address this chunk was fetched from.
+ * @param inst Raw instruction data.
+ */
void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst);
- //Use this to give data to the decoder. This should be used
- //when instructions are executed in order.
- void moreBytes(MachInst machInst)
+ /**
+ * Decode an instruction or fetch it from the code cache.
+ *
+ * This method decodes the currently pending pre-decoded
+ * instruction. Data must be fed to the decoder using moreBytes()
+ * until instReady() is true before calling this method.
+ *
+ * @param pc Instruction pointer that we are decoding.
+ * @return A pointer to a static instruction or NULL if the
+ * decoder isn't ready (see instReady()).
+ */
+ StaticInstPtr decode(ArmISA::PCState &pc);
+
+ /**
+ * Decode a pre-decoded machine instruction.
+ *
+ * @warn This method takes a pre-decoded instruction as its
+ * argument. It should typically not be called directly.
+ *
+ * @param mach_inst A pre-decoded instruction
+ * @retval A pointer to the corresponding StaticInst object.
+ */
+ StaticInstPtr decode(ExtMachInst mach_inst, Addr addr)
{
- moreBytes(0, 0, machInst);
- }
-
- inline void consumeBytes(int numBytes)
- {
- offset += numBytes;
- assert(offset <= sizeof(MachInst));
- if (offset == sizeof(MachInst))
- outOfBytes = true;
+ return defaultCache.decode(this, mach_inst, addr);
}
- bool needMoreBytes() const
- {
- return outOfBytes;
- }
+ /**
+ * Decode a machine instruction without calling the cache.
+ *
+ * @note The implementation of this method is generated by the ISA
+ * parser script.
+ *
+ * @warn This method takes a pre-decoded instruction as its
+ * argument. It should typically not be called directly.
+ *
+ * @param mach_inst The binary instruction to decode.
+ * @retval A pointer to the corresponding StaticInst object.
+ */
+ StaticInstPtr decodeInst(ExtMachInst mach_inst);
- bool instReady() const
- {
- return instDone;
- }
+ /**
+ * Take over the state from an old decoder when switching CPUs.
+ *
+ * @param old Decoder used in old CPU
+ */
+ void takeOverFrom(Decoder *old) {}
- int getInstSize() const
- {
- return (!emi.thumb || emi.bigThumb) ? 4 : 2;
- }
+ public: // ARM-specific decoder state manipulation
void setContext(FPSCR fpscr)
{
fpscrLen = fpscr.len;
fpscrStride = fpscr.stride;
}
-
- void takeOverFrom(Decoder *old) {}
-
- protected:
- /// A cache of decoded instruction objects.
- static GenericISA::BasicDecodeCache defaultCache;
-
- public:
- StaticInstPtr decodeInst(ExtMachInst mach_inst);
-
- /// Decode a machine instruction.
- /// @param mach_inst The binary instruction to decode.
- /// @retval A pointer to the corresponding StaticInst object.
- StaticInstPtr
- decode(ExtMachInst mach_inst, Addr addr)
- {
- return defaultCache.decode(this, mach_inst, addr);
- }
-
- StaticInstPtr
- decode(ArmISA::PCState &nextPC)
- {
- if (!instDone)
- return NULL;
-
- assert(instDone);
- ExtMachInst thisEmi = emi;
- nextPC.npc(nextPC.pc() + getInstSize());
- if (foundIt)
- nextPC.nextItstate(itBits);
- thisEmi.itstate = nextPC.itstate();
- nextPC.size(getInstSize());
- emi = 0;
- instDone = false;
- foundIt = false;
- return decode(thisEmi, nextPC.instAddr());
- }
};
} // namespace ArmISA