1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

Add more indirection to the disassembler tables to reduce amount of space used to store the operand types and encodings. Store only the unique combinations in a separate table and store indices in the instruction table. Saves about 32K of static data.

llvm-svn: 161101
This commit is contained in:
Craig Topper 2012-08-01 07:39:18 +00:00
parent f4e550e004
commit 3f200a7638
7 changed files with 71 additions and 42 deletions

View File

@ -762,8 +762,7 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
translateRegister(mcInst, insn.vvvv); translateRegister(mcInst, insn.vvvv);
return false; return false;
case ENCODING_DUP: case ENCODING_DUP:
return translateOperand(mcInst, return translateOperand(mcInst, insn.operands[operand.type - TYPE_DUP0],
insn.spec->operands[operand.type - TYPE_DUP0],
insn, Dis); insn, Dis);
} }
} }
@ -789,8 +788,8 @@ static bool translateInstruction(MCInst &mcInst,
insn.numImmediatesTranslated = 0; insn.numImmediatesTranslated = 0;
for (index = 0; index < X86_MAX_OPERANDS; ++index) { for (index = 0; index < X86_MAX_OPERANDS; ++index) {
if (insn.spec->operands[index].encoding != ENCODING_NONE) { if (insn.operands[index].encoding != ENCODING_NONE) {
if (translateOperand(mcInst, insn.spec->operands[index], insn, Dis)) { if (translateOperand(mcInst, insn.operands[index], insn, Dis)) {
return true; return true;
} }
} }

View File

@ -74,7 +74,8 @@
#ifndef X86DISASSEMBLER_H #ifndef X86DISASSEMBLER_H
#define X86DISASSEMBLER_H #define X86DISASSEMBLER_H
#define INSTRUCTION_SPECIFIER_FIELDS #define INSTRUCTION_SPECIFIER_FIELDS \
uint16_t operands;
#define INSTRUCTION_IDS \ #define INSTRUCTION_IDS \
unsigned instructionIDs; unsigned instructionIDs;

View File

@ -1495,14 +1495,14 @@ static int readOperands(struct InternalInstruction* insn) {
needVVVV = hasVVVV && (insn->vvvv != 0); needVVVV = hasVVVV && (insn->vvvv != 0);
for (index = 0; index < X86_MAX_OPERANDS; ++index) { for (index = 0; index < X86_MAX_OPERANDS; ++index) {
switch (insn->spec->operands[index].encoding) { switch (x86OperandSets[insn->spec->operands][index].encoding) {
case ENCODING_NONE: case ENCODING_NONE:
break; break;
case ENCODING_REG: case ENCODING_REG:
case ENCODING_RM: case ENCODING_RM:
if (readModRM(insn)) if (readModRM(insn))
return -1; return -1;
if (fixupReg(insn, &insn->spec->operands[index])) if (fixupReg(insn, &x86OperandSets[insn->spec->operands][index]))
return -1; return -1;
break; break;
case ENCODING_CB: case ENCODING_CB:
@ -1524,14 +1524,14 @@ static int readOperands(struct InternalInstruction* insn) {
} }
if (readImmediate(insn, 1)) if (readImmediate(insn, 1))
return -1; return -1;
if (insn->spec->operands[index].type == TYPE_IMM3 && if (x86OperandSets[insn->spec->operands][index].type == TYPE_IMM3 &&
insn->immediates[insn->numImmediatesConsumed - 1] > 7) insn->immediates[insn->numImmediatesConsumed - 1] > 7)
return -1; return -1;
if (insn->spec->operands[index].type == TYPE_IMM5 && if (x86OperandSets[insn->spec->operands][index].type == TYPE_IMM5 &&
insn->immediates[insn->numImmediatesConsumed - 1] > 31) insn->immediates[insn->numImmediatesConsumed - 1] > 31)
return -1; return -1;
if (insn->spec->operands[index].type == TYPE_XMM128 || if (x86OperandSets[insn->spec->operands][index].type == TYPE_XMM128 ||
insn->spec->operands[index].type == TYPE_XMM256) x86OperandSets[insn->spec->operands][index].type == TYPE_XMM256)
sawRegImm = 1; sawRegImm = 1;
break; break;
case ENCODING_IW: case ENCODING_IW:
@ -1582,7 +1582,7 @@ static int readOperands(struct InternalInstruction* insn) {
needVVVV = 0; /* Mark that we have found a VVVV operand. */ needVVVV = 0; /* Mark that we have found a VVVV operand. */
if (!hasVVVV) if (!hasVVVV)
return -1; return -1;
if (fixupReg(insn, &insn->spec->operands[index])) if (fixupReg(insn, &x86OperandSets[insn->spec->operands][index]))
return -1; return -1;
break; break;
case ENCODING_DUP: case ENCODING_DUP:
@ -1644,6 +1644,8 @@ int decodeInstruction(struct InternalInstruction* insn,
insn->instructionID == 0 || insn->instructionID == 0 ||
readOperands(insn)) readOperands(insn))
return -1; return -1;
insn->operands = &x86OperandSets[insn->spec->operands][0];
insn->length = insn->readerCursor - insn->startLocation; insn->length = insn->readerCursor - insn->startLocation;

View File

@ -20,7 +20,8 @@
extern "C" { extern "C" {
#endif #endif
#define INSTRUCTION_SPECIFIER_FIELDS #define INSTRUCTION_SPECIFIER_FIELDS \
uint16_t operands;
#define INSTRUCTION_IDS \ #define INSTRUCTION_IDS \
unsigned instructionIDs; unsigned instructionIDs;
@ -538,6 +539,8 @@ struct InternalInstruction {
SIBIndex sibIndex; SIBIndex sibIndex;
uint8_t sibScale; uint8_t sibScale;
SIBBase sibBase; SIBBase sibBase;
const struct OperandSpecifier *operands;
}; };
/* decodeInstruction - Decode one instruction and store the decoding results in /* decodeInstruction - Decode one instruction and store the decoding results in

View File

@ -374,7 +374,6 @@ typedef enum {
struct InstructionSpecifier { struct InstructionSpecifier {
uint8_t modifierType; uint8_t modifierType;
uint8_t modifierBase; uint8_t modifierBase;
struct OperandSpecifier operands[X86_MAX_OPERANDS];
/* The macro below must be defined wherever this file is included. */ /* The macro below must be defined wherever this file is included. */
INSTRUCTION_SPECIFIER_FIELDS INSTRUCTION_SPECIFIER_FIELDS

View File

@ -14,6 +14,7 @@
#include <string.h> #include <string.h>
#define INSTRUCTION_SPECIFIER_FIELDS \ #define INSTRUCTION_SPECIFIER_FIELDS \
struct OperandSpecifier operands[X86_MAX_OPERANDS]; \
bool filtered; \ bool filtered; \
InstructionContext insnContext; \ InstructionContext insnContext; \
std::string name; \ std::string name; \

View File

@ -21,6 +21,7 @@
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include <map>
using namespace llvm; using namespace llvm;
using namespace X86Disassembler; using namespace X86Disassembler;
@ -424,48 +425,71 @@ void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
void DisassemblerTables::emitInstructionInfo(raw_ostream &o, void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
unsigned &i) const { unsigned &i) const {
unsigned NumInstructions = InstructionSpecifiers.size();
o << "static const struct OperandSpecifier x86OperandSets[]["
<< X86_MAX_OPERANDS << "] = {\n";
typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
std::map<OperandListTy, unsigned> OperandSets;
unsigned OperandSetNum = 0;
for (unsigned Index = 0; Index < NumInstructions; ++Index) {
OperandListTy OperandList;
for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
++OperandIndex) {
const char *Encoding =
stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
.operands[OperandIndex].encoding);
const char *Type =
stringForOperandType((OperandType)InstructionSpecifiers[Index]
.operands[OperandIndex].type);
OperandList.push_back(std::make_pair(Encoding, Type));
}
unsigned &N = OperandSets[OperandList];
if (N != 0) continue;
N = ++OperandSetNum;
o << " { /* " << (OperandSetNum - 1) << " */\n";
for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
o << " { " << OperandList[i].first << ", "
<< OperandList[i].second << " },\n";
}
o << " },\n";
}
o << "};" << "\n\n";
o.indent(i * 2) << "static const struct InstructionSpecifier "; o.indent(i * 2) << "static const struct InstructionSpecifier ";
o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
i++; i++;
unsigned numInstructions = InstructionSpecifiers.size(); for (unsigned index = 0; index < NumInstructions; ++index) {
for (unsigned index = 0; index < numInstructions; ++index) {
o.indent(i * 2) << "{ /* " << index << " */" << "\n"; o.indent(i * 2) << "{ /* " << index << " */" << "\n";
i++; i++;
o.indent(i * 2) << stringForModifierType( o.indent(i * 2) << stringForModifierType(
(ModifierType)InstructionSpecifiers[index].modifierType); (ModifierType)InstructionSpecifiers[index].modifierType);
o << "," << "\n"; o << ",\n";
o.indent(i * 2) << "0x"; o.indent(i * 2) << "0x";
o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase);
o << "," << "\n"; o << ",\n";
o.indent(i * 2) << "{" << "\n"; OperandListTy OperandList;
i++; for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
++OperandIndex) {
for (unsigned operandIndex = 0; operandIndex < X86_MAX_OPERANDS; const char *Encoding =
++operandIndex) { stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
o.indent(i * 2) << "{ "; .operands[OperandIndex].encoding);
o <<stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] const char *Type =
.operands[operandIndex] stringForOperandType((OperandType)InstructionSpecifiers[index]
.encoding); .operands[OperandIndex].type);
o << ", "; OperandList.push_back(std::make_pair(Encoding, Type));
o << stringForOperandType((OperandType)InstructionSpecifiers[index]
.operands[operandIndex]
.type);
o << " }";
if (operandIndex < X86_MAX_OPERANDS - 1)
o << ",";
o << "\n";
} }
o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
i--;
o.indent(i * 2) << "}," << "\n";
o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
o << "\n"; o << "\n";
@ -473,7 +497,7 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
i--; i--;
o.indent(i * 2) << "}"; o.indent(i * 2) << "}";
if (index + 1 < numInstructions) if (index + 1 < NumInstructions)
o << ","; o << ",";
o << "\n"; o << "\n";