From b33812ba430bba0ab5ff4e6372b47f4b323f0891 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Tue, 23 Dec 2014 09:31:17 -0500 Subject: 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. --- src/arch/arm/decoder.cc | 52 +++++++++++++- src/arch/arm/decoder.hh | 187 ++++++++++++++++++++++++++++-------------------- 2 files changed, 157 insertions(+), 82 deletions(-) (limited to 'src/arch/arm') 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 -- cgit v1.2.3