decoder.hh revision 9024
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" 439024Sgblack@eecs.umich.edu#include "cpu/static_inst.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 ¤t, 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: 2219024Sgblack@eecs.umich.edu /// Caching for decoded instruction objects. 2229024Sgblack@eecs.umich.edu static DecodeCache::InstMap instMap; 2239024Sgblack@eecs.umich.edu static DecodeCache::AddrMap<StaticInstPtr> decodePages; 2249022Sgblack@eecs.umich.edu 2259022Sgblack@eecs.umich.edu public: 2269022Sgblack@eecs.umich.edu StaticInstPtr decodeInst(ExtMachInst mach_inst); 2279022Sgblack@eecs.umich.edu 2289022Sgblack@eecs.umich.edu /// Decode a machine instruction. 2299022Sgblack@eecs.umich.edu /// @param mach_inst The binary instruction to decode. 2309022Sgblack@eecs.umich.edu /// @retval A pointer to the corresponding StaticInst object. 2319024Sgblack@eecs.umich.edu StaticInstPtr decode(ExtMachInst mach_inst, Addr addr); 2329023Sgblack@eecs.umich.edu 2339023Sgblack@eecs.umich.edu StaticInstPtr 2349023Sgblack@eecs.umich.edu decode(X86ISA::PCState &nextPC) 2359023Sgblack@eecs.umich.edu { 2369023Sgblack@eecs.umich.edu if (!instDone) 2379023Sgblack@eecs.umich.edu return NULL; 2389023Sgblack@eecs.umich.edu instDone = false; 2399023Sgblack@eecs.umich.edu updateNPC(nextPC); 2409023Sgblack@eecs.umich.edu return decode(emi, origPC); 2419023Sgblack@eecs.umich.edu } 2429022Sgblack@eecs.umich.edu}; 2439020Sgblack@eecs.umich.edu 2449020Sgblack@eecs.umich.edu} // namespace X86ISA 2459020Sgblack@eecs.umich.edu 2469020Sgblack@eecs.umich.edu#endif // __ARCH_X86_DECODER_HH__ 247