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:
parent
f4e550e004
commit
3f200a7638
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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; \
|
||||||
|
@ -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";
|
||||||
|
Loading…
Reference in New Issue
Block a user