diff --git a/include/fxos/lang.h b/include/fxos/lang.h index c1e5964..6807b61 100644 --- a/include/fxos/lang.h +++ b/include/fxos/lang.h @@ -159,6 +159,14 @@ struct AsmInstruction IsDynamicJump = 0x40, }; +#define GENDEFS_INSN(NAME, STR) SH_##NAME, + enum { +#include "gendefs/insn.h" + SH_MAX, + }; +#undef GENDEFS_INSN + static_assert(SH_MAX <= 0xff); + AsmInstruction() = default; /* Construct with one or several arguments */ @@ -177,7 +185,7 @@ struct AsmInstruction u16 tags; /* Mnemonic **without the size indicator** */ - char mnemonic[12]; + char const *mnemonic() const; /* Arguments (up to 2) */ AsmArgument args[2]; @@ -235,6 +243,10 @@ struct AsmInstruction /* Get the PC-relative target, assuming the instruction is at the provided address, for instructions with PC-relative offsets. */ u32 getPCRelativeTarget(u32 pc) const; + +private: + /* Assembler instruction name (mov, add, etc), without size modifier. */ + u8 m_opcode; }; } /* namespace FxOS */ diff --git a/lib/disassembly.cpp b/lib/disassembly.cpp index f6912ee..8c561c6 100644 --- a/lib/disassembly.cpp +++ b/lib/disassembly.cpp @@ -23,7 +23,7 @@ void register_instruction(AsmInstruction const &ins) if(insmap[encoding]) FxOS_log(ERR, "encoding collision between a %s and a %s at %04x", - insmap[encoding]->mnemonic, ins.mnemonic, encoding); + insmap[encoding]->mnemonic(), ins.mnemonic(), encoding); else insmap[encoding] = ins; } diff --git a/lib/lang.cpp b/lib/lang.cpp index 33a6ebc..abaad9a 100644 --- a/lib/lang.cpp +++ b/lib/lang.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace FxOS { @@ -195,6 +196,12 @@ u32 AsmArgument::getPCRelativeTarget(u32 pc, int size) const // Instruction management //--- +static char const *instructionMnemonics[] = { +#define GENDEFS_INSN(NAME, STR) [AsmInstruction::SH_##NAME] = STR, +#include "gendefs/insn.h" +#undef GENDEFS_INSN +}; + AsmInstruction::AsmInstruction(char const *mn): encoding {0}, opsize {0}, arg_count {0} { @@ -214,9 +221,15 @@ AsmInstruction::AsmInstruction(char const *mn): len -= 2; } - len = std::min(len, 11); - strncpy(mnemonic, mn, len); - mnemonic[len] = 0; + int i; + for(i = 0; i < SH_MAX; i++) { + if(!strncmp(mn, instructionMnemonics[i], len) + && !instructionMnemonics[i][len]) { + m_opcode = i; + break; + } + } + assert(i < SH_MAX && "AsmInstruction with unknown opcode string"); } AsmInstruction::AsmInstruction(char const *mn, AsmArgument arg): @@ -235,6 +248,12 @@ AsmInstruction::AsmInstruction( arg_count = 2; } +char const *AsmInstruction::mnemonic() const +{ + assert(m_opcode < SH_MAX); + return instructionMnemonics[m_opcode]; +} + u32 AsmInstruction::getPCRelativeTarget(u32 pc) const { for(int i = 0; i < this->arg_count; i++) { diff --git a/lib/view/assembly.cpp b/lib/view/assembly.cpp index d8935c5..0d92a96 100644 --- a/lib/view/assembly.cpp +++ b/lib/view/assembly.cpp @@ -152,9 +152,10 @@ static void doOldInst(u32 pc, OldInstruction &i, static char const *suffixes[5] = {"", ".b", ".w", "", ".l"}; char const *suffix = suffixes[(i.inst->opsize <= 4) ? i.inst->opsize : 0]; - int spacing - = i.inst->arg_count ? 8 - strlen(i.inst->mnemonic) - strlen(suffix) : 0; - printf(" %s%s%*s", i.inst->mnemonic, suffix, spacing, ""); + int spacing = i.inst->arg_count + ? 8 - strlen(i.inst->mnemonic()) - strlen(suffix) + : 0; + printf(" %s%s%*s", i.inst->mnemonic(), suffix, spacing, ""); /* Arguments */ for(size_t n = 0; n < i.inst->arg_count; n++) { @@ -246,9 +247,9 @@ void viewAssemblyInstruction(Instruction const &ins, ViewAssemblyOptions *opts) char const *suffix = suffixes[(opcode.opsize <= 4) ? opcode.opsize : 0]; int spacing - = opcode.arg_count ? 8 - strlen(opcode.mnemonic) - strlen(suffix) : 0; + = opcode.arg_count ? 8 - strlen(opcode.mnemonic()) - strlen(suffix) : 0; std::string str = " "; - str += opcode.mnemonic; + str += opcode.mnemonic(); str += suffix; str += std::string(spacing, ' ');