mirror of
https://github.com/Noratrieb/rustv32i.git
synced 2026-01-14 05:15:01 +01:00
finish initial C implementation
This commit is contained in:
parent
957b6a263a
commit
de03390dab
3 changed files with 130 additions and 24 deletions
|
|
@ -11,6 +11,6 @@ A small RISC-V emulator written in Rust.
|
|||
- [x] Zaamo standard extension
|
||||
- [ ] F standard extension
|
||||
- [ ] D standard extension
|
||||
- [ ] C standard extension
|
||||
- [x] C standard extension
|
||||
|
||||
- [x] Zihintpause standard extension
|
||||
|
|
|
|||
148
src/inst.rs
148
src/inst.rs
|
|
@ -244,17 +244,13 @@ impl Display for Inst {
|
|||
Inst::Sb { offset, src, base } => write!(f, "sb {src}, {}({base})", offset as i32),
|
||||
Inst::Sh { offset, src, base } => write!(f, "sh {src}, {}({base})", offset as i32),
|
||||
Inst::Sw { offset, src, base } => write!(f, "sw {src}, {}({base})", offset as i32),
|
||||
Inst::Addi {
|
||||
imm,
|
||||
dest: rd,
|
||||
src1: rs1,
|
||||
} => {
|
||||
if rs1.0 == 0 {
|
||||
write!(f, "li {rd}, {}", imm as i32)
|
||||
} else if imm == 0 {
|
||||
write!(f, "mv {rd}, {rs1}")
|
||||
Inst::Addi { imm, dest, src1 } => {
|
||||
if dest.0 == 0 && src1.0 == 0 {
|
||||
write!(f, "nop")
|
||||
} else if src1.0 == 0 {
|
||||
write!(f, "li {dest}, {}", imm as i32)
|
||||
} else {
|
||||
write!(f, "addi {rd}, {rs1}, {}", imm as i32)
|
||||
write!(f, "addi {dest}, {src1}, {}", imm as i32)
|
||||
}
|
||||
}
|
||||
Inst::Slti {
|
||||
|
|
@ -297,7 +293,13 @@ impl Display for Inst {
|
|||
dest,
|
||||
src1: rs1,
|
||||
} => write!(f, "srai {dest}, {rs1}, {}", imm as i32),
|
||||
Inst::Add { dest, src1, src2 } => write!(f, "add {dest}, {src1}, {src2}"),
|
||||
Inst::Add { dest, src1, src2 } => {
|
||||
if src1.0 == 0 {
|
||||
write!(f, "mv {dest}, {src2}")
|
||||
} else {
|
||||
write!(f, "add {dest}, {src1}, {src2}")
|
||||
}
|
||||
}
|
||||
Inst::Sub { dest, src1, src2 } => write!(f, "sub {dest}, {src1}, {src2}"),
|
||||
Inst::Sll { dest, src1, src2 } => write!(f, "sll {dest}, {src1}, {src2}"),
|
||||
Inst::Slt { dest, src1, src2 } => write!(f, "slt {dest}, {src1}, {src2}"),
|
||||
|
|
@ -501,10 +503,14 @@ impl InstCodeC {
|
|||
fn funct3(self) -> u32 {
|
||||
self.extract(13..=15)
|
||||
}
|
||||
fn funct2(self) -> u32 {
|
||||
self.extract(10..=11)
|
||||
}
|
||||
/// rd/rs1 (7..=11)
|
||||
fn rd(self) -> Reg {
|
||||
Reg(self.extract(7..=11) as u32)
|
||||
}
|
||||
/// rs2 (2..=6)
|
||||
fn rs2(self) -> Reg {
|
||||
Reg(self.extract(2..=6) as u32)
|
||||
}
|
||||
|
|
@ -552,6 +558,12 @@ impl Inst {
|
|||
let inst = match code.quadrant() {
|
||||
// C0
|
||||
0b00 => match code.funct3() {
|
||||
// C.ADDI4SPN -> addi \rd', sp, \imm
|
||||
0b000 => Inst::Addi {
|
||||
imm: code.immediate_u(&[(5..=5, 3), (6..=6, 2), (7..=10, 6), (11..=12, 4)]),
|
||||
dest: code.rs2_short(),
|
||||
src1: Reg::SP,
|
||||
},
|
||||
// C.LW -> lw \dest \offset(\base)
|
||||
0b010 => Inst::Lw {
|
||||
offset: code.immediate_u(&[(10..=12, 3), (5..=5, 6), (6..=6, 2)]),
|
||||
|
|
@ -594,6 +606,76 @@ impl Inst {
|
|||
dest: code.rd(),
|
||||
src1: Reg::ZERO,
|
||||
},
|
||||
// Arithmetic instructions
|
||||
0b100 => {
|
||||
let bit12 = code.extract(12..=12);
|
||||
match code.funct2() {
|
||||
// C.SRLI -> srli \rd', \rd', \imm
|
||||
0b00 => {
|
||||
if bit12 != 0 {
|
||||
return Err(Status::IllegalInstruction(code.into(), "imm"));
|
||||
}
|
||||
|
||||
Inst::Srli {
|
||||
imm: code.immediate_u(&[(2..=6, 0), (12..=12, 5)]),
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
}
|
||||
}
|
||||
// C.SRAI -> srai \rd', \rd', \imm
|
||||
0b01 => {
|
||||
if bit12 != 0 {
|
||||
return Err(Status::IllegalInstruction(code.into(), "imm"));
|
||||
}
|
||||
|
||||
Inst::Srai {
|
||||
imm: code.immediate_u(&[(2..=6, 0), (12..=12, 5)]),
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
}
|
||||
}
|
||||
// C.ANDI -> andi \rd', \rd', \imm
|
||||
0b10 => Inst::Andi {
|
||||
imm: code.immediate_u(&[(2..=6, 0), (12..=12, 5)]),
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
},
|
||||
0b11 => {
|
||||
if bit12 != 0 {
|
||||
return Err(Status::IllegalInstruction(code.into(), "bit 12"));
|
||||
}
|
||||
let funct2 = code.extract(5..=6);
|
||||
match funct2 {
|
||||
// C.SUB -> sub \rd', \rd', \rs2'
|
||||
0b00 => Inst::Sub {
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
src2: code.rs2_short(),
|
||||
},
|
||||
// C.XOR -> xor \rd', \rd', \rs2'
|
||||
0b01 => Inst::Xor {
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
src2: code.rs2_short(),
|
||||
},
|
||||
// C.OR -> or \rd', \rd', \rs2'
|
||||
0b10 => Inst::Or {
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
src2: code.rs2_short(),
|
||||
},
|
||||
// C.AND -> and \rd', \rd', \rs2'
|
||||
0b11 => Inst::And {
|
||||
dest: code.rs1_short(),
|
||||
src1: code.rs1_short(),
|
||||
src2: code.rs2_short(),
|
||||
},
|
||||
_ => unreachable!("only two bits"),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("only two bits"),
|
||||
}
|
||||
}
|
||||
// C.J -> jal zero, \offset
|
||||
0b101 => Inst::Jal {
|
||||
offset: code.immediate_s(&[
|
||||
|
|
@ -662,6 +744,17 @@ impl Inst {
|
|||
},
|
||||
// C2
|
||||
0b10 => match code.funct3() {
|
||||
// C.SLLI -> slli \rd, \rd, \imm
|
||||
0b000 => {
|
||||
if code.extract(12..=12) != 0 {
|
||||
return Err(Status::IllegalInstruction(code.into(), "imm"));
|
||||
}
|
||||
Inst::Slli {
|
||||
imm: code.immediate_u(&[(2..=6, 0), (12..=12, 5)]),
|
||||
dest: code.rd(),
|
||||
src1: code.rd(),
|
||||
}
|
||||
}
|
||||
// C.LWSP -> lw \reg \offset(sp)
|
||||
0b010 => {
|
||||
let dest = code.rd();
|
||||
|
|
@ -681,14 +774,23 @@ impl Inst {
|
|||
let rd_rs1 = code.rd();
|
||||
match (bit, rd_rs1.0, rs2.0) {
|
||||
// C.JR -> jalr zero, 0(\rs1)
|
||||
(0, _, 0) if rd_rs1.0 != 0 => Inst::Jalr {
|
||||
offset: 0,
|
||||
base: rd_rs1,
|
||||
dest: Reg::ZERO,
|
||||
(0, _, 0) => {
|
||||
if rd_rs1.0 == 0 {
|
||||
return Err(Status::IllegalInstruction(code.into(), "rs1"));
|
||||
}
|
||||
Inst::Jalr {
|
||||
offset: 0,
|
||||
base: rd_rs1,
|
||||
dest: Reg::ZERO,
|
||||
}
|
||||
}
|
||||
// C.MV -> add \rd, x0, \rs2
|
||||
(0, _, _) => Inst::Add {
|
||||
dest: code.rd(),
|
||||
src1: Reg::ZERO,
|
||||
src2: code.rs2(),
|
||||
},
|
||||
// C.MV
|
||||
(0, _, _) if rd_rs1.0 != 0 && rs2.0 != 0 => todo!(),
|
||||
// C.EBREAK
|
||||
// C.EBREAK -> ebreak
|
||||
(1, 0, 0) => Inst::Ebreak,
|
||||
// C.JALR -> jalr ra, 0(\rs1)
|
||||
(1, _, 0) if rd_rs1.0 != 0 => Inst::Jalr {
|
||||
|
|
@ -696,11 +798,11 @@ impl Inst {
|
|||
base: rd_rs1,
|
||||
dest: Reg::RA,
|
||||
},
|
||||
// C.ADD
|
||||
(1, _, _) if rd_rs1.0 != 0 && rs2.0 != 0 => Inst::Add {
|
||||
dest: todo!(),
|
||||
src1: todo!(),
|
||||
src2: todo!(),
|
||||
// C.ADD -> add \rd, \rd, \rs2
|
||||
(1, _, _) => Inst::Add {
|
||||
dest: rd_rs1,
|
||||
src1: rd_rs1,
|
||||
src2: rs2,
|
||||
},
|
||||
_ => return Err(Status::IllegalInstruction(code.into(), "inst")),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ START_TEST
|
|||
CASE xor 0b101, 0b100, 0b001
|
||||
|
||||
CASE sll, 2, 1, 4
|
||||
CASE sll, 2, 20, 2097152
|
||||
CASE sll, 2, 30, 2147483648
|
||||
CASE sll, 2, 31, 0
|
||||
CASER sll, 2, 32, 2 # error for immediate
|
||||
CASE sll, 0, 10, 0
|
||||
CASE sll, 10, 0, 10
|
||||
CASE sll, -1, 31, -2147483648
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue