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#include <vector> 36 37#include "arch/x86/regs/misc.hh" 38#include "arch/x86/types.hh" 39#include "base/bitfield.hh" 40#include "base/misc.hh" 41#include "base/trace.hh" 42#include "base/types.hh" 43#include "cpu/decode_cache.hh" 44#include "cpu/static_inst.hh" 45#include "debug/Decoder.hh" 46 47namespace X86ISA 48{ 49 50class Decoder 51{ 52 private: 53 //These are defined and documented in decoder_tables.cc 54 static const uint8_t Prefixes[256]; 55 static const uint8_t UsesModRM[2][256]; 56 static const uint8_t ImmediateType[2][256]; 57 static const uint8_t SizeTypeToSize[3][10]; 58 59 protected: 60 struct InstBytes 61 { 62 StaticInstPtr si; 63 std::vector<MachInst> chunks; 64 std::vector<MachInst> masks; 65 int lastOffset; 66 67 InstBytes() : lastOffset(0) 68 {} 69 }; 70 71 static InstBytes dummy; 72 73 //The bytes to be predecoded 74 MachInst fetchChunk; 75 InstBytes *instBytes; 76 int chunkIdx; 77 //The pc of the start of fetchChunk 78 Addr basePC; 79 //The pc the current instruction started at 80 Addr origPC; 81 //The offset into fetchChunk of current processing 82 int offset; 83 //The extended machine instruction being generated 84 ExtMachInst emi; 85 //Predecoding state 86 X86Mode mode; 87 X86SubMode submode; 88 uint8_t altOp; 89 uint8_t defOp; 90 uint8_t altAddr; 91 uint8_t defAddr; 92 uint8_t stack; 93 94 uint8_t getNextByte() 95 { 96 return ((uint8_t *)&fetchChunk)[offset]; 97 } 98 99 void getImmediate(int &collected, uint64_t ¤t, int size) 100 { 101 //Figure out how many bytes we still need to get for the 102 //immediate. 103 int toGet = size - collected; 104 //Figure out how many bytes are left in our "buffer" 105 int remaining = sizeof(MachInst) - offset; 106 //Get as much as we need, up to the amount available. 107 toGet = toGet > remaining ? remaining : toGet; 108 109 //Shift the bytes we want to be all the way to the right 110 uint64_t partialImm = fetchChunk >> (offset * 8); 111 //Mask off what we don't want 112 partialImm &= mask(toGet * 8); 113 //Shift it over to overlay with our displacement. 114 partialImm <<= (immediateCollected * 8); 115 //Put it into our displacement 116 current |= partialImm; 117 //Update how many bytes we've collected. 118 collected += toGet; 119 consumeBytes(toGet); 120 } 121 122 void updateOffsetState() 123 { 124 assert(offset <= sizeof(MachInst)); 125 if (offset == sizeof(MachInst)) { 126 DPRINTF(Decoder, "At the end of a chunk, idx = %d, chunks = %d.\n", 127 chunkIdx, instBytes->chunks.size()); 128 chunkIdx++; 129 if (chunkIdx == instBytes->chunks.size()) { 130 outOfBytes = true; 131 } else { 132 offset = 0; 133 fetchChunk = instBytes->chunks[chunkIdx]; 134 basePC += sizeof(MachInst); 135 } 136 } 137 } 138 139 void consumeByte() 140 { 141 offset++; 142 updateOffsetState(); 143 } 144 145 void consumeBytes(int numBytes) 146 { 147 offset += numBytes; 148 updateOffsetState(); 149 } 150 151 //State machine state 152 protected: 153 //Whether or not we're out of bytes 154 bool outOfBytes; 155 //Whether we've completed generating an ExtMachInst 156 bool instDone; 157 //The size of the displacement value 158 int displacementSize; 159 //The size of the immediate value 160 int immediateSize; 161 //This is how much of any immediate value we've gotten. This is used 162 //for both the actual immediate and the displacement. 163 int immediateCollected; 164 165 enum State { 166 ResetState, 167 FromCacheState, 168 PrefixState, 169 OpcodeState, 170 ModRMState, 171 SIBState, 172 DisplacementState, 173 ImmediateState, 174 //We should never get to this state. Getting here is an error. 175 ErrorState 176 }; 177 178 State state; 179 180 //Functions to handle each of the states 181 State doResetState(); 182 State doFromCacheState(); 183 State doPrefixState(uint8_t); 184 State doOpcodeState(uint8_t); 185 State doModRMState(uint8_t); 186 State doSIBState(uint8_t); 187 State doDisplacementState(); 188 State doImmediateState(); 189 190 protected: 191 /// Caching for decoded instruction objects. 192 193 typedef MiscReg CacheKey; 194 195 typedef DecodeCache::AddrMap<Decoder::InstBytes> DecodePages; 196 DecodePages *decodePages; 197 typedef m5::hash_map<CacheKey, DecodePages *> AddrCacheMap; 198 AddrCacheMap addrCacheMap; 199 200 DecodeCache::InstMap *instMap; 201 typedef m5::hash_map<CacheKey, DecodeCache::InstMap *> InstCacheMap; 202 static InstCacheMap instCacheMap; 203 204 public: 205 Decoder() : basePC(0), origPC(0), offset(0), 206 outOfBytes(true), instDone(false), 207 state(ResetState) 208 { 209 memset(&emi, 0, sizeof(emi)); 210 mode = LongMode; 211 submode = SixtyFourBitMode; 212 emi.mode.mode = mode; 213 emi.mode.submode = submode; 214 altOp = 0; 215 defOp = 0; 216 altAddr = 0; 217 defAddr = 0; 218 stack = 0; 219 instBytes = &dummy; 220 decodePages = NULL; 221 instMap = NULL; 222 } 223 224 void setM5Reg(HandyM5Reg m5Reg) 225 { 226 mode = (X86Mode)(uint64_t)m5Reg.mode; 227 submode = (X86SubMode)(uint64_t)m5Reg.submode; 228 emi.mode.mode = mode; 229 emi.mode.submode = submode; 230 altOp = m5Reg.altOp; 231 defOp = m5Reg.defOp; 232 altAddr = m5Reg.altAddr; 233 defAddr = m5Reg.defAddr; 234 stack = m5Reg.stack; 235 236 AddrCacheMap::iterator amIter = addrCacheMap.find(m5Reg); 237 if (amIter != addrCacheMap.end()) { 238 decodePages = amIter->second; 239 } else { 240 decodePages = new DecodePages; 241 addrCacheMap[m5Reg] = decodePages; 242 } 243 244 InstCacheMap::iterator imIter = instCacheMap.find(m5Reg); 245 if (imIter != instCacheMap.end()) { 246 instMap = imIter->second; 247 } else { 248 instMap = new DecodeCache::InstMap; 249 instCacheMap[m5Reg] = instMap; 250 } 251 } 252
| 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#include <vector> 36 37#include "arch/x86/regs/misc.hh" 38#include "arch/x86/types.hh" 39#include "base/bitfield.hh" 40#include "base/misc.hh" 41#include "base/trace.hh" 42#include "base/types.hh" 43#include "cpu/decode_cache.hh" 44#include "cpu/static_inst.hh" 45#include "debug/Decoder.hh" 46 47namespace X86ISA 48{ 49 50class Decoder 51{ 52 private: 53 //These are defined and documented in decoder_tables.cc 54 static const uint8_t Prefixes[256]; 55 static const uint8_t UsesModRM[2][256]; 56 static const uint8_t ImmediateType[2][256]; 57 static const uint8_t SizeTypeToSize[3][10]; 58 59 protected: 60 struct InstBytes 61 { 62 StaticInstPtr si; 63 std::vector<MachInst> chunks; 64 std::vector<MachInst> masks; 65 int lastOffset; 66 67 InstBytes() : lastOffset(0) 68 {} 69 }; 70 71 static InstBytes dummy; 72 73 //The bytes to be predecoded 74 MachInst fetchChunk; 75 InstBytes *instBytes; 76 int chunkIdx; 77 //The pc of the start of fetchChunk 78 Addr basePC; 79 //The pc the current instruction started at 80 Addr origPC; 81 //The offset into fetchChunk of current processing 82 int offset; 83 //The extended machine instruction being generated 84 ExtMachInst emi; 85 //Predecoding state 86 X86Mode mode; 87 X86SubMode submode; 88 uint8_t altOp; 89 uint8_t defOp; 90 uint8_t altAddr; 91 uint8_t defAddr; 92 uint8_t stack; 93 94 uint8_t getNextByte() 95 { 96 return ((uint8_t *)&fetchChunk)[offset]; 97 } 98 99 void getImmediate(int &collected, uint64_t ¤t, int size) 100 { 101 //Figure out how many bytes we still need to get for the 102 //immediate. 103 int toGet = size - collected; 104 //Figure out how many bytes are left in our "buffer" 105 int remaining = sizeof(MachInst) - offset; 106 //Get as much as we need, up to the amount available. 107 toGet = toGet > remaining ? remaining : toGet; 108 109 //Shift the bytes we want to be all the way to the right 110 uint64_t partialImm = fetchChunk >> (offset * 8); 111 //Mask off what we don't want 112 partialImm &= mask(toGet * 8); 113 //Shift it over to overlay with our displacement. 114 partialImm <<= (immediateCollected * 8); 115 //Put it into our displacement 116 current |= partialImm; 117 //Update how many bytes we've collected. 118 collected += toGet; 119 consumeBytes(toGet); 120 } 121 122 void updateOffsetState() 123 { 124 assert(offset <= sizeof(MachInst)); 125 if (offset == sizeof(MachInst)) { 126 DPRINTF(Decoder, "At the end of a chunk, idx = %d, chunks = %d.\n", 127 chunkIdx, instBytes->chunks.size()); 128 chunkIdx++; 129 if (chunkIdx == instBytes->chunks.size()) { 130 outOfBytes = true; 131 } else { 132 offset = 0; 133 fetchChunk = instBytes->chunks[chunkIdx]; 134 basePC += sizeof(MachInst); 135 } 136 } 137 } 138 139 void consumeByte() 140 { 141 offset++; 142 updateOffsetState(); 143 } 144 145 void consumeBytes(int numBytes) 146 { 147 offset += numBytes; 148 updateOffsetState(); 149 } 150 151 //State machine state 152 protected: 153 //Whether or not we're out of bytes 154 bool outOfBytes; 155 //Whether we've completed generating an ExtMachInst 156 bool instDone; 157 //The size of the displacement value 158 int displacementSize; 159 //The size of the immediate value 160 int immediateSize; 161 //This is how much of any immediate value we've gotten. This is used 162 //for both the actual immediate and the displacement. 163 int immediateCollected; 164 165 enum State { 166 ResetState, 167 FromCacheState, 168 PrefixState, 169 OpcodeState, 170 ModRMState, 171 SIBState, 172 DisplacementState, 173 ImmediateState, 174 //We should never get to this state. Getting here is an error. 175 ErrorState 176 }; 177 178 State state; 179 180 //Functions to handle each of the states 181 State doResetState(); 182 State doFromCacheState(); 183 State doPrefixState(uint8_t); 184 State doOpcodeState(uint8_t); 185 State doModRMState(uint8_t); 186 State doSIBState(uint8_t); 187 State doDisplacementState(); 188 State doImmediateState(); 189 190 protected: 191 /// Caching for decoded instruction objects. 192 193 typedef MiscReg CacheKey; 194 195 typedef DecodeCache::AddrMap<Decoder::InstBytes> DecodePages; 196 DecodePages *decodePages; 197 typedef m5::hash_map<CacheKey, DecodePages *> AddrCacheMap; 198 AddrCacheMap addrCacheMap; 199 200 DecodeCache::InstMap *instMap; 201 typedef m5::hash_map<CacheKey, DecodeCache::InstMap *> InstCacheMap; 202 static InstCacheMap instCacheMap; 203 204 public: 205 Decoder() : basePC(0), origPC(0), offset(0), 206 outOfBytes(true), instDone(false), 207 state(ResetState) 208 { 209 memset(&emi, 0, sizeof(emi)); 210 mode = LongMode; 211 submode = SixtyFourBitMode; 212 emi.mode.mode = mode; 213 emi.mode.submode = submode; 214 altOp = 0; 215 defOp = 0; 216 altAddr = 0; 217 defAddr = 0; 218 stack = 0; 219 instBytes = &dummy; 220 decodePages = NULL; 221 instMap = NULL; 222 } 223 224 void setM5Reg(HandyM5Reg m5Reg) 225 { 226 mode = (X86Mode)(uint64_t)m5Reg.mode; 227 submode = (X86SubMode)(uint64_t)m5Reg.submode; 228 emi.mode.mode = mode; 229 emi.mode.submode = submode; 230 altOp = m5Reg.altOp; 231 defOp = m5Reg.defOp; 232 altAddr = m5Reg.altAddr; 233 defAddr = m5Reg.defAddr; 234 stack = m5Reg.stack; 235 236 AddrCacheMap::iterator amIter = addrCacheMap.find(m5Reg); 237 if (amIter != addrCacheMap.end()) { 238 decodePages = amIter->second; 239 } else { 240 decodePages = new DecodePages; 241 addrCacheMap[m5Reg] = decodePages; 242 } 243 244 InstCacheMap::iterator imIter = instCacheMap.find(m5Reg); 245 if (imIter != instCacheMap.end()) { 246 instMap = imIter->second; 247 } else { 248 instMap = new DecodeCache::InstMap; 249 instCacheMap[m5Reg] = instMap; 250 } 251 } 252
|
253 void reset() 254 { 255 state = ResetState; 256 } 257 258 void process(); 259 260 //Use this to give data to the decoder. This should be used 261 //when there is control flow. 262 void moreBytes(const PCState &pc, Addr fetchPC, MachInst data) 263 { 264 DPRINTF(Decoder, "Getting more bytes.\n"); 265 basePC = fetchPC; 266 offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; 267 fetchChunk = data; 268 outOfBytes = false; 269 process(); 270 } 271 272 bool needMoreBytes() 273 { 274 return outOfBytes; 275 } 276 277 bool instReady() 278 { 279 return instDone; 280 } 281 282 void 283 updateNPC(X86ISA::PCState &nextPC) 284 { 285 if (!nextPC.size()) { 286 int size = basePC + offset - origPC; 287 DPRINTF(Decoder, 288 "Calculating the instruction size: " 289 "basePC: %#x offset: %#x origPC: %#x size: %d\n", 290 basePC, offset, origPC, size); 291 nextPC.size(size); 292 nextPC.npc(nextPC.pc() + size); 293 } 294 } 295 296 public: 297 StaticInstPtr decodeInst(ExtMachInst mach_inst); 298 299 /// Decode a machine instruction. 300 /// @param mach_inst The binary instruction to decode. 301 /// @retval A pointer to the corresponding StaticInst object. 302 StaticInstPtr decode(ExtMachInst mach_inst, Addr addr); 303 StaticInstPtr decode(X86ISA::PCState &nextPC); 304}; 305 306} // namespace X86ISA 307 308#endif // __ARCH_X86_DECODER_HH__
| 266 void reset() 267 { 268 state = ResetState; 269 } 270 271 void process(); 272 273 //Use this to give data to the decoder. This should be used 274 //when there is control flow. 275 void moreBytes(const PCState &pc, Addr fetchPC, MachInst data) 276 { 277 DPRINTF(Decoder, "Getting more bytes.\n"); 278 basePC = fetchPC; 279 offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; 280 fetchChunk = data; 281 outOfBytes = false; 282 process(); 283 } 284 285 bool needMoreBytes() 286 { 287 return outOfBytes; 288 } 289 290 bool instReady() 291 { 292 return instDone; 293 } 294 295 void 296 updateNPC(X86ISA::PCState &nextPC) 297 { 298 if (!nextPC.size()) { 299 int size = basePC + offset - origPC; 300 DPRINTF(Decoder, 301 "Calculating the instruction size: " 302 "basePC: %#x offset: %#x origPC: %#x size: %d\n", 303 basePC, offset, origPC, size); 304 nextPC.size(size); 305 nextPC.npc(nextPC.pc() + size); 306 } 307 } 308 309 public: 310 StaticInstPtr decodeInst(ExtMachInst mach_inst); 311 312 /// Decode a machine instruction. 313 /// @param mach_inst The binary instruction to decode. 314 /// @retval A pointer to the corresponding StaticInst object. 315 StaticInstPtr decode(ExtMachInst mach_inst, Addr addr); 316 StaticInstPtr decode(X86ISA::PCState &nextPC); 317}; 318 319} // namespace X86ISA 320 321#endif // __ARCH_X86_DECODER_HH__
|