fxos: generate defs from insn table + some renaming

This commit is contained in:
Lephenixnoir 2023-11-14 02:56:06 +01:00
parent c299a5f1b6
commit 74fade0042
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
10 changed files with 100 additions and 14 deletions

View File

@ -28,6 +28,22 @@ if(FXOS_CLEAN_LOGS)
"${PROJECT_BINARY_DIR}/compiler_filter.sh")
endif()
#---
# tooling for generating code at compile-time
#---
add_executable(mkdefs_insn tools/mkdefs_insn.cc)
target_link_libraries(mkdefs_insn PRIVATE -lfmt)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gendefs/insn.h"
COMMAND mkdir -p "${CMAKE_CURRENT_BINARY_DIR}/gendefs/"
COMMAND "$<TARGET_FILE:mkdefs_insn>"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/sh3.def"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/sh4.def" >
"${CMAKE_CURRENT_BINARY_DIR}/gendefs/insn.h"
DEPENDS mkdefs_insn lib/sh3.def lib/sh4.def)
#---
# fxos core
#---
@ -69,10 +85,13 @@ set(fxos_core_SOURCES
lib/util/bson.cpp
lib/util/Buffer.cpp
lib/util/log.cpp
lib/util/Timer.cpp)
lib/util/Timer.cpp
"${CMAKE_CURRENT_BINARY_DIR}/gendefs/insn.h")
add_library(fxos-core ${fxos_core_SOURCES} ${FLEX_LoadAsm_OUTPUTS})
target_include_directories(fxos-core PUBLIC include)
target_include_directories(fxos-core
PUBLIC include "${CMAKE_CURRENT_BINARY_DIR}")
#---
# fxos shell

View File

@ -168,7 +168,7 @@ struct AsmInstruction
/* Original opcode. Initialized to 0 when unset, which is an invalid
instruction by design. */
u32 opcode;
u32 encoding;
/* Operation size (0, 1, 2 or 4) */
i8 opsize;
/* Number of arguments */

View File

@ -109,7 +109,7 @@ static ProgramStateDiff interpretInstruction(
diff.setUnknown();
// TODO: Do this properly
u16 opc = ins.opcode().opcode;
u16 opc = ins.opcode().encoding;
if((opc & 0xf000) == 0xe000) {
int reg = (opc >> 8) & 0xf;
int val = (int8_t)opc;

View File

@ -19,13 +19,13 @@ std::array<std::optional<AsmInstruction>, 65536> insmap;
void register_instruction(AsmInstruction const &ins)
{
uint16_t opcode = ins.opcode;
uint16_t encoding = ins.encoding;
if(insmap[opcode])
FxOS_log(ERR, "opcode collision between a %s and a %s at %04x",
insmap[opcode]->mnemonic, ins.mnemonic, opcode);
if(insmap[encoding])
FxOS_log(ERR, "encoding collision between a %s and a %s at %04x",
insmap[encoding]->mnemonic, ins.mnemonic, encoding);
else
insmap[opcode] = ins;
insmap[encoding] = ins;
}
//---
@ -40,7 +40,7 @@ Argument::Argument()
}
OldInstruction::OldInstruction(AsmInstruction const *inst):
inst {inst}, args {}, opcode {inst->opcode}, leader {false},
inst {inst}, args {}, opcode {inst->encoding}, leader {false},
delayslot {false}, terminal {false}, jump {false}, condjump {false},
jmptarget {0xffffffff}
{

View File

@ -196,7 +196,7 @@ u32 AsmArgument::getPCRelativeTarget(u32 pc, int size) const
//---
AsmInstruction::AsmInstruction(char const *mn):
opcode {0}, opsize {0}, arg_count {0}
encoding {0}, opsize {0}, arg_count {0}
{
int len = strlen(mn);
int pos = std::max(0, len - 2);

View File

@ -268,7 +268,7 @@ static int instantiate(struct Pattern p, char const *mnemonic, int argtoken1,
opcode |= (i << p.i_sh);
AsmInstruction ins(mnemonic);
ins.opcode = opcode;
ins.encoding = opcode;
ins.tags = insntags;
if(argtoken1) {

View File

@ -141,7 +141,7 @@ static void doOldInst(u32 pc, OldInstruction &i,
}
/* Raw data if instruction cannot be decoded */
printf(" %08x: %04x", pc, (i.inst ? i.inst->opcode : i.opcode));
printf(" %08x: %04x", pc, (i.inst ? i.inst->encoding : i.opcode));
if(!i.inst) {
printf("\n");
m_lastAddress = pc;
@ -239,7 +239,7 @@ void viewAssemblyInstruction(Instruction const &ins, ViewAssemblyOptions *opts)
ArgumentOutput argout;
u32 pc = ins.address();
printf(" %08x: %04x", pc, opcode.opcode);
printf(" %08x: %04x", pc, opcode.encoding);
/* Mnemonic */
static char const *suffixes[5] = {"", ".b", ".w", "", ".l"};

67
tools/mkdefs_insn.cc Normal file
View File

@ -0,0 +1,67 @@
#include <fmt/core.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <map>
static void usage(int rc)
{
fprintf(stderr, "usage: ./mkdefs_insn <insn listing...>\n");
exit(rc);
}
std::string encodeMnemonic(std::string mnemonic)
{
for(size_t i = 0; i < mnemonic.size(); i++) {
if(!isalnum(mnemonic[i]))
mnemonic[i] = '_';
}
return mnemonic;
}
static void parseTable(
char const *file, std::map<std::string, std::string> &allMnemonics)
{
std::ifstream fin {file};
std::string line, pattern, mnemonic;
while(std::getline(fin, line)) {
if(line.size() == 0 || !strchr("01nmdi", line[0]))
continue;
std::istringstream stream {line};
stream >> pattern >> mnemonic;
if(mnemonic.ends_with(".b") || mnemonic.ends_with(".w") ||
mnemonic.ends_with(".l"))
mnemonic = mnemonic.substr(0, mnemonic.size() - 2);
std::string enc = encodeMnemonic(mnemonic);
assert(!allMnemonics.count(enc) || allMnemonics.at(enc) == mnemonic);
allMnemonics.insert({ enc, mnemonic });
}
}
int main(int argc, char **argv)
{
for(int i = 1; i < argc; i++) {
if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
usage(0);
}
if(argc <= 1)
usage(1);
std::map<std::string, std::string> allMnemonics;
for(int i = 1; i < argc; i++)
parseTable(argv[i], allMnemonics);
for(auto const &[e,m]: allMnemonics)
fmt::print("GENDEFS_INSN({}, \"{}\")\n", e, m);
return 0;
}