Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
trdthg committed Jun 26, 2024
1 parent 7e3bd09 commit a248b5c
Show file tree
Hide file tree
Showing 7 changed files with 524 additions and 188 deletions.
6 changes: 3 additions & 3 deletions src/machine/csr/controlstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,16 @@ namespace machine { namespace CSR {

class RegisterMapByName {
bool initialized = false;
std::unordered_map<const char *, size_t> map;
std::unordered_map<std::string, size_t> map;

void init() {
for (size_t i = 0; i < REGISTERS.size(); i++) {
map.emplace(REGISTERS[i].name, i);
map.emplace(std::string(REGISTERS[i].name), i);
}
initialized = true;
}
public:
size_t at(const char* name) {
size_t at(std::string name) {
if (!initialized) init();
return map.at(name);
}
Expand Down
108 changes: 56 additions & 52 deletions src/machine/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,55 @@ Instruction &Instruction::operator=(const Instruction &c) {
return *this;
}

QString field_to_string(int32_t field, const ArgumentDesc* arg_desc, Address inst_addr, bool symbolic_registers_enabled) {
QString res = "";
if (arg_desc->min < 0) {
field = extend(field, [&]() {
int sum = (int)arg_desc->arg.shift;
for (auto chunk : arg_desc->arg) {
sum += chunk.count;
}
return sum;
}());
}
switch (arg_desc->kind) {
case 'g': {
if (symbolic_registers_enabled) {
res += QString(Rv_regnames[field]);
} else {
res += "x" + QString::number(field);
}
break;
}
case 'p':
case 'a': {
field += (int32_t)inst_addr.get_raw();
res.append(str::asHex(field));
break;
}
case 'o':
case 'n': {
if (arg_desc->min < 0) {
res += QString::number((int32_t)field, 10);
} else {
res.append(str::asHex(uint32_t(field)));
}
break;
}
case 'E': {
if (symbolic_registers_enabled) {
try {
res += CSR::REGISTERS[CSR::REGISTER_MAP.at(CSR::Address(field))].name;
} catch (std::out_of_range &e) { res.append(str::asHex(field)); }
} else {
res.append(str::asHex(field));
}
break;
}
}
return res;
}

QString Instruction::to_str(Address inst_addr) const {
const InstructionMap &im = InstructionMapFind(dt);
// TODO there are exception where some fields are zero and such so we should
Expand All @@ -787,50 +836,7 @@ QString Instruction::to_str(Address inst_addr) const {
continue;
}
auto field = (int32_t)arg_desc->arg.decode(this->dt);
if (arg_desc->min < 0) {
field = extend(field, [&]() {
int sum = (int)arg_desc->arg.shift;
for (auto chunk : arg_desc->arg) {
sum += chunk.count;
}
return sum;
}());
}
switch (arg_desc->kind) {
case 'g': {
if (symbolic_registers_enabled) {
res += QString(Rv_regnames[field]);
} else {
res += "x" + QString::number(field);
}
break;
}
case 'p':
case 'a': {
field += (int32_t)inst_addr.get_raw();
res.append(str::asHex(uint32_t(field)));
break;
}
case 'o':
case 'n': {
if (arg_desc->min < 0) {
res += QString::number((int32_t)field, 10);
} else {
res.append(str::asHex(uint32_t(field)));
}
break;
}
case 'E': {
if (symbolic_registers_enabled) {
try {
res += CSR::REGISTERS[CSR::REGISTER_MAP.at(CSR::Address(field))].name;
} catch (std::out_of_range &e) { res.append(str::asHex(field)); }
} else {
res.append(str::asHex(field));
}
break;
}
}
res += field_to_string(field, arg_desc, inst_addr, symbolic_registers_enabled);
}
}
return res;
Expand Down Expand Up @@ -1375,14 +1381,15 @@ bool parse_immediate_value(

uint16_t parse_csr_address(const QString &field_token, uint &chars_taken) {
if (field_token.at(0).isLetter()) {
size_t index = CSR::REGISTER_MAP_BY_NAME.at(qPrintable(field_token));
if (index < 0) {
try {
size_t index = CSR::REGISTER_MAP_BY_NAME.at(field_token.toStdString());
auto &reg = CSR::REGISTERS[index];
chars_taken = strlen(reg.name);
return reg.address.data;
} catch (std::out_of_range &e) {
chars_taken = 0;
return 0;
}
auto &reg = CSR::REGISTERS[index];
chars_taken = strlen(reg.name);
return reg.address.data;
} else {
char *r;
uint64_t val;
Expand Down Expand Up @@ -1449,9 +1456,6 @@ void Instruction::set_symbolic_registers(bool enable) {
symbolic_registers_enabled = enable;
}

inline int32_t Instruction::extend(uint32_t value, uint32_t used_bits) const {
return value | ~((value & (1 << (used_bits - 1))) - 1);
}

void Instruction::append_recognized_registers(QStringList &list) {
for (auto name : Rv_regnames) {
Expand Down
5 changes: 4 additions & 1 deletion src/machine/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ struct TokenizedInstruction {
struct RelocExpression;
typedef QVector<RelocExpression *> RelocExpressionList;

inline int32_t extend(uint32_t value, uint32_t used_bits) {
return value | ~((value & (1 << (used_bits - 1))) - 1);
}

class Instruction {
public:
Instruction();
Expand Down Expand Up @@ -208,7 +212,6 @@ class Instruction {
RelocExpressionList *reloc,
Modifier pseudo_mod = Modifier::NONE,
uint64_t initial_immediate_value = 0);
inline int32_t extend(uint32_t value, uint32_t used_bits) const;
static uint32_t parse_field(
QString &field_token,
const QString &arg,
Expand Down
72 changes: 57 additions & 15 deletions src/machine/instruction.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,73 @@ void TestInstruction::instruction_access() {
QCOMPARE(i.address().get_raw(), (uint64_t)0x3ffffff);
}

static struct { uint32_t code; QString str; } code_to_string[] = {
{0xffffffff, "unknown"},
{0x0, "unknown"},
{0b00000000000000000000000000010011, "nop"},
{0b00000000000000001000000010010011, "addi x1, x1, 0"},
{0b01111111111111111000111110010011, "addi x31, x31, 2047"},
{0b11111111111100001000000010010011, "addi x1, x1, -1"},
{0b10000000000000001000000010010011, "addi x1, x1, -2048"},
#include<./instruction.test.data.h>
static const struct {
uint32_t code;
QString str;
QString alias_str = nullptr;
} code_to_string[] = {
{ 0xffffffff, "unknown" },
{ 0x0, "unknown" },
{ 0b00000000000000000000000000010011, "nop" },
{ 0b00000000000000001000000010010011, "addi x1, x1, 0" },
{ 0b01111111111111111000111110010011, "addi x31, x31, 2047" },
{ 0b11111111111100001000000010010011, "addi x1, x1, -1" },
{ 0b10000000000000001000000010010011, "addi x1, x1, -2048" },
#include <./instruction.test.data.def>
};

struct Pair {
uint32_t code;
QString str;
};
static const struct {
QString string_data;
std::vector<Pair> pairs;
} pesude_code_to_string[] = {
{ "nop", { { 0b00000000000000000000000000010011, "nop" } } },
{ "la x1, 0xffffefff",
{ { 0xfffff097, "auipc x1, 0xfffff" }, { 0xfff08093, "addi x1, x1, -1" } } },
{ "li x1, 0xffffefff",
{ { 0xfffff0b7, "lui x1, 0xfffff" }, { 0xfff08093, "addi x1, x1, -1" } } },
{ "call 0xfffeffff",
{ { 0xffff0317, "auipc x6, 0xffff0" }, { 0xfff300e7, "jalr x1, -1(x6)" } } },
{ "tail 0xfffeffff",
{ { 0xffff0317, "auipc x6, 0xffff0" }, { 0xfff30067, "jalr x0, -1(x6)" } } },
{ "sext.b x1, x2", { { 0x11093, "slli x1, x2, 0x0" }, { 0x4000d093, "srai x1, x1, 0x0" } } },
{ "sext.h x1, x2", { { 0x11093, "slli x1, x2, 0x0" }, { 0x4000d093, "srai x1, x1, 0x0" } } },
{ "zext.h x1, x2", { { 0x11093, "slli x1, x2, 0x0" }, { 0xd093, "srli x1, x1, 0x0" } } },
{ "zext.w x1, x2", { { 0x11093, "slli x1, x2, 0x0" }, { 0xd093, "srli x1, x1, 0x0" } } },
};

void TestInstruction::instruction_to_str() {
size_t array_length = sizeof(code_to_string) / sizeof(code_to_string[0]);
for (size_t i = 0; i < array_length; ++i) {
for (size_t i = 0; i < sizeof(code_to_string) / sizeof(code_to_string[0]); i++) {
QCOMPARE(Instruction(code_to_string[i].code).to_str(), code_to_string[i].str);
}

for (size_t i = 0; i < sizeof(pesude_code_to_string) / sizeof(pesude_code_to_string[0]); i++) {
for (size_t j = 0; j < pesude_code_to_string[i].pairs.size(); j++) {
Pair pair = pesude_code_to_string[i].pairs[j];
QCOMPARE(Instruction(pair.code).to_str(), pair.str);
}
}
}

void TestInstruction::instruction_code_from_str() {
size_t array_length = sizeof(code_to_string) / sizeof(code_to_string[0]);
for (size_t i = 0; i < array_length; ++i) {
for (size_t i = 0; i < sizeof(code_to_string) / sizeof(code_to_string[0]); i++) {
if (code_to_string[i].str == "unknown") { continue; }
QString test_string_data = code_to_string[i].alias_str == nullptr
? code_to_string[i].str
: code_to_string[i].alias_str;
uint32_t code = 0;
Instruction::code_from_string(&code, code_to_string[i].str.length(), code_to_string[i].str, machine::Address(0x0));
QCOMPARE(code, code_to_string[i].code);
try {
Instruction::code_from_string(
&code, code_to_string[i].str.length(), test_string_data, Address(0x0));
QCOMPARE(code, code_to_string[i].code);
} catch (const Instruction::ParseError &e) {
TokenizedInstruction inst
= TokenizedInstruction::from_line(test_string_data, Address(0x0), nullptr, 0);
QFAIL(qPrintable(e.message));
} catch (...) { QFAIL("code_from_string throw unexpected exception"); }
}
}

Expand Down
Loading

0 comments on commit a248b5c

Please sign in to comment.