diff options
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/SConscript | 3 | ||||
-rw-r--r-- | src/arch/x86/isa/formats/unknown.isa | 3 | ||||
-rw-r--r-- | src/arch/x86/predecoder.cc | 345 | ||||
-rw-r--r-- | src/arch/x86/predecoder.hh | 225 | ||||
-rw-r--r-- | src/arch/x86/predecoder_tables.cc | 222 | ||||
-rw-r--r-- | src/arch/x86/types.hh | 75 | ||||
-rw-r--r-- | src/arch/x86/utility.hh | 17 |
7 files changed, 879 insertions, 11 deletions
diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index f49225758..2e2c5b006 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -84,11 +84,12 @@ # Authors: Gabe Black Import('*') - if env['TARGET_ISA'] == 'x86': Source('floatregfile.cc') Source('intregfile.cc') Source('miscregfile.cc') + Source('predecoder.cc') + Source('predecoder_tables.cc') Source('regfile.cc') Source('remote_gdb.cc') diff --git a/src/arch/x86/isa/formats/unknown.isa b/src/arch/x86/isa/formats/unknown.isa index 605ddcb69..43ddc20c1 100644 --- a/src/arch/x86/isa/formats/unknown.isa +++ b/src/arch/x86/isa/formats/unknown.isa @@ -120,7 +120,8 @@ output exec {{ Fault Unknown::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - panic("No instructions are implemented for X86!\n"); + warn("No instructions are implemented for X86!\n"); + return NoFault; } }}; diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc new file mode 100644 index 000000000..5ea960b36 --- /dev/null +++ b/src/arch/x86/predecoder.cc @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/predecoder.hh" +#include "base/misc.hh" +#include "base/trace.hh" +#include "sim/host.hh" + +namespace X86ISA +{ + void Predecoder::process() + { + //This function drives the predecoder state machine. + + //Some sanity checks. You shouldn't try to process more bytes if + //there aren't any, and you shouldn't overwrite an already + //predecoder ExtMachInst. + assert(!outOfBytes); + assert(!emiIsReady); + + //While there's still something to do... + while(!emiIsReady && !outOfBytes) + { + uint8_t nextByte = getNextByte(); + switch(state) + { + case Prefix: + state = doPrefixState(nextByte); + break; + case Opcode: + state = doOpcodeState(nextByte); + break; + case ModRM: + state = doModRMState(nextByte); + break; + case SIB: + state = doSIBState(nextByte); + break; + case Displacement: + state = doDisplacementState(); + break; + case Immediate: + state = doImmediateState(); + break; + case ErrorState: + panic("Went to the error state in the predecoder.\n"); + default: + panic("Unrecognized state! %d\n", state); + } + } + } + + //Either get a prefix and record it in the ExtMachInst, or send the + //state machine on to get the opcode(s). + Predecoder::State Predecoder::doPrefixState(uint8_t nextByte) + { + uint8_t prefix = Prefixes[nextByte]; + State nextState = Prefix; + if(prefix) + consumeByte(); + switch(prefix) + { + //Operand size override prefixes + case OperandSizeOverride: + DPRINTF(Predecoder, "Found operand size override prefix.\n"); + break; + case AddressSizeOverride: + DPRINTF(Predecoder, "Found address size override prefix.\n"); + break; + //Segment override prefixes + case CSOverride: + DPRINTF(Predecoder, "Found cs segment override.\n"); + break; + case DSOverride: + DPRINTF(Predecoder, "Found ds segment override.\n"); + break; + case ESOverride: + DPRINTF(Predecoder, "Found es segment override.\n"); + break; + case FSOverride: + DPRINTF(Predecoder, "Found fs segment override.\n"); + break; + case GSOverride: + DPRINTF(Predecoder, "Found gs segment override.\n"); + break; + case SSOverride: + DPRINTF(Predecoder, "Found ss segment override.\n"); + break; + case Lock: + DPRINTF(Predecoder, "Found lock prefix.\n"); + break; + case Rep: + DPRINTF(Predecoder, "Found rep prefix.\n"); + break; + case Repne: + DPRINTF(Predecoder, "Found repne prefix.\n"); + break; + case Rex: + DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte); + emi.rexPrefix = nextByte; + break; + case 0: + emi.numOpcodes = 0; + nextState = Opcode; + break; + default: + panic("Unrecognized prefix %#x\n", nextByte); + } + return nextState; + } + + //Load all the opcodes (currently up to 2) and then figure out + //what immediate and/or ModRM is needed. + Predecoder::State Predecoder::doOpcodeState(uint8_t nextByte) + { + State nextState = ErrorState; + emi.numOpcodes++; + //We can't handle 3+ byte opcodes right now + assert(emi.numOpcodes < 2); + consumeByte(); + if(nextByte == 0xf0) + { + nextState = Opcode; + DPRINTF(Predecoder, "Found two byte opcode.\n"); + } + else + { + DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte); + + //Prepare for any immediate/displacement we might need + immediateCollected = 0; + emi.immediate = 0; + displacementCollected = 0; + emi.displacement = 0; + + //Figure out how big of an immediate we'll retreive based + //on the opcode. + int immType = ImmediateType[ + emi.numOpcodes - 1][nextByte]; + if(0) //16 bit mode + immediateSize = ImmediateTypeToSize[0][immType]; + else if(!(emi.rexPrefix & 0x4)) //32 bit mode + immediateSize = ImmediateTypeToSize[1][immType]; + else //64 bit mode + immediateSize = ImmediateTypeToSize[2][immType]; + + //Determine what to expect next + if (UsesModRM[emi.numOpcodes - 1][nextByte]) { + nextState = ModRM; + } else if(immediateSize) { + nextState = Immediate; + } else { + emiIsReady = true; + nextState = Prefix; + } + } + return nextState; + } + + //Get the ModRM byte and determine what displacement, if any, there is. + //Also determine whether or not to get the SIB byte, displacement, or + //immediate next. + Predecoder::State Predecoder::doModRMState(uint8_t nextByte) + { + State nextState = ErrorState; + DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte); + if (0) {//FIXME in 16 bit mode + //figure out 16 bit displacement size + if(nextByte & 0xC7 == 0x06 || + nextByte & 0xC0 == 0x80) + displacementSize = 2; + else if(nextByte & 0xC0 == 0x40) + displacementSize = 1; + else + displacementSize = 0; + } else { + //figure out 32/64 bit displacement size + if(nextByte & 0xC7 == 0x05 || + nextByte & 0xC0 == 0x80) + displacementSize = 4; + else if(nextByte & 0xC0 == 0x40) + displacementSize = 2; + else + displacementSize = 0; + } + //If there's an SIB, get that next. + //There is no SIB in 16 bit mode. + if(nextByte & 0x7 == 4 && + nextByte & 0xC0 != 0xC0) { + // && in 32/64 bit mode) + nextState = SIB; + } else if(displacementSize) { + nextState = Displacement; + } else if(immediateSize) { + nextState = Immediate; + } else { + emiIsReady = true; + nextState = Prefix; + } + //The ModRM byte is consumed no matter what + consumeByte(); + return nextState; + } + + //Get the SIB byte. We don't do anything with it at this point, other + //than storing it in the ExtMachInst. Determine if we need to get a + //displacement or immediate next. + Predecoder::State Predecoder::doSIBState(uint8_t nextByte) + { + State nextState = ErrorState; + DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte); + consumeByte(); + if(displacementSize) { + nextState = Displacement; + } else if(immediateSize) { + nextState = Immediate; + } else { + emiIsReady = true; + nextState = Prefix; + } + return nextState; + } + + //Gather up the displacement, or at least as much of it + //as we can get. + Predecoder::State Predecoder::doDisplacementState() + { + State nextState = ErrorState; + + getImmediate(displacementCollected, + emi.displacement, + displacementSize); + + DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n", + displacementSize, displacementCollected); + + if(displacementSize == displacementCollected) { + //Sign extend the displacement + switch(displacementSize) + { + case 1: + emi.displacement = sext<8>(emi.displacement); + break; + case 2: + emi.displacement = sext<16>(emi.displacement); + break; + case 4: + emi.displacement = sext<32>(emi.displacement); + break; + default: + panic("Undefined displacement size!\n"); + } + DPRINTF(Predecoder, "Collected displacement %#x.\n", + emi.displacement); + if(immediateSize) { + nextState = Immediate; + } else { + emiIsReady = true; + nextState = Prefix; + } + } + else + nextState = Displacement; + return nextState; + } + + //Gather up the immediate, or at least as much of it + //as we can get + Predecoder::State Predecoder::doImmediateState() + { + State nextState = ErrorState; + + getImmediate(immediateCollected, + emi.immediate, + immediateSize); + + DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n", + immediateSize, immediateCollected); + + if(immediateSize == immediateCollected) + { + DPRINTF(Predecoder, "Collected immediate %#x.\n", + emi.immediate); + emiIsReady = true; + nextState = Prefix; + } + else + nextState = Immediate; + return nextState; + } +} diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh new file mode 100644 index 000000000..d7734be88 --- /dev/null +++ b/src/arch/x86/predecoder.hh @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_PREDECODER_HH__ +#define __ARCH_X86_PREDECODER_HH__ + +#include "arch/x86/types.hh" +#include "base/bitfield.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace X86ISA +{ + class Predecoder + { + private: + //These are defined and documented in predecoder_tables.cc + static const uint8_t Prefixes[256]; + static const uint8_t UsesModRM[2][256]; + static const uint8_t ImmediateType[2][256]; + static const uint8_t ImmediateTypeToSize[3][10]; + + protected: + ThreadContext * tc; + //The bytes to be predecoded + MachInst fetchChunk; + //The pc of the start of fetchChunk + Addr basePC; + //The offset into fetchChunk of current processing + int offset; + //The extended machine instruction being generated + ExtMachInst emi; + + inline uint8_t getNextByte() + { + return (fetchChunk >> (offset * 8)) & 0xff; + } + + void getImmediate(int &collected, uint64_t ¤t, int size) + { + //Figure out how many bytes we still need to get for the + //immediate. + int toGet = size - collected; + //Figure out how many bytes are left in our "buffer" + int remaining = sizeof(MachInst) - offset; + //Get as much as we need, up to the amount available. + toGet = toGet > remaining ? remaining : toGet; + + //Shift the bytes we want to be all the way to the right + uint64_t partialDisp = fetchChunk >> (offset * 8); + //Mask off what we don't want + partialDisp &= mask(toGet * 8); + //Shift it over to overlay with our displacement. + partialDisp <<= (displacementCollected * 8); + //Put it into our displacement + current |= partialDisp; + //Update how many bytes we've collected. + collected += toGet; + consumeBytes(toGet); + } + + inline void consumeByte() + { + offset++; + assert(offset <= sizeof(MachInst)); + if(offset == sizeof(MachInst)) + outOfBytes = true; + } + + inline void consumeBytes(int numBytes) + { + offset += numBytes; + assert(offset <= sizeof(MachInst)); + if(offset == sizeof(MachInst)) + outOfBytes = true; + } + + //State machine state + protected: + //Whether or not we're out of bytes + bool outOfBytes; + //Whether we've completed generating an ExtMachInst + bool emiIsReady; + //The size of the displacement value + int displacementSize; + int displacementCollected; + //The size of the immediate value + int immediateSize; + int immediateCollected; + + enum State { + Prefix, + Opcode, + ModRM, + SIB, + Displacement, + Immediate, + //We should never get to this state. Getting here is an error. + ErrorState + }; + + State state; + + //Functions to handle each of the states + State doPrefixState(uint8_t); + State doOpcodeState(uint8_t); + State doModRMState(uint8_t); + State doSIBState(uint8_t); + State doDisplacementState(); + State doImmediateState(); + + public: + Predecoder(ThreadContext * _tc) : + tc(_tc), basePC(0), offset(0), + outOfBytes(true), emiIsReady(false), + state(Prefix) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process(); + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst data) + { + basePC = currPC; + offset = off; + fetchChunk = data; + assert(off < sizeof(MachInst)); + outOfBytes = false; + process(); + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(basePC + sizeof(machInst), 0, machInst); + } + + bool needMoreBytes() + { + return outOfBytes; + } + + bool extMachInstReady() + { + return emiIsReady; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + assert(emiIsReady); + emiIsReady = false; + return emi; + } + }; +}; + +#endif // __ARCH_X86_PREDECODER_HH__ diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc new file mode 100644 index 000000000..0cebef61a --- /dev/null +++ b/src/arch/x86/predecoder_tables.cc @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/predecoder.hh" +#include "arch/x86/types.hh" + +namespace X86ISA +{ + const uint8_t CS = CSOverride; + const uint8_t DS = DSOverride; + const uint8_t ES = ESOverride; + const uint8_t FS = FSOverride; + const uint8_t GS = GSOverride; + const uint8_t SS = SSOverride; + + const uint8_t OO = OperandSizeOverride; + const uint8_t AO = AddressSizeOverride; + const uint8_t LO = Lock; + const uint8_t RE = Rep; + const uint8_t RN = Repne; + const uint8_t RX = Rex; + + //This table identifies whether a byte is a prefix, and if it is, + //which prefix it is. + const uint8_t Predecoder::Prefixes[256] = + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 1*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 2*/ 0 , 0 , 0 , 0 , 0 , 0 , ES, 0 , 0 , 0 , 0 , 0 , 0 , 0 , CS, 0, +/* 3*/ 0 , 0 , 0 , 0 , 0 , 0 , SS, 0 , 0 , 0 , 0 , 0 , 0 , 0 , DS, 0, +/* 4*/ RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, +/* 5*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 6*/ 0 , 0 , 0 , 0 , FS, GS, OO, AO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 7*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 8*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 9*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* A*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* B*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* C*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* E*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* F*/ LO, 0 , RN, RE, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + }; + + //This table identifies whether a particular opcode uses the ModRM byte + const uint8_t Predecoder::UsesModRM[2][256] = + {//For one byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 1 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 2 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 3 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 6 */ 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0, +/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 8 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* C */ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 + }, + //For two byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1, +/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 5 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 6 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 7 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1, +/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 9 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* A */ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1, +/* B */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1, +/* C */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* E */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 + } + }; + + enum ImmediateTypes { + NoImm, + NI = NoImm, + ByteImm, + BY = ByteImm, + WordImm, + WO = WordImm, + DWordImm, + DW = DWordImm, + QWordImm, + QW = QWordImm, + OWordImm, + OW = OWordImm, + VWordImm, + VW = VWordImm, + ZWordImm, + ZW = ZWordImm, + Pointer, + PO = Pointer, + //The enter instruction takes -2- immediates for a total of 3 bytes + Enter, + EN = Enter + }; + + const uint8_t Predecoder::ImmediateTypeToSize[3][10] = + { +// noimm byte word dword qword oword vword zword enter + {0, 1, 2, 4, 8, 16, 2, 2, 3, 4}, //16 bit + {0, 1, 2, 4, 8, 16, 4, 4, 3, 6}, //32 bit + {0, 1, 2, 4, 8, 16, 4, 8, 3, 0} //64 bit + }; + + //This table determines the immediate type. The first index is the + //number of bytes in the instruction, and the second is the meaningful + //byte of the opcode. I didn't use the NI constant here for the sake + //of clarity. + const uint8_t Predecoder::ImmediateType[2][256] = + {//For one byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 1 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 2 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 3 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, ZW, BY, BY, 0 , 0 , 0 , 0 , +/* 7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, +/* 8 */ BY, ZW, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* A */ BY, VW, BY, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , +/* B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW, +/* C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 , +/* D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* E */ BY, BY, BY, BY, BY, BY, BY, BY, ZW, ZW, PO, BY, 0 , 0 , 0 , 0 , +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + }, + //For two byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 7 */ BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 8 */ ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* A */ 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , +/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, 0 , BY, 0 , 0 , 0 , 0 , 0 , +/* C */ 0 , 0 , BY, 0 , BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + } + }; +} diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 63f65eee5..583f03d55 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -59,13 +59,80 @@ #define __ARCH_X86_TYPES_HH__ #include <inttypes.h> +#include <iostream> namespace X86ISA { - //XXX This won't work - typedef uint32_t MachInst; - //XXX This won't work either - typedef uint64_t ExtMachInst; + //This really determines how many bytes are passed to the predecoder. + typedef uint64_t MachInst; + + enum Prefixes { + NoOverride = 0, + CSOverride = 1, + DSOverride = 2, + ESOverride = 3, + FSOverride = 4, + GSOverride = 5, + SSOverride = 6, + //The Rex prefix obviously doesn't fit in with the above, but putting + //it here lets us save double the space the enums take up. + Rex = 7, + //There can be only one segment override, so they share the + //first 3 bits in the legacyPrefixes bitfield. + SegmentOverride = 0x7, + OperandSizeOverride = 8, + AddressSizeOverride = 16, + Lock = 32, + Rep = 64, + Repne = 128 + }; + + //The intermediate structure the x86 predecoder returns. + struct ExtMachInst + { + public: //XXX These should be hidden in the future + + uint8_t legacyPrefixes; + uint8_t rexPrefix; + //Right now, we ignore that this can be 3 in + //some cases + uint8_t numOpcodes; + //This will need to be decoded specially later + bool is3dnow; + uint8_t opcode; + uint64_t immediate; + uint64_t displacement; + + public: + + //These are to pacify the decoder for now. This will go away once + //it can handle non integer inputs, and in the mean time allow me to + //excercise the predecoder a little. + operator unsigned int() + { + return 0; + } + + ExtMachInst(unsigned int) + {;} + + ExtMachInst() + {;} + }; + + inline static std::ostream & + operator << (std::ostream & os, const ExtMachInst & emi) + { + os << "{X86 ExtMachInst}"; + return os; + } + + inline static bool + operator == (const ExtMachInst &emi1, const ExtMachInst &emi2) + { + //Since this is empty, it's always equal + return true; + } typedef uint64_t IntReg; //XXX Should this be a 128 bit structure for XMM memory ops? diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 1fbe1fffe..d89e223de 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -59,11 +59,23 @@ #define __ARCH_X86_UTILITY_HH__ #include "arch/x86/types.hh" +#include "base/hashmap.hh" #include "base/misc.hh" +#include "cpu/thread_context.hh" #include "sim/host.hh" class ThreadContext; +namespace __hash_namespace { + template<> + struct hash<X86ISA::ExtMachInst> { + size_t operator()(const X86ISA::ExtMachInst &emi) const { + //Because these are all the same, return 0 + return 0; + }; + }; +} + namespace X86ISA { static inline bool @@ -72,11 +84,6 @@ namespace X86ISA return false; } - inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { - return inst; - } - inline bool isCallerSaveIntegerRegister(unsigned int reg) { panic("register classification not implemented"); return false; |