decoder.hh revision 9023
19020Sgblack@eecs.umich.edu/*
29020Sgblack@eecs.umich.edu * Copyright (c) 2012 Google
39020Sgblack@eecs.umich.edu * All rights reserved.
49020Sgblack@eecs.umich.edu *
59020Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
69020Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
79020Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
89020Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
99020Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
109020Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
119020Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
129020Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
139020Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
149020Sgblack@eecs.umich.edu * this software without specific prior written permission.
159020Sgblack@eecs.umich.edu *
169020Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179020Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189020Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199020Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209020Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219020Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229020Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239020Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249020Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259020Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269020Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279020Sgblack@eecs.umich.edu *
289020Sgblack@eecs.umich.edu * Authors: Gabe Black
299020Sgblack@eecs.umich.edu */
309020Sgblack@eecs.umich.edu
319020Sgblack@eecs.umich.edu#ifndef __ARCH_X86_DECODER_HH__
329020Sgblack@eecs.umich.edu#define __ARCH_X86_DECODER_HH__
339020Sgblack@eecs.umich.edu
349023Sgblack@eecs.umich.edu#include <cassert>
359023Sgblack@eecs.umich.edu
369023Sgblack@eecs.umich.edu#include "arch/x86/regs/misc.hh"
379023Sgblack@eecs.umich.edu#include "arch/x86/types.hh"
389023Sgblack@eecs.umich.edu#include "base/bitfield.hh"
399023Sgblack@eecs.umich.edu#include "base/misc.hh"
409023Sgblack@eecs.umich.edu#include "base/trace.hh"
419023Sgblack@eecs.umich.edu#include "base/types.hh"
429022Sgblack@eecs.umich.edu#include "cpu/decode_cache.hh"
439022Sgblack@eecs.umich.edu#include "cpu/static_inst_fwd.hh"
449023Sgblack@eecs.umich.edu#include "debug/Decoder.hh"
459023Sgblack@eecs.umich.edu
469023Sgblack@eecs.umich.educlass ThreadContext;
479020Sgblack@eecs.umich.edu
489020Sgblack@eecs.umich.edunamespace X86ISA
499020Sgblack@eecs.umich.edu{
509020Sgblack@eecs.umich.edu
519022Sgblack@eecs.umich.educlass Decoder
529022Sgblack@eecs.umich.edu{
539023Sgblack@eecs.umich.edu  private:
549023Sgblack@eecs.umich.edu    //These are defined and documented in decoder_tables.cc
559023Sgblack@eecs.umich.edu    static const uint8_t Prefixes[256];
569023Sgblack@eecs.umich.edu    static const uint8_t UsesModRM[2][256];
579023Sgblack@eecs.umich.edu    static const uint8_t ImmediateType[2][256];
589023Sgblack@eecs.umich.edu    static const uint8_t SizeTypeToSize[3][10];
599023Sgblack@eecs.umich.edu
609023Sgblack@eecs.umich.edu  protected:
619023Sgblack@eecs.umich.edu    ThreadContext * tc;
629023Sgblack@eecs.umich.edu    //The bytes to be predecoded
639023Sgblack@eecs.umich.edu    MachInst fetchChunk;
649023Sgblack@eecs.umich.edu    //The pc of the start of fetchChunk
659023Sgblack@eecs.umich.edu    Addr basePC;
669023Sgblack@eecs.umich.edu    //The pc the current instruction started at
679023Sgblack@eecs.umich.edu    Addr origPC;
689023Sgblack@eecs.umich.edu    //The offset into fetchChunk of current processing
699023Sgblack@eecs.umich.edu    int offset;
709023Sgblack@eecs.umich.edu    //The extended machine instruction being generated
719023Sgblack@eecs.umich.edu    ExtMachInst emi;
729023Sgblack@eecs.umich.edu    HandyM5Reg m5Reg;
739023Sgblack@eecs.umich.edu
749023Sgblack@eecs.umich.edu    inline uint8_t getNextByte()
759023Sgblack@eecs.umich.edu    {
769023Sgblack@eecs.umich.edu        return ((uint8_t *)&fetchChunk)[offset];
779023Sgblack@eecs.umich.edu    }
789023Sgblack@eecs.umich.edu
799023Sgblack@eecs.umich.edu    void getImmediate(int &collected, uint64_t &current, int size)
809023Sgblack@eecs.umich.edu    {
819023Sgblack@eecs.umich.edu        //Figure out how many bytes we still need to get for the
829023Sgblack@eecs.umich.edu        //immediate.
839023Sgblack@eecs.umich.edu        int toGet = size - collected;
849023Sgblack@eecs.umich.edu        //Figure out how many bytes are left in our "buffer"
859023Sgblack@eecs.umich.edu        int remaining = sizeof(MachInst) - offset;
869023Sgblack@eecs.umich.edu        //Get as much as we need, up to the amount available.
879023Sgblack@eecs.umich.edu        toGet = toGet > remaining ? remaining : toGet;
889023Sgblack@eecs.umich.edu
899023Sgblack@eecs.umich.edu        //Shift the bytes we want to be all the way to the right
909023Sgblack@eecs.umich.edu        uint64_t partialImm = fetchChunk >> (offset * 8);
919023Sgblack@eecs.umich.edu        //Mask off what we don't want
929023Sgblack@eecs.umich.edu        partialImm &= mask(toGet * 8);
939023Sgblack@eecs.umich.edu        //Shift it over to overlay with our displacement.
949023Sgblack@eecs.umich.edu        partialImm <<= (immediateCollected * 8);
959023Sgblack@eecs.umich.edu        //Put it into our displacement
969023Sgblack@eecs.umich.edu        current |= partialImm;
979023Sgblack@eecs.umich.edu        //Update how many bytes we've collected.
989023Sgblack@eecs.umich.edu        collected += toGet;
999023Sgblack@eecs.umich.edu        consumeBytes(toGet);
1009023Sgblack@eecs.umich.edu    }
1019023Sgblack@eecs.umich.edu
1029023Sgblack@eecs.umich.edu    inline void consumeByte()
1039023Sgblack@eecs.umich.edu    {
1049023Sgblack@eecs.umich.edu        offset++;
1059023Sgblack@eecs.umich.edu        assert(offset <= sizeof(MachInst));
1069023Sgblack@eecs.umich.edu        if(offset == sizeof(MachInst))
1079023Sgblack@eecs.umich.edu            outOfBytes = true;
1089023Sgblack@eecs.umich.edu    }
1099023Sgblack@eecs.umich.edu
1109023Sgblack@eecs.umich.edu    inline void consumeBytes(int numBytes)
1119023Sgblack@eecs.umich.edu    {
1129023Sgblack@eecs.umich.edu        offset += numBytes;
1139023Sgblack@eecs.umich.edu        assert(offset <= sizeof(MachInst));
1149023Sgblack@eecs.umich.edu        if(offset == sizeof(MachInst))
1159023Sgblack@eecs.umich.edu            outOfBytes = true;
1169023Sgblack@eecs.umich.edu    }
1179023Sgblack@eecs.umich.edu
1189023Sgblack@eecs.umich.edu    void doReset();
1199023Sgblack@eecs.umich.edu
1209023Sgblack@eecs.umich.edu    //State machine state
1219023Sgblack@eecs.umich.edu  protected:
1229023Sgblack@eecs.umich.edu    //Whether or not we're out of bytes
1239023Sgblack@eecs.umich.edu    bool outOfBytes;
1249023Sgblack@eecs.umich.edu    //Whether we've completed generating an ExtMachInst
1259023Sgblack@eecs.umich.edu    bool instDone;
1269023Sgblack@eecs.umich.edu    //The size of the displacement value
1279023Sgblack@eecs.umich.edu    int displacementSize;
1289023Sgblack@eecs.umich.edu    //The size of the immediate value
1299023Sgblack@eecs.umich.edu    int immediateSize;
1309023Sgblack@eecs.umich.edu    //This is how much of any immediate value we've gotten. This is used
1319023Sgblack@eecs.umich.edu    //for both the actual immediate and the displacement.
1329023Sgblack@eecs.umich.edu    int immediateCollected;
1339023Sgblack@eecs.umich.edu
1349023Sgblack@eecs.umich.edu    enum State {
1359023Sgblack@eecs.umich.edu        ResetState,
1369023Sgblack@eecs.umich.edu        PrefixState,
1379023Sgblack@eecs.umich.edu        OpcodeState,
1389023Sgblack@eecs.umich.edu        ModRMState,
1399023Sgblack@eecs.umich.edu        SIBState,
1409023Sgblack@eecs.umich.edu        DisplacementState,
1419023Sgblack@eecs.umich.edu        ImmediateState,
1429023Sgblack@eecs.umich.edu        //We should never get to this state. Getting here is an error.
1439023Sgblack@eecs.umich.edu        ErrorState
1449023Sgblack@eecs.umich.edu    };
1459023Sgblack@eecs.umich.edu
1469023Sgblack@eecs.umich.edu    State state;
1479023Sgblack@eecs.umich.edu
1489023Sgblack@eecs.umich.edu    //Functions to handle each of the states
1499023Sgblack@eecs.umich.edu    State doPrefixState(uint8_t);
1509023Sgblack@eecs.umich.edu    State doOpcodeState(uint8_t);
1519023Sgblack@eecs.umich.edu    State doModRMState(uint8_t);
1529023Sgblack@eecs.umich.edu    State doSIBState(uint8_t);
1539023Sgblack@eecs.umich.edu    State doDisplacementState();
1549023Sgblack@eecs.umich.edu    State doImmediateState();
1559023Sgblack@eecs.umich.edu
1569023Sgblack@eecs.umich.edu  public:
1579023Sgblack@eecs.umich.edu    Decoder(ThreadContext * _tc) :
1589023Sgblack@eecs.umich.edu        tc(_tc), basePC(0), origPC(0), offset(0),
1599023Sgblack@eecs.umich.edu        outOfBytes(true), instDone(false),
1609023Sgblack@eecs.umich.edu        state(ResetState)
1619023Sgblack@eecs.umich.edu    {
1629023Sgblack@eecs.umich.edu        emi.mode.mode = LongMode;
1639023Sgblack@eecs.umich.edu        emi.mode.submode = SixtyFourBitMode;
1649023Sgblack@eecs.umich.edu        m5Reg = 0;
1659023Sgblack@eecs.umich.edu    }
1669023Sgblack@eecs.umich.edu
1679023Sgblack@eecs.umich.edu    void reset()
1689023Sgblack@eecs.umich.edu    {
1699023Sgblack@eecs.umich.edu        state = ResetState;
1709023Sgblack@eecs.umich.edu    }
1719023Sgblack@eecs.umich.edu
1729023Sgblack@eecs.umich.edu    ThreadContext * getTC()
1739023Sgblack@eecs.umich.edu    {
1749023Sgblack@eecs.umich.edu        return tc;
1759023Sgblack@eecs.umich.edu    }
1769023Sgblack@eecs.umich.edu
1779023Sgblack@eecs.umich.edu    void setTC(ThreadContext * _tc)
1789023Sgblack@eecs.umich.edu    {
1799023Sgblack@eecs.umich.edu        tc = _tc;
1809023Sgblack@eecs.umich.edu    }
1819023Sgblack@eecs.umich.edu
1829023Sgblack@eecs.umich.edu    void process();
1839023Sgblack@eecs.umich.edu
1849023Sgblack@eecs.umich.edu    //Use this to give data to the decoder. This should be used
1859023Sgblack@eecs.umich.edu    //when there is control flow.
1869023Sgblack@eecs.umich.edu    void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
1879023Sgblack@eecs.umich.edu    {
1889023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Getting more bytes.\n");
1899023Sgblack@eecs.umich.edu        basePC = fetchPC;
1909023Sgblack@eecs.umich.edu        offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
1919023Sgblack@eecs.umich.edu        fetchChunk = data;
1929023Sgblack@eecs.umich.edu        outOfBytes = false;
1939023Sgblack@eecs.umich.edu        process();
1949023Sgblack@eecs.umich.edu    }
1959023Sgblack@eecs.umich.edu
1969023Sgblack@eecs.umich.edu    bool needMoreBytes()
1979023Sgblack@eecs.umich.edu    {
1989023Sgblack@eecs.umich.edu        return outOfBytes;
1999023Sgblack@eecs.umich.edu    }
2009023Sgblack@eecs.umich.edu
2019023Sgblack@eecs.umich.edu    bool instReady()
2029023Sgblack@eecs.umich.edu    {
2039023Sgblack@eecs.umich.edu        return instDone;
2049023Sgblack@eecs.umich.edu    }
2059023Sgblack@eecs.umich.edu
2069023Sgblack@eecs.umich.edu    void
2079023Sgblack@eecs.umich.edu    updateNPC(X86ISA::PCState &nextPC)
2089023Sgblack@eecs.umich.edu    {
2099023Sgblack@eecs.umich.edu        if (!nextPC.size()) {
2109023Sgblack@eecs.umich.edu            int size = basePC + offset - origPC;
2119023Sgblack@eecs.umich.edu            DPRINTF(Decoder,
2129023Sgblack@eecs.umich.edu                    "Calculating the instruction size: "
2139023Sgblack@eecs.umich.edu                    "basePC: %#x offset: %#x origPC: %#x size: %d\n",
2149023Sgblack@eecs.umich.edu                    basePC, offset, origPC, size);
2159023Sgblack@eecs.umich.edu            nextPC.size(size);
2169023Sgblack@eecs.umich.edu            nextPC.npc(nextPC.pc() + size);
2179023Sgblack@eecs.umich.edu        }
2189023Sgblack@eecs.umich.edu    }
2199023Sgblack@eecs.umich.edu
2209022Sgblack@eecs.umich.edu  protected:
2219022Sgblack@eecs.umich.edu    /// A cache of decoded instruction objects.
2229022Sgblack@eecs.umich.edu    static DecodeCache defaultCache;
2239022Sgblack@eecs.umich.edu
2249022Sgblack@eecs.umich.edu  public:
2259022Sgblack@eecs.umich.edu    StaticInstPtr decodeInst(ExtMachInst mach_inst);
2269022Sgblack@eecs.umich.edu
2279022Sgblack@eecs.umich.edu    /// Decode a machine instruction.
2289022Sgblack@eecs.umich.edu    /// @param mach_inst The binary instruction to decode.
2299022Sgblack@eecs.umich.edu    /// @retval A pointer to the corresponding StaticInst object.
2309022Sgblack@eecs.umich.edu    StaticInstPtr
2319022Sgblack@eecs.umich.edu    decode(ExtMachInst mach_inst, Addr addr)
2329022Sgblack@eecs.umich.edu    {
2339022Sgblack@eecs.umich.edu        return defaultCache.decode(this, mach_inst, addr);
2349022Sgblack@eecs.umich.edu    }
2359023Sgblack@eecs.umich.edu
2369023Sgblack@eecs.umich.edu    StaticInstPtr
2379023Sgblack@eecs.umich.edu    decode(X86ISA::PCState &nextPC)
2389023Sgblack@eecs.umich.edu    {
2399023Sgblack@eecs.umich.edu        if (!instDone)
2409023Sgblack@eecs.umich.edu            return NULL;
2419023Sgblack@eecs.umich.edu        instDone = false;
2429023Sgblack@eecs.umich.edu        updateNPC(nextPC);
2439023Sgblack@eecs.umich.edu        return decode(emi, origPC);
2449023Sgblack@eecs.umich.edu    }
2459022Sgblack@eecs.umich.edu};
2469020Sgblack@eecs.umich.edu
2479020Sgblack@eecs.umich.edu} // namespace X86ISA
2489020Sgblack@eecs.umich.edu
2499020Sgblack@eecs.umich.edu#endif // __ARCH_X86_DECODER_HH__
250