decoder.hh revision 9037:2f84b98634ff
1/* 2 * Copyright (c) 2012 Google 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 */ 30 31#ifndef __ARCH_X86_DECODER_HH__ 32#define __ARCH_X86_DECODER_HH__ 33 34#include <cassert> 35 36#include "arch/x86/regs/misc.hh" 37#include "arch/x86/types.hh" 38#include "base/bitfield.hh" 39#include "base/misc.hh" 40#include "base/trace.hh" 41#include "base/types.hh" 42#include "cpu/decode_cache.hh" 43#include "cpu/static_inst.hh" 44#include "debug/Decoder.hh" 45 46class ThreadContext; 47 48namespace X86ISA 49{ 50 51class Decoder 52{ 53 private: 54 //These are defined and documented in decoder_tables.cc 55 static const uint8_t Prefixes[256]; 56 static const uint8_t UsesModRM[2][256]; 57 static const uint8_t ImmediateType[2][256]; 58 static const uint8_t SizeTypeToSize[3][10]; 59 60 protected: 61 ThreadContext * tc; 62 //The bytes to be predecoded 63 MachInst fetchChunk; 64 //The pc of the start of fetchChunk 65 Addr basePC; 66 //The pc the current instruction started at 67 Addr origPC; 68 //The offset into fetchChunk of current processing 69 int offset; 70 //The extended machine instruction being generated 71 ExtMachInst emi; 72 HandyM5Reg m5Reg; 73 74 inline uint8_t getNextByte() 75 { 76 return ((uint8_t *)&fetchChunk)[offset]; 77 } 78 79 void getImmediate(int &collected, uint64_t ¤t, int size) 80 { 81 //Figure out how many bytes we still need to get for the 82 //immediate. 83 int toGet = size - collected; 84 //Figure out how many bytes are left in our "buffer" 85 int remaining = sizeof(MachInst) - offset; 86 //Get as much as we need, up to the amount available. 87 toGet = toGet > remaining ? remaining : toGet; 88 89 //Shift the bytes we want to be all the way to the right 90 uint64_t partialImm = fetchChunk >> (offset * 8); 91 //Mask off what we don't want 92 partialImm &= mask(toGet * 8); 93 //Shift it over to overlay with our displacement. 94 partialImm <<= (immediateCollected * 8); 95 //Put it into our displacement 96 current |= partialImm; 97 //Update how many bytes we've collected. 98 collected += toGet; 99 consumeBytes(toGet); 100 } 101 102 inline void consumeByte() 103 { 104 offset++; 105 assert(offset <= sizeof(MachInst)); 106 if(offset == sizeof(MachInst)) 107 outOfBytes = true; 108 } 109 110 inline void consumeBytes(int numBytes) 111 { 112 offset += numBytes; 113 assert(offset <= sizeof(MachInst)); 114 if(offset == sizeof(MachInst)) 115 outOfBytes = true; 116 } 117 118 void doReset(); 119 120 //State machine state 121 protected: 122 //Whether or not we're out of bytes 123 bool outOfBytes; 124 //Whether we've completed generating an ExtMachInst 125 bool instDone; 126 //The size of the displacement value 127 int displacementSize; 128 //The size of the immediate value 129 int immediateSize; 130 //This is how much of any immediate value we've gotten. This is used 131 //for both the actual immediate and the displacement. 132 int immediateCollected; 133 134 enum State { 135 ResetState, 136 PrefixState, 137 OpcodeState, 138 ModRMState, 139 SIBState, 140 DisplacementState, 141 ImmediateState, 142 //We should never get to this state. Getting here is an error. 143 ErrorState 144 }; 145 146 State state; 147 148 //Functions to handle each of the states 149 State doPrefixState(uint8_t); 150 State doOpcodeState(uint8_t); 151 State doModRMState(uint8_t); 152 State doSIBState(uint8_t); 153 State doDisplacementState(); 154 State doImmediateState(); 155 156 public: 157 Decoder(ThreadContext * _tc) : 158 tc(_tc), basePC(0), origPC(0), offset(0), 159 outOfBytes(true), instDone(false), 160 state(ResetState) 161 { 162 memset(&emi, 0, sizeof(emi)); 163 emi.mode.mode = LongMode; 164 emi.mode.submode = SixtyFourBitMode; 165 m5Reg = 0; 166 } 167 168 void reset() 169 { 170 state = ResetState; 171 } 172 173 ThreadContext * getTC() 174 { 175 return tc; 176 } 177 178 void setTC(ThreadContext * _tc) 179 { 180 tc = _tc; 181 } 182 183 void process(); 184 185 //Use this to give data to the decoder. This should be used 186 //when there is control flow. 187 void moreBytes(const PCState &pc, Addr fetchPC, MachInst data) 188 { 189 DPRINTF(Decoder, "Getting more bytes.\n"); 190 basePC = fetchPC; 191 offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; 192 fetchChunk = data; 193 outOfBytes = false; 194 process(); 195 } 196 197 bool needMoreBytes() 198 { 199 return outOfBytes; 200 } 201 202 bool instReady() 203 { 204 return instDone; 205 } 206 207 void 208 updateNPC(X86ISA::PCState &nextPC) 209 { 210 if (!nextPC.size()) { 211 int size = basePC + offset - origPC; 212 DPRINTF(Decoder, 213 "Calculating the instruction size: " 214 "basePC: %#x offset: %#x origPC: %#x size: %d\n", 215 basePC, offset, origPC, size); 216 nextPC.size(size); 217 nextPC.npc(nextPC.pc() + size); 218 } 219 } 220 221 protected: 222 /// Caching for decoded instruction objects. 223 static DecodeCache::InstMap instMap; 224 static DecodeCache::AddrMap<StaticInstPtr> decodePages; 225 226 public: 227 StaticInstPtr decodeInst(ExtMachInst mach_inst); 228 229 /// Decode a machine instruction. 230 /// @param mach_inst The binary instruction to decode. 231 /// @retval A pointer to the corresponding StaticInst object. 232 StaticInstPtr decode(ExtMachInst mach_inst, Addr addr); 233 234 StaticInstPtr 235 decode(X86ISA::PCState &nextPC) 236 { 237 if (!instDone) 238 return NULL; 239 instDone = false; 240 updateNPC(nextPC); 241 return decode(emi, origPC); 242 } 243}; 244 245} // namespace X86ISA 246 247#endif // __ARCH_X86_DECODER_HH__ 248