mirror of
https://github.com/Noratrieb/rustv32i.git
synced 2026-01-14 13:25:01 +01:00
mul
This commit is contained in:
parent
ab8e4ebc13
commit
42c4d826f1
4 changed files with 135 additions and 10 deletions
13
README.md
Normal file
13
README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# rustv32i
|
||||||
|
|
||||||
|
A small RISC-V emulator written in Rust.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- [ ] Base RV32I instruction set
|
||||||
|
- missing fence and pause
|
||||||
|
- [x] M standard extension
|
||||||
|
- [ ] A standard extension
|
||||||
|
- [ ] F standard extension
|
||||||
|
- [ ] D standard extension
|
||||||
|
- [ ] C standard extension
|
||||||
71
src/emu.rs
71
src/emu.rs
|
|
@ -183,6 +183,16 @@ enum Inst {
|
||||||
|
|
||||||
Ecall,
|
Ecall,
|
||||||
Ebreak,
|
Ebreak,
|
||||||
|
|
||||||
|
// M
|
||||||
|
Mul { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Mulh { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Mulhsu { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Mulhu { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Div { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Divu { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Rem { dest: Reg, src1: Reg, src2: Reg },
|
||||||
|
Remu { dest: Reg, src1: Reg, src2: Reg },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Inst {
|
impl Debug for Inst {
|
||||||
|
|
@ -288,6 +298,14 @@ impl Display for Inst {
|
||||||
Inst::And { dest, src1, src2 } => write!(f, "and {dest}, {src1}, {src2}"),
|
Inst::And { dest, src1, src2 } => write!(f, "and {dest}, {src1}, {src2}"),
|
||||||
Inst::Ecall => write!(f, "ecall"),
|
Inst::Ecall => write!(f, "ecall"),
|
||||||
Inst::Ebreak => write!(f, "ebreak"),
|
Inst::Ebreak => write!(f, "ebreak"),
|
||||||
|
Inst::Mul { dest, src1, src2 } => write!(f, "mul {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Mulh { dest, src1, src2 } => write!(f, "mulh {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Mulhsu { dest, src1, src2 } => write!(f, "mulhsu {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Mulhu { dest, src1, src2 } => write!(f, "mulhu {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Div { dest, src1, src2 } => write!(f, "div {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Divu { dest, src1, src2 } => write!(f, "divu {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Rem { dest, src1, src2 } => write!(f, "rem {dest}, {src1}, {src2}"),
|
||||||
|
Inst::Remu { dest, src1, src2 } => write!(f, "remu {dest}, {src1}, {src2}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -542,6 +560,15 @@ impl Inst {
|
||||||
(0b101, 0b0100000) => Inst::Sra { dest, src1, src2 },
|
(0b101, 0b0100000) => Inst::Sra { dest, src1, src2 },
|
||||||
(0b110, 0b0000000) => Inst::Or { dest, src1, src2 },
|
(0b110, 0b0000000) => Inst::Or { dest, src1, src2 },
|
||||||
(0b111, 0b0000000) => Inst::And { dest, src1, src2 },
|
(0b111, 0b0000000) => Inst::And { dest, src1, src2 },
|
||||||
|
|
||||||
|
(0b000, 0b0000001) => Inst::Mul { dest, src1, src2 },
|
||||||
|
(0b001, 0b0000001) => Inst::Mulh { dest, src1, src2 },
|
||||||
|
(0b010, 0b0000001) => Inst::Mulhsu { dest, src1, src2 },
|
||||||
|
(0b011, 0b0000001) => Inst::Mulhu { dest, src1, src2 },
|
||||||
|
(0b100, 0b0000001) => Inst::Div { dest, src1, src2 },
|
||||||
|
(0b101, 0b0000001) => Inst::Divu { dest, src1, src2 },
|
||||||
|
(0b110, 0b0000001) => Inst::Rem { dest, src1, src2 },
|
||||||
|
(0b111, 0b0000001) => Inst::Remu { dest, src1, src2 },
|
||||||
_ => return Err(Error::IllegalInstruction(code, "funct3/funct7")),
|
_ => return Err(Error::IllegalInstruction(code, "funct3/funct7")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -751,6 +778,50 @@ impl Emulator {
|
||||||
(self.ecall_handler)(&mut self.mem, &mut self.xreg)?;
|
(self.ecall_handler)(&mut self.mem, &mut self.xreg)?;
|
||||||
}
|
}
|
||||||
Inst::Ebreak => return Err(Error::Ebreak),
|
Inst::Ebreak => return Err(Error::Ebreak),
|
||||||
|
Inst::Mul { dest, src1, src2 } => {
|
||||||
|
self[dest] = ((self[src1] as i32).wrapping_mul(self[src2] as i32)) as u32;
|
||||||
|
}
|
||||||
|
Inst::Mulh { dest, src1, src2 } => {
|
||||||
|
let shifted = ((self[src1] as i64).wrapping_mul(self[src2] as i64) as i64) >> 32;
|
||||||
|
self[dest] = shifted as u32;
|
||||||
|
}
|
||||||
|
Inst::Mulhsu { .. } => todo!("mulhsu"),
|
||||||
|
Inst::Mulhu { dest, src1, src2 } => {
|
||||||
|
let shifted = ((self[src1] as u64).wrapping_mul(self[src2] as u64) as u64) >> 32;
|
||||||
|
self[dest] = shifted as u32;
|
||||||
|
}
|
||||||
|
Inst::Div { dest, src1, src2 } => {
|
||||||
|
if self[src2] == 0 {
|
||||||
|
self[dest] = u32::MAX;
|
||||||
|
} else if self[src2] == u32::MAX {
|
||||||
|
self[dest] = u32::MAX;
|
||||||
|
} else {
|
||||||
|
self[dest] = ((self[src1] as i32) / (self[src2] as i32)) as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Inst::Divu { dest, src1, src2 } => {
|
||||||
|
if self[src2] == 0 {
|
||||||
|
self[dest] = 2_u32.pow(32) - 1;
|
||||||
|
} else {
|
||||||
|
self[dest] = self[src1] / self[src2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Inst::Rem { dest, src1, src2 } => {
|
||||||
|
if self[src2] == 0 {
|
||||||
|
self[dest] = self[src1];
|
||||||
|
} else if self[src2] == u32::MAX {
|
||||||
|
self[dest] = 0;
|
||||||
|
} else {
|
||||||
|
self[dest] = ((self[src1] as i32) % (self[src2] as i32)) as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Inst::Remu { dest, src1, src2 } => {
|
||||||
|
if self[src2] == 0 {
|
||||||
|
self[dest] = 2_u32.pow(32) - 1;
|
||||||
|
} else {
|
||||||
|
self[dest] = self[src1] % self[src2];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !jumped {
|
if !jumped {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
CC = clang -Wall -Wpedantic -target riscv32-unknown-linux-gnu -fuse-ld=lld -march=rv32i
|
CC = clang -Wall -Wpedantic -target riscv32-unknown-linux-gnu -fuse-ld=lld -march=rv32i
|
||||||
CC_STATIC = $(CC) -static -nostdlib -nodefaultlibs
|
CC_STATIC = $(CC) -static -nostdlib -nodefaultlibs
|
||||||
|
|
||||||
RUSTC = rustc --target riscv32i-unknown-none-elf
|
RUSTC = rustc --target riscv32im-unknown-none-elf
|
||||||
|
|
||||||
all: init init1
|
all: init init1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,23 @@ struct Stderr;
|
||||||
impl core::fmt::Write for Stderr {
|
impl core::fmt::Write for Stderr {
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
let ret = write(2, s.as_bytes());
|
let ret = write(2, s.as_bytes());
|
||||||
if ret < 0 { Err(core::fmt::Error) } else { Ok(()) }
|
if ret < 0 {
|
||||||
|
Err(core::fmt::Error)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! eprintln {
|
||||||
|
($($tt:tt)*) => {
|
||||||
|
writeln!(Stderr, $($tt)*).unwrap();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
macro_rules! eprint {
|
||||||
|
($($tt:tt)*) => {
|
||||||
|
write!(Stderr, $($tt)*).unwrap();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
|
|
@ -61,13 +76,39 @@ fn handle(info: &core::panic::PanicInfo<'_>) -> ! {
|
||||||
unsafe { core::arch::asm!("unimp", options(noreturn)) }
|
unsafe { core::arch::asm!("unimp", options(noreturn)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
fn input() -> u64 {
|
||||||
fn _start() {
|
eprint!("enter a number: ");
|
||||||
write(1, b"enter a number: ");
|
|
||||||
|
loop {
|
||||||
let mut buf = [0; 10];
|
let mut buf = [0; 10];
|
||||||
let len = read(0, &mut buf);
|
let len = read(0, &mut buf);
|
||||||
let buf = &buf[..(len as usize)];
|
let buf = &buf[..(len as usize)];
|
||||||
let n = str::from_utf8(buf).unwrap().trim().parse::<i32>().unwrap();
|
let n = str::from_utf8(buf).unwrap().trim();
|
||||||
|
match n.parse::<u64>() {
|
||||||
exit(n);
|
Ok(v) => return v,
|
||||||
|
Err(_) => {
|
||||||
|
eprint!("not a valid number, try again: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn _start() -> ! {
|
||||||
|
let random_number = 45;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let n = input();
|
||||||
|
if n == random_number {
|
||||||
|
eprintln!("correct!");
|
||||||
|
break;
|
||||||
|
} else if n < random_number {
|
||||||
|
eprintln!("random number is greater");
|
||||||
|
} else {
|
||||||
|
eprintln!("random number is smaller");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue