diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-03-15 19:16:36 +0000 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-03-15 19:16:36 +0000 |
commit | 05c71c6194bcd94e0e51634970ed9ceda37a47ad (patch) | |
tree | 44a3f580de538b34ef00da2c830e51b45ba26bba /src/arch | |
parent | c6e1dc61c23dc1f5300610ce8348f9a0e9c128cc (diff) | |
parent | 6cdd434f7f94afc81aa09c411c00969cd80cc833 (diff) | |
download | gem5-05c71c6194bcd94e0e51634970ed9ceda37a47ad.tar.xz |
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86
--HG--
extra : convert_revision : cf2cc07f18b877f980e2d1fc83916f7849d9c7d9
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/predecoder.hh | 124 | ||||
-rw-r--r-- | src/arch/x86/predecoder_tables.cc | 79 | ||||
-rw-r--r-- | src/arch/x86/types.hh | 6 |
3 files changed, 148 insertions, 61 deletions
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index 371ce9db9..f1dee6bf4 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -61,6 +61,7 @@ #include "arch/x86/types.hh" #include "base/bitfield.hh" #include "base/misc.hh" +#include "base/trace.hh" #include "sim/host.hh" class ThreadContext; @@ -70,8 +71,11 @@ 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; @@ -133,7 +137,6 @@ namespace X86ISA void process() { - warn("About to process some bytes\n"); assert(!outOfBytes); assert(!emiIsReady); while(!emiIsReady && !outOfBytes) @@ -143,60 +146,51 @@ namespace X86ISA { case Prefix: uint8_t prefix = Prefixes[nextByte]; + if(prefix) + offset++; switch(prefix) { //Operand size override prefixes case OperandSizeOverride: - warn("Found operand size override prefix!\n"); - offset++; + DPRINTF(Predecoder, "Found operand size override prefix.\n"); break; case AddressSizeOverride: - warn("Found address size override prefix!\n"); - offset++; + DPRINTF(Predecoder, "Found address size override prefix.\n"); break; //Segment override prefixes case CSOverride: - warn("Found cs segment override!\n"); - offset++; + DPRINTF(Predecoder, "Found cs segment override.\n"); break; case DSOverride: - warn("Found ds segment override!\n"); - offset++; + DPRINTF(Predecoder, "Found ds segment override.\n"); break; case ESOverride: - warn("Found es segment override!\n"); - offset++; + DPRINTF(Predecoder, "Found es segment override.\n"); break; case FSOverride: - warn("Found fs segment override!\n"); - offset++; + DPRINTF(Predecoder, "Found fs segment override.\n"); break; case GSOverride: - warn("Found gs segment override!\n"); - offset++; + DPRINTF(Predecoder, "Found gs segment override.\n"); break; case SSOverride: - warn("Found ss segment override!\n"); - offset++; + DPRINTF(Predecoder, "Found ss segment override.\n"); break; case Lock: - warn("Found lock prefix!\n"); - offset++; + DPRINTF(Predecoder, "Found lock prefix.\n"); break; case Rep: - warn("Found rep prefix!\n"); - offset++; + DPRINTF(Predecoder, "Found rep prefix.\n"); break; case Repne: - warn("Found repne prefix!\n"); - offset++; + DPRINTF(Predecoder, "Found repne prefix.\n"); break; case Rex: - warn("Found Rex prefix %#x!\n", nextByte); - offset++; + DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte); + emi.rexPrefix = nextByte; break; case 0: - emi.twoByteOpcode = false; + emi.numOpcodes = 0; state = Opcode; break; default: @@ -204,20 +198,30 @@ namespace X86ISA } break; case Opcode: + emi.numOpcodes++; + assert(emi.numOpcodes < 2); if(nextByte == 0xf0) { - warn("Found two byte opcode!\n"); - emi.twoByteOpcode = true; + DPRINTF(Predecoder, "Found two byte opcode.\n"); } else { - warn("Found opcode %#x!\n", nextByte); - if (UsesModRM[emi.twoByteOpcode ? 1 : 0][nextByte]) { + immediateCollected = 0; + displacementCollected = 0; + emi.immediate = 0; + emi.displacement = 0; + 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]; + DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte); + if (UsesModRM[emi.numOpcodes - 1][nextByte]) { state = ModRM; - } else if(0 /* uses immediate */) { - //Figure out how big the immediate should be - immediateCollected = 0; - emi.immediate = 0; + } else if(immediateSize) { state = Immediate; } else { emiIsReady = true; @@ -227,25 +231,25 @@ namespace X86ISA offset++; break; case ModRM: - warn("Found modrm byte %#x!\n", nextByte); + DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte); if (0) {//in 16 bit mode //figure out 16 bit displacement size if(nextByte & 0xC7 == 0x06 || - nextByte & 0xC0 == 0x40) - displacementSize = 1; - else if(nextByte & 0xC7 == 0x80) + 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 == 0x06 || - nextByte & 0xC0 == 0x40) + if(nextByte & 0xC7 == 0x05 || + nextByte & 0xC0 == 0x80) displacementSize = 4; - else if(nextByte & 0xC7 == 0x80) + else if(nextByte & 0xC0 == 0x40) displacementSize = 2; else - displacementSize = 4; + displacementSize = 0; } //If there's an SIB, get that next. //There is no SIB in 16 bit mode. @@ -254,12 +258,8 @@ namespace X86ISA // && in 32/64 bit mode) state = SIB; } else if(displacementSize) { - displacementCollected = 0; - emi.displacement = 0; state = Displacement; } else if(immediateSize) { - immediateCollected = 0; - emi.immediate = 0; state = Immediate; } else { emiIsReady = true; @@ -269,15 +269,11 @@ namespace X86ISA offset++; break; case SIB: - warn("Found SIB byte %#x!\n", nextByte); + DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte); offset++; if(displacementSize) { - displacementCollected = 0; - emi.displacement = 0; state = Displacement; } else if(immediateSize) { - immediateCollected = 0; - emi.immediate = 0; state = Immediate; } else { emiIsReady = true; @@ -297,15 +293,18 @@ namespace X86ISA toGet = toGet > remaining ? remaining : toGet; //Shift the bytes we want to be all the way to the right - partialDisp = fetchChunk >> offset; + 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; + partialDisp <<= (displacementCollected * 8); //Put it into our displacement emi.displacement |= partialDisp; //Update how many bytes we've collected. displacementCollected += toGet; + offset += toGet; + DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n", + displacementSize, displacementCollected); if(displacementSize == displacementCollected) { //Sign extend the displacement @@ -323,9 +322,9 @@ namespace X86ISA default: panic("Undefined displacement size!\n"); } + DPRINTF(Predecoder, "Collected displacement %#x.\n", + emi.displacement); if(immediateSize) { - immediateCollected = 0; - emi.immediate = 0; state = Immediate; } else { emiIsReady = true; @@ -346,17 +345,23 @@ namespace X86ISA toGet = toGet > remaining ? remaining : toGet; //Shift the bytes we want to be all the way to the right - partialDisp = fetchChunk >> offset; + partialDisp = fetchChunk >> (offset * 8); //Mask off what we don't want partialDisp &= mask(toGet * 8); //Shift it over to overlay with our immediate. - partialDisp <<= displacementCollected; + partialDisp <<= (immediateCollected * 8); //Put it into our immediate - emi.displacement |= partialDisp; + emi.immediate |= partialDisp; //Update how many bytes we've collected. - displacementCollected += toGet; + immediateCollected += toGet; + offset += toGet; + 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; state = Prefix; } @@ -378,7 +383,6 @@ namespace X86ISA fetchChunk = data; assert(off < sizeof(MachInst)); outOfBytes = false; - warn("About to call process.\n"); process(); } diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc index 9304eee47..0cebef61a 100644 --- a/src/arch/x86/predecoder_tables.cc +++ b/src/arch/x86/predecoder_tables.cc @@ -140,4 +140,83 @@ namespace X86ISA /* 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 68d95de94..583f03d55 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -94,7 +94,11 @@ namespace X86ISA uint8_t legacyPrefixes; uint8_t rexPrefix; - bool twoByteOpcode; + //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; |