Compare commits
4 Commits
39df51900d
...
20d8953220
| Author | SHA1 | Date | |
|---|---|---|---|
| 20d8953220 | |||
| cc868fa6ec | |||
| daad92956e | |||
| 1d8b889771 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@
|
||||
/chip8
|
||||
/mos6502
|
||||
/riscv64
|
||||
/riscv64-linux-musl-cross
|
||||
/dump
|
||||
503
riscv64.cc
503
riscv64.cc
@@ -46,6 +46,7 @@ enum Op {
|
||||
ADDI,
|
||||
ADDIW,
|
||||
ADDW,
|
||||
AMOSWAP_D,
|
||||
AND,
|
||||
ANDI,
|
||||
AUIPC,
|
||||
@@ -55,11 +56,45 @@ enum Op {
|
||||
BLT,
|
||||
BLTU,
|
||||
BNE,
|
||||
C_ADD,
|
||||
C_ADDI,
|
||||
C_ADDIW,
|
||||
C_ADDI16SP,
|
||||
C_ADDI4SPN,
|
||||
C_ADDW,
|
||||
C_AND,
|
||||
C_ANDI,
|
||||
C_BEQZ,
|
||||
C_BNEZ,
|
||||
C_EBREAK,
|
||||
C_FLDSP,
|
||||
C_J,
|
||||
C_JALR,
|
||||
C_JR,
|
||||
C_LD,
|
||||
C_LDSP,
|
||||
C_LI,
|
||||
C_LUI,
|
||||
C_LW,
|
||||
C_MV,
|
||||
C_OR,
|
||||
C_SD,
|
||||
C_SDSP,
|
||||
C_SRAI,
|
||||
C_SRLI,
|
||||
C_SLLI,
|
||||
C_SUB,
|
||||
C_SUBW,
|
||||
C_SW,
|
||||
C_SWSP,
|
||||
C_XOR,
|
||||
DIV,
|
||||
DIVU,
|
||||
DIVUW,
|
||||
DIVW,
|
||||
ECALL,
|
||||
FENCE,
|
||||
FENCE_TSO,
|
||||
JAL,
|
||||
JALR,
|
||||
LB,
|
||||
@@ -67,6 +102,7 @@ enum Op {
|
||||
LD,
|
||||
LH,
|
||||
LHU,
|
||||
LR_D,
|
||||
LUI,
|
||||
LW,
|
||||
LWU,
|
||||
@@ -76,11 +112,13 @@ enum Op {
|
||||
MULW,
|
||||
OR,
|
||||
ORI,
|
||||
PAUSE,
|
||||
REM,
|
||||
REMU,
|
||||
REMUW,
|
||||
REMW,
|
||||
SB,
|
||||
SC_D,
|
||||
SD,
|
||||
SH,
|
||||
SLL,
|
||||
@@ -103,11 +141,13 @@ enum Op {
|
||||
SUBW,
|
||||
SW,
|
||||
XOR,
|
||||
XORI
|
||||
XORI,
|
||||
};
|
||||
|
||||
struct Ins {
|
||||
Op op;
|
||||
u8 length;
|
||||
|
||||
u8 rd;
|
||||
u8 rs1;
|
||||
union {
|
||||
@@ -123,34 +163,71 @@ struct Section {
|
||||
u64 entrypoint;
|
||||
};
|
||||
|
||||
enum class Format { NONE, R, I, I_LOAD, I_SHIFT, S, B, U, J };
|
||||
enum class Format {
|
||||
NONE,
|
||||
R,
|
||||
I,
|
||||
I_LOAD,
|
||||
I_SHIFT,
|
||||
S,
|
||||
B,
|
||||
U,
|
||||
J,
|
||||
CI,
|
||||
CJ,
|
||||
CSS,
|
||||
CR,
|
||||
CR1,
|
||||
CL,
|
||||
R_ATOMIC,
|
||||
R_ATOMIC_LR
|
||||
};
|
||||
|
||||
struct OpDef {
|
||||
const char *mnemonic;
|
||||
Format format;
|
||||
};
|
||||
|
||||
static constexpr std::array<OpDef, 63> OP_TABLE = {{
|
||||
static constexpr std::array<OpDef, 101> OP_TABLE = {{
|
||||
{"???", Format::NONE}, {"add", Format::R},
|
||||
{"addi", Format::I}, {"addiw", Format::I},
|
||||
{"addw", Format::R}, {"and", Format::R},
|
||||
{"andi", Format::I}, {"auipc", Format::U},
|
||||
{"beq", Format::B}, {"bge", Format::B},
|
||||
{"bgeu", Format::B}, {"blt", Format::B},
|
||||
{"bltu", Format::B}, {"bne", Format::B},
|
||||
{"div", Format::R}, {"divu", Format::R},
|
||||
{"divuw", Format::R}, {"divw", Format::R},
|
||||
{"ecall", Format::NONE}, {"jal", Format::J},
|
||||
{"jalr", Format::I}, {"lb", Format::I_LOAD},
|
||||
{"lbu", Format::I_LOAD}, {"ld", Format::I_LOAD},
|
||||
{"lh", Format::I_LOAD}, {"lhu", Format::I_LOAD},
|
||||
{"addw", Format::R}, {"amoswap.d", Format::R_ATOMIC},
|
||||
{"and", Format::R}, {"andi", Format::I},
|
||||
{"auipc", Format::U}, {"beq", Format::B},
|
||||
{"bge", Format::B}, {"bgeu", Format::B},
|
||||
{"blt", Format::B}, {"bltu", Format::B},
|
||||
{"bne", Format::B}, {"c.add", Format::CR},
|
||||
{"c.addi", Format::CI}, {"c.addiw", Format::CI},
|
||||
{"c.addi16sp", Format::CI}, {"c.addi4spn", Format::CI},
|
||||
{"c.addw", Format::CI}, {"c.and", Format::CR},
|
||||
{"c.andi", Format::CI}, {"c.beqz", Format::B},
|
||||
{"c.bnez", Format::B}, {"c.ebreak", Format::CR},
|
||||
{"c.fldsp", Format::CSS}, {"c.j", Format::CJ},
|
||||
{"c.jalr", Format::CR1}, {"c.jr", Format::CR1},
|
||||
{"c.ld", Format::CL}, {"c.ldsp", Format::CL},
|
||||
{"c.li", Format::CI}, {"c.lui", Format::CI},
|
||||
{"c.lw", Format::CL}, {"c.mv", Format::CR},
|
||||
{"c.or", Format::CR}, {"c.sd", Format::S},
|
||||
{"c.sdsp", Format::CSS}, {"c.slli", Format::CI},
|
||||
{"c.srai", Format::CI}, {"c.srli", Format::CI},
|
||||
{"c.sub", Format::CR}, {"c.subw", Format::CR},
|
||||
{"c.sw", Format::S}, {"c.swsp", Format::CSS},
|
||||
{"c.xor", Format::CR}, {"div", Format::R},
|
||||
{"divu", Format::R}, {"divuw", Format::R},
|
||||
{"divw", Format::R}, {"ecall", Format::NONE},
|
||||
{"fence", Format::NONE}, {"fence.tso", Format::NONE},
|
||||
{"jal", Format::J}, {"jalr", Format::I},
|
||||
{"lb", Format::I_LOAD}, {"lbu", Format::I_LOAD},
|
||||
{"ld", Format::I_LOAD}, {"lh", Format::I_LOAD},
|
||||
{"lhu", Format::I_LOAD}, {"lr.d", Format::R_ATOMIC_LR},
|
||||
{"lui", Format::U}, {"lw", Format::I_LOAD},
|
||||
{"lwu", Format::I_LOAD}, {"mul", Format::R},
|
||||
{"mulh", Format::R}, {"mulhu", Format::R},
|
||||
{"mulw", Format::R}, {"or", Format::R},
|
||||
{"ori", Format::I}, {"rem", Format::R},
|
||||
{"remu", Format::R}, {"remuw", Format::R},
|
||||
{"remw", Format::R}, {"sb", Format::S},
|
||||
{"ori", Format::I}, {"pause", Format::NONE},
|
||||
{"rem", Format::R}, {"remu", Format::R},
|
||||
{"remuw", Format::R}, {"remw", Format::R},
|
||||
{"sb", Format::S}, {"sc.d", Format::R_ATOMIC},
|
||||
{"sd", Format::S}, {"sh", Format::S},
|
||||
{"sll", Format::R}, {"slli", Format::I_SHIFT},
|
||||
{"slliw", Format::I_SHIFT}, {"sllw", Format::R},
|
||||
@@ -198,27 +275,35 @@ public:
|
||||
}
|
||||
elf_end(elf);
|
||||
|
||||
u64 num_ins = m_code_section.size / 4;
|
||||
u64 num_ins = m_code_section.size / 2;
|
||||
m_decoded.resize(num_ins);
|
||||
for (u64 i = 0; i < num_ins; i++) {
|
||||
|
||||
u64 offset = 0;
|
||||
while (offset < m_code_section.size) {
|
||||
u32 raw;
|
||||
std::memcpy(&raw, m_memory + m_code_section.offset + i * 4, sizeof(raw));
|
||||
m_decoded[i] = decode_raw(raw);
|
||||
std::memcpy(&raw, m_memory + m_code_section.offset + offset, sizeof(raw));
|
||||
|
||||
Ins ins = decode_raw(raw);
|
||||
ins.length = ((raw & 0b11) == 0b11) ? 4 : 2;
|
||||
m_decoded[offset / 2] = ins;
|
||||
disassemble_ins(ins);
|
||||
|
||||
offset += ins.length;
|
||||
}
|
||||
}
|
||||
|
||||
~RISCV64() { munmap(m_memory, MEMORY_SIZE); }
|
||||
|
||||
void disassemble_all() {
|
||||
for (m_pc = m_code_section.offset;
|
||||
m_pc < m_code_section.offset + m_code_section.size; m_pc += 4) {
|
||||
disassemble_one();
|
||||
m_pc = m_code_section.offset;
|
||||
while (m_pc < m_code_section.offset + m_code_section.size) {
|
||||
Ins ins = m_decoded[(m_pc - m_code_section.offset) / 2];
|
||||
disassemble_ins(ins);
|
||||
m_pc += ins.length;
|
||||
}
|
||||
}
|
||||
|
||||
void disassemble_one() {
|
||||
Ins ins = m_decoded[(m_pc - m_code_section.offset) / 4];
|
||||
|
||||
void disassemble_ins(Ins ins) {
|
||||
const OpDef &def = OP_TABLE[ins.op];
|
||||
|
||||
switch (def.format) {
|
||||
@@ -252,6 +337,32 @@ public:
|
||||
case Format::J:
|
||||
std::println("{} {}, {}", def.mnemonic, REGS[ins.rd], ins.imm);
|
||||
break;
|
||||
case Format::CI:
|
||||
std::println("{} {}, {}", def.mnemonic, REGS[ins.rd], ins.imm);
|
||||
break;
|
||||
case Format::CJ:
|
||||
std::println("{} {}", def.mnemonic, ins.imm);
|
||||
break;
|
||||
case Format::CSS:
|
||||
std::println("{} {}, {}(sp)", def.mnemonic, REGS[ins.rs2], ins.imm);
|
||||
break;
|
||||
case Format::CR:
|
||||
std::println("{} {}, {}", def.mnemonic, REGS[ins.rd], REGS[ins.rs2]);
|
||||
break;
|
||||
case Format::CR1:
|
||||
std::println("{} {}", def.mnemonic, REGS[ins.rs1]);
|
||||
break;
|
||||
case Format::CL:
|
||||
std::println("{} {}, {}({})", def.mnemonic, REGS[ins.rd], ins.imm,
|
||||
REGS[ins.rs1]);
|
||||
break;
|
||||
case Format::R_ATOMIC_LR:
|
||||
std::println("{} {}, ({})", def.mnemonic, REGS[ins.rd], REGS[ins.rs1]);
|
||||
break;
|
||||
case Format::R_ATOMIC:
|
||||
std::println("{} {}, {}, ({})", def.mnemonic, REGS[ins.rd], REGS[ins.rs2],
|
||||
REGS[ins.rs1]);
|
||||
break;
|
||||
case Format::NONE:
|
||||
std::println("{}", def.mnemonic);
|
||||
break;
|
||||
@@ -300,7 +411,7 @@ public:
|
||||
while (m_pc < MEMORY_SIZE) {
|
||||
m_regs[0] = 0; // clear the zero register
|
||||
|
||||
Ins i = m_decoded[(m_pc - m_code_section.offset) / 4];
|
||||
Ins i = m_decoded[(m_pc - m_code_section.offset) / 2];
|
||||
|
||||
switch (i.op) {
|
||||
case Op::INVALID: {
|
||||
@@ -640,9 +751,13 @@ public:
|
||||
case Op::XORI: {
|
||||
m_regs[i.rd] = m_regs[i.rs1] ^ i.imm;
|
||||
}; break;
|
||||
default: {
|
||||
std::println(stderr, "Unrecognized Op: {}", (u64)i.op);
|
||||
exit(1);
|
||||
}; break;
|
||||
}
|
||||
|
||||
m_pc += 4;
|
||||
m_pc += i.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,6 +794,284 @@ private:
|
||||
}
|
||||
|
||||
Ins decode_raw(u32 raw) {
|
||||
if ((raw & 0b11) != 0b11) {
|
||||
return decode_raw_16bit((u16)raw);
|
||||
} else {
|
||||
return decode_raw_32bit(raw);
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.riscv.org/reference/isa/unpriv/c-st-ext.html#27-8-rvc-instruction-set-listings
|
||||
Ins decode_raw_16bit(u16 raw) {
|
||||
u8 opcode = raw & 0b11;
|
||||
u32 funct3 = (raw >> 13) & 0b111;
|
||||
|
||||
Ins i;
|
||||
i.op = Op::INVALID;
|
||||
|
||||
i.rd = (raw >> 7) & 0b11111;
|
||||
|
||||
switch (opcode) {
|
||||
case 0b00: {
|
||||
switch (funct3) {
|
||||
case 0b000: {
|
||||
if (raw == 0) {
|
||||
std::println(stderr, "C: illegal instruction (all zeros)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
i.rd = ((raw >> 2) & 0b111) + 8;
|
||||
i.rs1 = 2;
|
||||
i.imm = (((raw >> 11) & 0b11) << 4) | (((raw >> 7) & 0b1111) << 6) |
|
||||
(((raw >> 6) & 0b1) << 2) | (((raw >> 5) & 0b1) << 3);
|
||||
i.op = Op::C_ADDI4SPN;
|
||||
}; break;
|
||||
case 0b010: {
|
||||
i.rd = ((raw >> 2) & 0b111) + 8;
|
||||
i.rs1 = ((raw >> 7) & 0b111) + 8;
|
||||
i.imm = (((raw >> 10) & 0b111) << 3) | (((raw >> 6) & 0b1) << 2) |
|
||||
(((raw >> 5) & 0b1) << 6);
|
||||
i.op = Op::C_LW;
|
||||
}; break;
|
||||
case 0b011: {
|
||||
i.rd = ((raw >> 2) & 0b111) + 8;
|
||||
i.rs1 = ((raw >> 7) & 0b111) + 8;
|
||||
i.imm = (((raw >> 10) & 0b111) << 3) | (((raw >> 5) & 0b11) << 6);
|
||||
i.op = Op::C_LD;
|
||||
}; break;
|
||||
case 0b110: {
|
||||
i.rs1 = ((raw >> 7) & 0b111) + 8;
|
||||
i.rs2 = ((raw >> 2) & 0b111) + 8;
|
||||
i.imm = (((raw >> 10) & 0b111) << 3) | (((raw >> 6) & 0b1) << 2) |
|
||||
(((raw >> 5) & 0b1) << 6);
|
||||
i.op = Op::C_SW;
|
||||
}; break;
|
||||
case 0b111: {
|
||||
i.rs1 = ((raw >> 7) & 0b111) + 8;
|
||||
i.rs2 = ((raw >> 2) & 0b111) + 8;
|
||||
i.imm = (((raw >> 10) & 0b111) << 3) | (((raw >> 5) & 0b11) << 6);
|
||||
i.op = Op::C_SD;
|
||||
}; break;
|
||||
default: {
|
||||
std::println(stderr, "C: opcode=00: unrecognized funct3: {:03b}",
|
||||
funct3);
|
||||
exit(1);
|
||||
}; break;
|
||||
}
|
||||
}; break;
|
||||
case 0b01: {
|
||||
switch (funct3) {
|
||||
case 0b000: {
|
||||
i.imm = ((raw >> 2) & 0b11111) | (((raw >> 12) & 0b1) << 5);
|
||||
i.imm = (i.imm << 26) >> 26;
|
||||
i.op = Op::C_ADDI;
|
||||
}; break;
|
||||
case 0b001: {
|
||||
i.rs1 = i.rd;
|
||||
i.imm = ((raw >> 2) & 0b11111) | (((raw >> 12) & 0b1) << 5);
|
||||
i.imm = (i.imm << 26) >> 26;
|
||||
i.op = Op::C_ADDIW;
|
||||
}; break;
|
||||
case 0b010: {
|
||||
i.imm = ((raw >> 2) & 0b11111) | (((raw >> 12) & 0b1) << 5);
|
||||
i.imm = (i.imm << 26) >> 26;
|
||||
i.op = Op::C_LI;
|
||||
}; break;
|
||||
case 0b011: {
|
||||
if (i.rd == 2) {
|
||||
i.imm = (((raw >> 12) & 0b1) << 9) | (((raw >> 3) & 0b11) << 7) |
|
||||
(((raw >> 5) & 0b1) << 6) | (((raw >> 2) & 0b1) << 5) |
|
||||
(((raw >> 6) & 0b1) << 4);
|
||||
i.imm = (i.imm << 22) >> 22;
|
||||
i.op = Op::C_ADDI16SP;
|
||||
} else {
|
||||
i.imm = (((raw >> 12) & 0b1) << 17) | (((raw >> 2) & 0b11111) << 12);
|
||||
i.imm = (i.imm << 14) >> 14;
|
||||
i.op = Op::C_LUI;
|
||||
}
|
||||
|
||||
}; break;
|
||||
case 0b100: {
|
||||
u8 funct2 = (raw >> 10) & 0b11;
|
||||
|
||||
if (funct2 == 0b11) {
|
||||
|
||||
bool bit12 = (raw >> 12) & 0b1;
|
||||
i.rs2 = ((raw >> 2) & 0b111) + 8;
|
||||
u8 sub_op = (raw >> 5) & 0b11;
|
||||
|
||||
if (bit12 == 0) {
|
||||
switch (sub_op) {
|
||||
case 0b00:
|
||||
i.op = Op::C_SUB;
|
||||
break;
|
||||
case 0b01:
|
||||
i.op = Op::C_XOR;
|
||||
break;
|
||||
case 0b10:
|
||||
i.op = Op::C_OR;
|
||||
break;
|
||||
case 0b11:
|
||||
i.op = Op::C_AND;
|
||||
break;
|
||||
default:
|
||||
std::println(
|
||||
stderr,
|
||||
"C: opcode=01: funct3=100: bit12=0: unrecognized sub_op");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
switch (sub_op) {
|
||||
case 0b00:
|
||||
i.op = Op::C_SUBW;
|
||||
break;
|
||||
case 0b01:
|
||||
i.op = Op::C_ADDW;
|
||||
break;
|
||||
default:
|
||||
std::println(stderr,
|
||||
"C: opcode=01: funct3=100: bit12=1: unrecognized "
|
||||
"sub_op: {:b}",
|
||||
sub_op);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i.rd = ((raw >> 7) & 0b111) + 8;
|
||||
i.rs1 = i.rd;
|
||||
i.imm = ((raw >> 2) & 0b11111) | (((raw >> 12) & 0b1) << 5);
|
||||
|
||||
switch (funct2) {
|
||||
case 0b00:
|
||||
i.op = Op::C_SRLI;
|
||||
break;
|
||||
case 0b01:
|
||||
i.op = Op::C_SRAI;
|
||||
break;
|
||||
case 0b10:
|
||||
i.imm = (i.imm << 26) >> 26;
|
||||
i.op = Op::C_ANDI;
|
||||
break;
|
||||
default:
|
||||
std::println(
|
||||
stderr,
|
||||
"C: opcode=01: funct3=100: funct2!=11: unrecognized funct2");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}; break;
|
||||
case 0b101: {
|
||||
i.rd = 0;
|
||||
i.imm = (((raw >> 12) & 0b1) << 11) | (((raw >> 11) & 0b1) << 4) |
|
||||
(((raw >> 9) & 0b11) << 8) | (((raw >> 8) & 0b1) << 10) |
|
||||
(((raw >> 7) & 0b1) << 6) | (((raw >> 6) & 0b1) << 7) |
|
||||
(((raw >> 5) & 0b1) << 3) | (((raw >> 3) & 0b11) << 1) |
|
||||
(((raw >> 2) & 0b1) << 5);
|
||||
i.imm = (i.imm << 20) >> 20;
|
||||
i.op = Op::C_J;
|
||||
}; break;
|
||||
case 0b110: {
|
||||
i.rs1 = ((raw >> 7) & 0b111) + 8;
|
||||
i.rs2 = 0;
|
||||
i.imm = (((raw >> 12) & 0b1) << 8) | (((raw >> 10) & 0b11) << 3) |
|
||||
(((raw >> 5) & 0b11) << 6) | (((raw >> 3) & 0b11) << 1) |
|
||||
(((raw >> 2) & 0b1) << 5);
|
||||
i.imm = (i.imm << 23) >> 23;
|
||||
i.op = Op::C_BEQZ;
|
||||
}; break;
|
||||
case 0b111: {
|
||||
i.rs1 = ((raw >> 7) & 0b111) + 8;
|
||||
i.rs2 = 0;
|
||||
i.imm = (((raw >> 12) & 0b1) << 8) | (((raw >> 10) & 0b11) << 3) |
|
||||
(((raw >> 5) & 0b11) << 6) | (((raw >> 3) & 0b11) << 1) |
|
||||
(((raw >> 2) & 0b1) << 5);
|
||||
i.imm = (i.imm << 23) >> 23;
|
||||
i.op = Op::C_BNEZ;
|
||||
}; break;
|
||||
default: {
|
||||
std::println(stderr, "C: opcode=01: unrecognized funct3: {:03b}",
|
||||
funct3);
|
||||
exit(1);
|
||||
}; break;
|
||||
}
|
||||
}; break;
|
||||
case 0b10: {
|
||||
switch (funct3) {
|
||||
case 0b000: {
|
||||
i.imm = ((raw >> 2) & 0b11111) | (((raw >> 12) & 0b1) << 5);
|
||||
i.op = Op::C_SLLI;
|
||||
}; break;
|
||||
case 0b001: {
|
||||
i.rs1 = 2;
|
||||
i.imm = (((raw >> 12) & 0b1) << 5) | (((raw >> 5) & 0b11) << 3) |
|
||||
(((raw >> 2) & 0b111) << 6);
|
||||
i.op = Op::C_FLDSP;
|
||||
}; break;
|
||||
case 0b011: {
|
||||
i.rs1 = 2;
|
||||
i.imm = (((raw >> 12) & 0b1) << 5) | (((raw >> 5) & 0b11) << 3) |
|
||||
(((raw >> 2) & 0b111) << 6);
|
||||
i.op = Op::C_LDSP;
|
||||
}; break;
|
||||
case 0b100: {
|
||||
bool bit12 = (raw >> 12) & 0b1;
|
||||
i.rs2 = (raw >> 2) & 0b11111;
|
||||
|
||||
if (bit12 == 0) {
|
||||
if (i.rs2 == 0) {
|
||||
i.rs1 = i.rd;
|
||||
i.rd = 0;
|
||||
i.imm = 0;
|
||||
i.op = Op::C_JR;
|
||||
} else {
|
||||
i.rs1 = 0;
|
||||
i.op = Op::C_MV;
|
||||
}
|
||||
} else {
|
||||
if (i.rs2 == 0) {
|
||||
if (i.rd == 0) {
|
||||
i.op = Op::C_EBREAK;
|
||||
} else {
|
||||
i.rs1 = i.rd;
|
||||
i.rd = 1;
|
||||
i.imm = 0;
|
||||
i.op = Op::C_JALR;
|
||||
}
|
||||
} else {
|
||||
i.rs1 = i.rd;
|
||||
i.op = Op::C_ADD;
|
||||
}
|
||||
}
|
||||
}; break;
|
||||
case 0b110: {
|
||||
i.rs2 = (raw >> 2) & 0b11111;
|
||||
i.rs1 = 2;
|
||||
i.imm = (((raw >> 9) & 0b1111) << 2) | (((raw >> 7) & 0b11) << 6);
|
||||
i.op = Op::C_SWSP;
|
||||
}; break;
|
||||
case 0b111: {
|
||||
i.rs2 = (raw >> 2) & 0b11111;
|
||||
i.imm = (((raw >> 10) & 0b111) << 3) | (((raw >> 7) & 0b111) << 6);
|
||||
i.op = Op::C_SDSP;
|
||||
}; break;
|
||||
default: {
|
||||
std::println(stderr, "C: opcode=10: unrecognized funct3: {:03b}",
|
||||
funct3);
|
||||
exit(1);
|
||||
}; break;
|
||||
}
|
||||
}; break;
|
||||
default: {
|
||||
std::println(stderr, "C: unrecognized opcode: {:02b}", opcode);
|
||||
exit(1);
|
||||
}; break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// https://docs.riscv.org/reference/isa/unpriv/rv-32-64g.html
|
||||
Ins decode_raw_32bit(u32 raw) {
|
||||
u8 opcode = raw & 0b1111111;
|
||||
|
||||
Ins i;
|
||||
@@ -925,9 +1318,36 @@ private:
|
||||
exit(1);
|
||||
}
|
||||
}; break;
|
||||
case 0b0101111:
|
||||
std::println(stderr, "A extension not implemented yet.");
|
||||
exit(1);
|
||||
case 0b0101111: {
|
||||
u8 funct3 = (raw >> 12) & 0b111;
|
||||
u8 funct7 = (raw >> 27) & 0b11111;
|
||||
i.rd = (raw >> 7) & 0b11111;
|
||||
i.rs1 = (raw >> 15) & 0b11111;
|
||||
i.rs2 = (raw >> 20) & 0b11111;
|
||||
|
||||
if (funct3 == 0b011) {
|
||||
switch (funct7) {
|
||||
case 0b00001: {
|
||||
i.op = Op::AMOSWAP_D;
|
||||
}; break;
|
||||
case 0b00010: {
|
||||
i.op = Op::LR_D;
|
||||
}; break;
|
||||
case 0b00011: {
|
||||
i.op = Op::SC_D;
|
||||
}; break;
|
||||
default: {
|
||||
std::println(stderr,
|
||||
"0101111: funct3=011: unrecognized funct7: {:05b}",
|
||||
funct7);
|
||||
exit(1);
|
||||
}; break;
|
||||
}
|
||||
} else {
|
||||
std::println(stderr, "0101111: unrecognized funct3: {:03b}", funct3);
|
||||
exit(1);
|
||||
}
|
||||
}; break;
|
||||
case 0b0111011: {
|
||||
u8 funct3 = (raw >> 12) & 0b111;
|
||||
u8 funct7 = (u8)((raw >> 25) & 0b1111111);
|
||||
@@ -1028,7 +1448,7 @@ private:
|
||||
} else if (funct3 == 0b011) {
|
||||
i.op = Op::SD;
|
||||
} else {
|
||||
std::println(stderr, "S-type: unrecognized funct3: {:03b}", funct3);
|
||||
std::println(stderr, "0100011: unrecognized funct3: {:03b}", funct3);
|
||||
exit(1);
|
||||
}
|
||||
}; break;
|
||||
@@ -1042,6 +1462,23 @@ private:
|
||||
i.imm = raw >> 12;
|
||||
i.op = Op::AUIPC;
|
||||
}; break;
|
||||
case 0b0001111: {
|
||||
u8 funct3 = (raw >> 12) & 0b111;
|
||||
if (funct3 == 0b000) {
|
||||
i.imm = (raw >> 20) & 0b111111111111;
|
||||
|
||||
if (i.imm == 0b000000010000) {
|
||||
i.op = Op::PAUSE;
|
||||
} else if (i.imm == 0b100000110011) {
|
||||
i.op = Op::FENCE_TSO;
|
||||
} else {
|
||||
i.op = Op::FENCE;
|
||||
}
|
||||
} else {
|
||||
std::println(stderr, "0001111: unrecognized funct3: {:03b}", funct3);
|
||||
exit(1);
|
||||
}
|
||||
}; break;
|
||||
default:
|
||||
std::println(stderr, "Unrecognized opcode: {:07b}", opcode);
|
||||
exit(1);
|
||||
|
||||
Reference in New Issue
Block a user