Skip to content

Commit eb150e5

Browse files
refactored due to prophecy
1 parent 008ee71 commit eb150e5

File tree

6 files changed

+369
-331
lines changed

6 files changed

+369
-331
lines changed

Cargo.lock

+99
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ edition = "2021"
66
[dependencies]
77
elf = "0.7.4"
88
object = "0.36.5"
9+
phf = { version = "0.11", features = ["macros"] }

src/disassembly.rs

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use crate::instructions::*;
2+
3+
/// # instruction decoding
4+
/// TODO: explain this
5+
fn disassemble(instruction: Instruction) -> Option<InstructionType> {
6+
// check if the instruction is valid
7+
if (instruction == 0) || (instruction == 0xFFFFFFFF) || (instruction & 0b11 != 0b11) {
8+
return None
9+
}
10+
11+
// determine which function it is
12+
if let Some((name, i_type)) = determine_name(&instruction) {
13+
// TODO: match on instruction type and change register operands using the enum
14+
15+
match i_type {
16+
IT::R => Some(InstructionType::R {
17+
name,
18+
rd: ABIRegister::from(retrieve!(rd instruction) as u8),
19+
rs1: ABIRegister::from(retrieve!(rs1 instruction) as u8),
20+
rs2: ABIRegister::from(retrieve!(rs2 instruction) as u8)
21+
}),
22+
IT::I => Some(InstructionType::I {
23+
name,
24+
rd: ABIRegister::from(retrieve!(rd instruction) as u8),
25+
rs1: ABIRegister::from(retrieve!(rs1 instruction) as u8),
26+
imm: retrieve!(iimm instruction) as u16
27+
}),
28+
IT::S => Some(InstructionType::S {
29+
name,
30+
rs1: ABIRegister::from(retrieve!(rs1 instruction) as u8),
31+
rs2: ABIRegister::from(retrieve!(rs2 instruction) as u8),
32+
imm: retrieve!(simm instruction) as u16
33+
}),
34+
IT::B => Some(InstructionType::B {
35+
name,
36+
rs1: ABIRegister::from(retrieve!(rs1 instruction) as u8),
37+
rs2: ABIRegister::from(retrieve!(rs2 instruction) as u8),
38+
imm: retrieve!(bimm instruction) as u16
39+
}),
40+
IT::U => Some(InstructionType::U {
41+
name,
42+
rd: ABIRegister::from(retrieve!(rd instruction) as u8),
43+
imm: retrieve!(uimm instruction)
44+
}),
45+
IT::J => Some(InstructionType::J {
46+
name,
47+
rd: ABIRegister::from(retrieve!(rd instruction) as u8),
48+
imm: retrieve!(jimm instruction)
49+
})
50+
}
51+
} else {
52+
None
53+
}
54+
}
55+
56+
/// # Determine the function name
57+
/// TODO: better documentation for all of these, honestly
58+
/// TODO: account for R4 instructions here too, could just do it in the table with correct masks?
59+
fn determine_name(instruction: &Instruction) -> Option<(String, IT)> {
60+
// this function was revealed to me in a dream
61+
62+
// what i actually want to do here is combine the three fields into a single binary number
63+
// and get which one it is with a jump table
64+
// something like (funct7.unwrap_or(0) << 8 | funct3.unwrap_or(0) << 5 | opcode as u32)
65+
let opcode: u8 = retrieve!(opcode instruction).try_into().unwrap();
66+
let funct3: u8 = retrieve!(funct3 instruction).try_into().unwrap();
67+
let funct7: u8 = retrieve!(funct7 instruction).try_into().unwrap();
68+
69+
// use the from_bits to convert
70+
if let Some((name, i_type)) = from_bits(opcode, funct3, funct7) {
71+
Some((name, i_type))
72+
} else {
73+
None
74+
}
75+
}
76+
77+
/// Convert from bit fields to instruction
78+
/// TODO: swap this from a match statement to a phf, see https://github.com/rust-phf/rust-phf
79+
/// also of note, https://github.com/abonander/mime_guess/pull/14/files
80+
fn from_bits(opcode: u8, funct3: u8, funct7: u8) -> Option<(String, IT)> {
81+
// convert to single value
82+
match (opcode, funct3, funct7) {
83+
// RV32I
84+
(0b01100, 0b000, 0b0000000) => Some(("add".to_string(), IT::R)),
85+
_ => None
86+
}
87+
}
88+
89+
#[cfg(test)]
90+
mod test {
91+
use super::*;
92+
93+
#[test]
94+
fn test_decoding() {
95+
// TODO: replace these with ones with nontrivial operands
96+
let r_type = 0x4000503b; // sraw
97+
let u_type = 0x00000037; // lui
98+
let i_type = 0x00002003; // lw
99+
let b_type = 0x00000063; // beq
100+
let s_type = 0x4000503b; // sraw
101+
let j_type = 0x00003023; // sd
102+
103+
assert_eq!(
104+
disassemble(r_type),
105+
// TODO: test versions with ABI and raw identifiers?
106+
// or maybe not
107+
Some(InstructionType::R {
108+
name: "sraw".to_string(),
109+
rd: ABIRegister::zero,
110+
rs1: ABIRegister::zero,
111+
rs2: ABIRegister::zero
112+
}));
113+
}
114+
}

0 commit comments

Comments
 (0)