mirror of
https://github.com/Noratrieb/rustv32i.git
synced 2026-01-14 13:25:01 +01:00
start c
This commit is contained in:
parent
9ad5785106
commit
dd2e4001fd
5 changed files with 130 additions and 27 deletions
|
|
@ -156,9 +156,6 @@ impl Emulator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_pc(&mut self, pc: u32) -> Result<(), Status> {
|
fn set_pc(&mut self, pc: u32) -> Result<(), Status> {
|
||||||
if pc % 4 != 0 {
|
|
||||||
return Err(Status::UnalignedPc(pc));
|
|
||||||
}
|
|
||||||
self.pc = pc;
|
self.pc = pc;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
146
src/inst.rs
146
src/inst.rs
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::emu::{Status, Reg};
|
use crate::emu::{Reg, Status};
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
|
|
@ -337,7 +337,7 @@ impl Display for AmoOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_extend(value: u32, size: u32) -> u32 {
|
fn sign_extend32(value: u32, size: u32) -> u32 {
|
||||||
assert!(size <= u32::BITS);
|
assert!(size <= u32::BITS);
|
||||||
let sign = value >> (size - 1);
|
let sign = value >> (size - 1);
|
||||||
let imm = if sign == 1 {
|
let imm = if sign == 1 {
|
||||||
|
|
@ -347,6 +347,16 @@ fn sign_extend(value: u32, size: u32) -> u32 {
|
||||||
};
|
};
|
||||||
imm
|
imm
|
||||||
}
|
}
|
||||||
|
fn sign_extend16(value: u16, size: u16) -> u16 {
|
||||||
|
assert!(size <= u16::BITS as u16);
|
||||||
|
let sign = value >> (size - 1);
|
||||||
|
let imm = if sign == 1 {
|
||||||
|
(u16::MAX << size) | value
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
};
|
||||||
|
imm
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct InstCode(u32);
|
pub struct InstCode(u32);
|
||||||
|
|
@ -356,6 +366,26 @@ impl InstCode {
|
||||||
let end_span = 32 - (range.end() + 1);
|
let end_span = 32 - (range.end() + 1);
|
||||||
(self.0 << (end_span)) >> (end_span + range.start())
|
(self.0 << (end_span)) >> (end_span + range.start())
|
||||||
}
|
}
|
||||||
|
fn immediate_u(self, mappings: &[(RangeInclusive<u32>, u32)]) -> u32 {
|
||||||
|
let mut imm = 0;
|
||||||
|
for (from, to) in mappings {
|
||||||
|
let value = self.extract(from.clone());
|
||||||
|
imm |= value << to;
|
||||||
|
}
|
||||||
|
imm
|
||||||
|
}
|
||||||
|
fn immediate_s(self, mappings: &[(RangeInclusive<u32>, u32)]) -> u32 {
|
||||||
|
let mut imm = 0;
|
||||||
|
let mut size = 0;
|
||||||
|
for (from, to) in mappings {
|
||||||
|
let value = self.extract(from.clone());
|
||||||
|
imm |= value << to;
|
||||||
|
let this_size = from.end() - from.start() + 1;
|
||||||
|
size = size.max(*to + this_size);
|
||||||
|
}
|
||||||
|
sign_extend32(imm, size)
|
||||||
|
}
|
||||||
|
|
||||||
fn opcode(self) -> u32 {
|
fn opcode(self) -> u32 {
|
||||||
self.0 & 0b1111111
|
self.0 & 0b1111111
|
||||||
}
|
}
|
||||||
|
|
@ -375,34 +405,19 @@ impl InstCode {
|
||||||
Reg(self.extract(7..=11))
|
Reg(self.extract(7..=11))
|
||||||
}
|
}
|
||||||
fn imm_i(self) -> u32 {
|
fn imm_i(self) -> u32 {
|
||||||
let imm = self.extract(20..=31);
|
self.immediate_s(&[(20..=31, 0)])
|
||||||
sign_extend(imm, 12)
|
|
||||||
}
|
}
|
||||||
fn imm_s(self) -> u32 {
|
fn imm_s(self) -> u32 {
|
||||||
let imm_11_5 = self.extract(25..=31);
|
self.immediate_s(&[(25..=31, 5), (7..=11, 0)])
|
||||||
let imm_4_0 = self.extract(7..=11);
|
|
||||||
let imm = (imm_11_5 << 5) | imm_4_0;
|
|
||||||
sign_extend(imm, 12)
|
|
||||||
}
|
}
|
||||||
fn imm_b(self) -> u32 {
|
fn imm_b(self) -> u32 {
|
||||||
let imm_12 = self.extract(31..=31);
|
self.immediate_s(&[(31..=31, 12), (7..=7, 11), (25..=30, 5), (8..=11, 1)])
|
||||||
let imm_10_5 = self.extract(25..=30);
|
|
||||||
let imm_4_1 = self.extract(8..=11);
|
|
||||||
let imm_11 = self.extract(7..=7);
|
|
||||||
let imm = (imm_12 << 12) | (imm_11 << 11) | (imm_10_5 << 5) | (imm_4_1 << 1);
|
|
||||||
sign_extend(imm, 13) // 13 due to 2-byte immediate offset
|
|
||||||
}
|
}
|
||||||
fn imm_u(self) -> u32 {
|
fn imm_u(self) -> u32 {
|
||||||
let imm_12_31 = self.extract(12..=31);
|
self.immediate_u(&[(12..=31, 12)])
|
||||||
imm_12_31 << 12
|
|
||||||
}
|
}
|
||||||
fn imm_j(self) -> u32 {
|
fn imm_j(self) -> u32 {
|
||||||
let imm_20 = self.extract(31..=31);
|
self.immediate_u(&[(31..=31, 20), (21..=30, 1), (20..=20, 11), (12..=19, 12)])
|
||||||
let imm_10_1 = self.extract(21..=30);
|
|
||||||
let imm_11 = self.extract(20..=20);
|
|
||||||
let imm_19_12 = self.extract(12..=19);
|
|
||||||
let imm = (imm_20 << 19) | (imm_19_12 << 11) | (imm_11 << 10) | imm_10_1;
|
|
||||||
sign_extend(imm, 20) << 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -412,8 +427,95 @@ impl Debug for InstCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct InstCodeC(u16);
|
||||||
|
|
||||||
|
impl InstCodeC {
|
||||||
|
fn extract(self, range: RangeInclusive<u16>) -> u16 {
|
||||||
|
let end_span = 32 - (range.end() + 1);
|
||||||
|
(self.0 << (end_span)) >> (end_span + range.start())
|
||||||
|
}
|
||||||
|
fn immediate_u(self, mappings: &[(RangeInclusive<u16>, u16)]) -> u16 {
|
||||||
|
let mut imm = 0;
|
||||||
|
for (from, to) in mappings {
|
||||||
|
let value = self.extract(from.clone());
|
||||||
|
imm |= value << to;
|
||||||
|
}
|
||||||
|
imm
|
||||||
|
}
|
||||||
|
|
||||||
|
fn immediate_s(self, mappings: &[(RangeInclusive<u16>, u16)]) -> u16 {
|
||||||
|
let mut imm = 0;
|
||||||
|
let mut size = 0;
|
||||||
|
for (from, to) in mappings {
|
||||||
|
let value = self.extract(from.clone());
|
||||||
|
imm |= value << to;
|
||||||
|
let this_size = from.end() - from.start() + 1;
|
||||||
|
size = size.max(*to + this_size);
|
||||||
|
}
|
||||||
|
sign_extend16(imm, size)
|
||||||
|
}
|
||||||
|
fn op(self) -> u16 {
|
||||||
|
self.0 & 0b11
|
||||||
|
}
|
||||||
|
fn funct3(self) -> u16 {
|
||||||
|
self.extract(13..=15)
|
||||||
|
}
|
||||||
|
fn rd(self) -> Reg {
|
||||||
|
Reg(self.extract(7..=11) as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InstCodeC> for InstCode {
|
||||||
|
fn from(value: InstCodeC) -> Self {
|
||||||
|
Self(value.0 as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Inst {
|
impl Inst {
|
||||||
pub fn decode(code: u32) -> Result<Inst, Status> {
|
pub fn decode(code: u32) -> Result<Inst, Status> {
|
||||||
|
let is_compressed = (code & 0b11) != 0b11;
|
||||||
|
if is_compressed {
|
||||||
|
Self::decode_compressed(code as u16)
|
||||||
|
} else {
|
||||||
|
Self::decode_normal(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_compressed(code: u16) -> Result<Inst, Status> {
|
||||||
|
let code = InstCodeC(code);
|
||||||
|
|
||||||
|
let inst = match code.op() {
|
||||||
|
// C0
|
||||||
|
0b00 => todo!(),
|
||||||
|
// C1
|
||||||
|
0b01 => todo!(),
|
||||||
|
// C2
|
||||||
|
0b10 => {
|
||||||
|
match code.funct3() {
|
||||||
|
// C.LDSP
|
||||||
|
010 => {
|
||||||
|
let dest = code.rd();
|
||||||
|
if dest.0 == 0 {
|
||||||
|
return Err(Status::IllegalInstruction(code.into(), "rd"));
|
||||||
|
}
|
||||||
|
let imm = code.immediate_s(&[(12..=12, 5), (4..=6, 2), (2..=3, 6)]);
|
||||||
|
|
||||||
|
Inst::Lw {
|
||||||
|
offset: imm as u32,
|
||||||
|
dest,
|
||||||
|
base: Reg::SP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(Status::IllegalInstruction(code.into(), "funct3")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(Status::IllegalInstruction(code.into(), "op")),
|
||||||
|
};
|
||||||
|
Ok(inst)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_normal(code: u32) -> Result<Inst, Status> {
|
||||||
let code = InstCode(code);
|
let code = InstCode(code);
|
||||||
let inst = match code.opcode() {
|
let inst = match code.opcode() {
|
||||||
// LUI
|
// LUI
|
||||||
|
|
|
||||||
|
|
@ -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 riscv32im-unknown-none-elf
|
RUSTC = rustc --target riscv32imac-unknown-none-elf
|
||||||
|
|
||||||
all: init init1
|
all: init init1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,9 +93,14 @@ fn input() -> u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn x(a: i32) {}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn _start() -> ! {
|
fn _start() -> ! {
|
||||||
|
x(0);
|
||||||
|
x(0);
|
||||||
|
exit(0);
|
||||||
let random_number = 45;
|
let random_number = 45;
|
||||||
|
|
||||||
let num = core::sync::atomic::AtomicI32::new(0);
|
let num = core::sync::atomic::AtomicI32::new(0);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
.macro CASE_BOTH inst insti a b expected
|
.macro CASE_BOTH inst insti a b expected
|
||||||
CASER \inst, \a, \b, \expected
|
CASER \inst, \a, \b, \expected
|
||||||
|
|
||||||
CASE_IMM \insti, \a, \b, \expected
|
CASE_IMM \insti, \a, \b, \expected
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue