aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2016-01-14 10:35:40 -0700
committerDavid Li <li.davidm96@gmail.com>2016-01-14 10:35:40 -0700
commit59ae270a4fa286e72f7deef08dcd044828eefe63 (patch)
tree91b6fabdf4e477a5437cf32e5f2d6d1114007ad2
parent36b21d7691bb452a68d857a71c16b9f922b047a2 (diff)
Convert ISA types to newtype structs
-rw-r--r--src/binary.rs94
-rw-r--r--src/isa/mod.rs208
-rw-r--r--src/lib.rs4
-rw-r--r--src/memory.rs68
-rw-r--r--src/register_file.rs2
-rw-r--r--src/simulator.rs87
6 files changed, 261 insertions, 202 deletions
diff --git a/src/binary.rs b/src/binary.rs
deleted file mode 100644
index 3847e53..0000000
--- a/src/binary.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015-2016 David Li
-// This file is part of rustv.
-
-// rustv is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// rustv is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with rustv. If not, see <http://www.gnu.org/licenses/>.
-
-use std::error::Error;
-use std::fmt;
-use std::fs::File;
-use std::io::{self, BufRead};
-use std::num;
-use std::path::Path;
-use std::str;
-
-/// Representation of a binary
-pub struct Binary {
- pub words: Vec<u32>,
-}
-
-#[derive(Debug)]
-pub enum BinaryError {
- Io(io::Error),
- Utf8(str::Utf8Error),
- ParseInt(num::ParseIntError),
-}
-
-impl fmt::Display for BinaryError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- BinaryError::Io(ref err) => err.fmt(f),
- BinaryError::Utf8(ref err) => err.fmt(f),
- BinaryError::ParseInt(ref err) => err.fmt(f),
- }
- }
-}
-
-impl Error for BinaryError {
- fn description(&self) -> &str {
- match *self {
- BinaryError::Io(ref err) => err.description(),
- BinaryError::Utf8(ref err) => err.description(),
- BinaryError::ParseInt(ref err) => err.description(),
- }
- }
-}
-
-impl From<io::Error> for BinaryError {
- fn from(err: io::Error) -> BinaryError {
- BinaryError::Io(err)
- }
-}
-
-impl From<str::Utf8Error> for BinaryError {
- fn from(err: str::Utf8Error) -> BinaryError {
- BinaryError::Utf8(err)
- }
-}
-
-impl From<num::ParseIntError> for BinaryError {
- fn from(err: num::ParseIntError) -> BinaryError {
- BinaryError::ParseInt(err)
- }
-}
-
-impl Binary {
- /// Load a binary from a hex file (generated with elf2hex)
- pub fn new_from_hex_file(path: &Path) -> Result<Binary, BinaryError> {
- let file = try!(File::open(path));
- let file = io::BufReader::new(file);
-
- let mut words: Vec<u32> = Vec::new();
- for line in file.lines() {
- let line = try!(line);
- for bytes in line.as_bytes().chunks(8).rev() {
- let word = try!(str::from_utf8(bytes));
- words.push(try!(u32::from_str_radix(word, 16)));
- }
- }
-
- Ok(Binary {
- words: words,
- })
- }
-}
diff --git a/src/isa/mod.rs b/src/isa/mod.rs
index 2c20d05..d5a5c14 100644
--- a/src/isa/mod.rs
+++ b/src/isa/mod.rs
@@ -14,18 +14,178 @@
// You should have received a copy of the GNU General Public License
// along with rustv. If not, see <http://www.gnu.org/licenses/>.
+use std::fmt;
+use std::ops;
+
pub mod opcodes;
pub mod funct3;
pub mod funct7;
-pub type Word = u32;
-pub type SignedWord = i32;
-pub type HalfWord = u16;
-pub type SignedHalfWord = i16;
-pub type Byte = u8;
-pub type SignedByte = i8;
+macro_rules! isa_type_op {
+ ($name: ident, $ty: ty, $op: ident, $op_name: ident) => {
+ impl ops::$op<$name> for $name {
+ type Output = $name;
+
+ fn $op_name(self, _rhs: $name) -> $name {
+ $name(ops::$op::$op_name(self.0, _rhs.0))
+ }
+ }
+
+ impl ops::$op<$ty> for $name {
+ type Output = $name;
+
+ fn $op_name(self, _rhs: $ty) -> $name {
+ $name(ops::$op::$op_name(self.0, _rhs))
+ }
+ }
+ }
+}
+
+macro_rules! isa_type_assign_op {
+ ($name: ident, $ty: ty, $op: ident, $op_name: ident) => {
+ impl ops::$op<$name> for $name {
+ fn $op_name(&mut self, _rhs: $name) {
+ ops::$op::$op_name(&mut self.0, _rhs.0)
+ }
+ }
+
+ impl ops::$op<$ty> for $name {
+ fn $op_name(&mut self, _rhs: $ty) {
+ ops::$op::$op_name(&mut self.0, _rhs)
+ }
+ }
+ }
+}
+
+macro_rules! isa_type {
+ ($name: ident, $utype: ty) => {
+ #[derive(Clone,Copy,Debug,Eq,Ord,PartialEq,PartialOrd)]
+ pub struct $name(pub $utype);
+
+ impl $name {
+ pub fn wrapping_add(self, rhs: Self) -> Self {
+ $name(self.0.wrapping_add(rhs.0))
+ }
+
+ pub fn wrapping_sub(self, rhs: Self) -> Self {
+ $name(self.0.wrapping_sub(rhs.0))
+ }
+
+ }
+
+ isa_type_op!($name, $utype, Add, add);
+ isa_type_assign_op!($name, $utype, AddAssign, add_assign);
+ isa_type_op!($name, $utype, Sub, sub);
+ isa_type_op!($name, $utype, Mul, mul);
+ isa_type_op!($name, $utype, Div, div);
+ isa_type_op!($name, $utype, Rem, rem);
+ isa_type_op!($name, $utype, Shr, shr);
+ isa_type_op!($name, $utype, Shl, shl);
+ isa_type_op!($name, $utype, BitAnd, bitand);
+ isa_type_op!($name, $utype, BitOr, bitor);
+ isa_type_op!($name, $utype, BitXor, bitxor);
+
+ impl fmt::LowerHex for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ write!(f, "{:x}", self.0)
+ }
+ }
+
+ impl fmt::UpperHex for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ write!(f, "{:X}", self.0)
+ }
+ }
+ }
+}
+
+pub trait IsaType {
+ type Unsigned;
+ type Signed;
+
+ fn as_signed(self) -> Self::Signed;
+ fn as_signed_word(self) -> SignedWord;
+ fn as_word(self) -> Word;
+ fn as_half_word(self) -> HalfWord;
+ fn as_byte(self) -> Byte;
+ fn as_address(self) -> Address;
+}
+
+macro_rules! isa_utype {
+ ($name: ident, $signed: ident, $utype: ty, $stype: ty) => {
+ impl IsaType for $name {
+ type Unsigned = $name;
+ type Signed = $signed;
+
+ fn as_signed(self) -> Self::Signed {
+ $signed(self.0 as $stype)
+ }
+
+ fn as_signed_word(self) -> SignedWord {
+ // Convert self to signed so that second cast will
+ // sign-extend
+ SignedWord((self.0 as $stype) as i32)
+ }
+
+ fn as_word(self) -> Word {
+ Word(self.0 as u32)
+ }
+
+ fn as_half_word(self) -> HalfWord {
+ HalfWord(self.0 as u16)
+ }
+
+ fn as_byte(self) -> Byte {
+ Byte(self.0 as u8)
+ }
+
+ fn as_address(self) -> Address {
+ self.as_word()
+ }
+ }
+
+ impl IsaType for $signed {
+ type Unsigned = $name;
+ type Signed = $signed;
+
+ fn as_signed(self) -> Self::Signed {
+ self
+ }
+
+ fn as_signed_word(self) -> SignedWord {
+ SignedWord(self.0 as i32)
+ }
+
+ fn as_word(self) -> Word {
+ Word(self.0 as u32)
+ }
+
+ fn as_half_word(self) -> HalfWord {
+ HalfWord(self.0 as u16)
+ }
+
+ fn as_byte(self) -> Byte {
+ Byte(self.0 as u8)
+ }
+
+ fn as_address(self) -> Address {
+ self.as_word()
+ }
+ }
+ }
+}
+
+isa_type!(Word, u32);
+isa_type!(SignedWord, i32);
+isa_utype!(Word, SignedWord, u32, i32);
+isa_type!(HalfWord, u16);
+isa_type!(SignedHalfWord, i16);
+isa_utype!(HalfWord, SignedHalfWord, u16, i16);
+isa_type!(Byte, u8);
+isa_type!(SignedByte, i8);
+isa_utype!(Byte, SignedByte, u8, i8);
-pub type Address = u32;
+pub type Address = Word;
#[derive(Debug, PartialEq)]
pub enum Register {
@@ -111,52 +271,52 @@ impl Register {
pub struct Instruction {
// TODO: rename word to something correct - instructions are not always a
// word
- word: u32,
+ word: Word,
}
impl Instruction {
- pub fn new(word: u32) -> Instruction {
+ pub fn new(word: Word) -> Instruction {
Instruction {
word: word,
}
}
pub fn opcode(&self) -> u32 {
- self.word & 0x7F
+ (self.word & 0x7F).0
}
pub fn rd(&self) -> Register {
- Register::from_num((self.word >> 7) & 0x1F)
+ Register::from_num(((self.word >> 7) & 0x1F).0)
}
pub fn funct3(&self) -> u32 {
- (self.word >> 12) & 0x7
+ ((self.word >> 12) & 0x7).0
}
pub fn funct7(&self) -> u32 {
- (self.word >> 25) & 0x7F
+ ((self.word >> 25) & 0x7F).0
}
pub fn shamt(&self) -> u32 {
- (self.word >> 20) & 0x1F
+ ((self.word >> 20) & 0x1F).0
}
pub fn rs1(&self) -> Register {
- Register::from_num((self.word >> 15) & 0x1F)
+ Register::from_num(((self.word >> 15) & 0x1F).0)
}
pub fn rs2(&self) -> Register {
- Register::from_num((self.word >> 20) & 0x1F)
+ Register::from_num(((self.word >> 20) & 0x1F).0)
}
pub fn i_imm(&self) -> SignedWord {
- (self.word as SignedWord) >> 20
+ (self.word.as_signed_word()) >> 20
}
pub fn s_imm(&self) -> SignedWord {
let low = (self.word >> 7) & 0x1F;
- let high = ((self.word as SignedWord) >> 25) as Word;
- ((high << 5) | low) as SignedWord
+ let high = ((self.word.as_signed_word()) >> 25).as_word();
+ ((high << 5) | low).as_signed_word()
}
pub fn uj_imm(&self) -> SignedWord {
@@ -165,19 +325,19 @@ impl Instruction {
let low11 = (self.word >> 20) & 0x1;
let low12 = (self.word >> 12) & 0xFF;
// Want sign-extension
- let low20 = ((self.word as SignedWord) >> 30) as Word;
- ((low20 << 20) | (low12 << 12) | (low11 << 11) | (low1 << 1)) as SignedWord
+ let low20 = ((self.word.as_signed_word()) >> 30).as_word();
+ ((low20 << 20) | (low12 << 12) | (low11 << 11) | (low1 << 1)).as_signed_word()
}
pub fn sb_imm(&self) -> SignedWord {
let low1 = (self.word >> 8) & 0xF;
let low5 = (self.word >> 25) & 0x3F;
let low11 = (self.word >> 7) & 0x1;
- let low12 = ((self.word as SignedWord) >> 31) as Word;
- ((low12 << 12) | (low11 << 11) | (low5 << 5) | (low1 << 1)) as SignedWord
+ let low12 = ((self.word.as_signed_word()) >> 31).as_word();
+ ((low12 << 12) | (low11 << 11) | (low5 << 5) | (low1 << 1)).as_signed_word()
}
pub fn u_imm(&self) -> SignedWord {
- (self.word & 0xFFFFF000) as SignedWord
+ (self.word & 0xFFFFF000).as_signed_word()
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 0b52b08..2188c07 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -14,11 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with rustv. If not, see <http://www.gnu.org/licenses/>.
-#![feature(braced_empty_structs, step_by)]
+#![feature(augmented_assignments, braced_empty_structs,
+ op_assign_traits, step_by)]
extern crate elfloader32 as elfloader_lib;
pub mod isa;
-pub mod binary;
pub mod memory;
pub mod register_file;
pub mod simulator;
diff --git a/src/memory.rs b/src/memory.rs
index 83f53af..097519f 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -17,8 +17,7 @@
use std::rc::Rc;
use std::cell::RefCell;
-use isa::{self, Instruction};
-use binary::{Binary};
+use isa::{self, Instruction, IsaType};
#[derive(Clone, Debug, PartialEq)]
pub enum MemoryError {
@@ -54,12 +53,12 @@ pub trait MemoryInterface {
fn read_halfword(&mut self, address: isa::Address) -> Result<isa::HalfWord> {
let result = self.read_word(address);
- let offset = address & 0b10;
+ let offset = (address & 0b10).0;
match result {
Ok(word) => match offset {
- 0 => Ok((word & 0xFFFF) as isa::HalfWord),
- 2 => Ok(((word & 0xFFFF0000) >> 16) as isa::HalfWord),
+ 0 => Ok((word & 0xFFFF).as_half_word()),
+ 2 => Ok(((word & 0xFFFF0000) >> 16).as_half_word()),
_ => panic!("Invalid halfword offset: address {:x}", address),
},
Err(e) => Err(e),
@@ -68,8 +67,8 @@ pub trait MemoryInterface {
fn write_halfword(&mut self, address: isa::Address, value: isa::HalfWord) -> Result<()> {
let result = self.read_word(address);
- let offset = address & 0b10;
- let value = value as isa::Word;
+ let offset = (address & 0b10).0;
+ let value = value.as_word();
match result {
Ok(word) => {
@@ -86,14 +85,14 @@ pub trait MemoryInterface {
fn read_byte(&mut self, address: isa::Address) -> Result<isa::Byte> {
let result = self.read_word(address);
- let offset = address % 4;
+ let offset = (address % 4).0;
match result {
Ok(word) => match offset {
- 0 => Ok((word & 0xFF) as isa::Byte),
- 1 => Ok(((word & 0xFF00) >> 8) as isa::Byte),
- 2 => Ok(((word & 0xFF0000) >> 16) as isa::Byte),
- 3 => Ok(((word & 0xFF000000) >> 24) as isa::Byte),
+ 0 => Ok((word & 0xFF).as_byte()),
+ 1 => Ok(((word & 0xFF00) >> 8).as_byte()),
+ 2 => Ok(((word & 0xFF0000) >> 16).as_byte()),
+ 3 => Ok(((word & 0xFF000000) >> 24).as_byte()),
_ => panic!("Invalid byte offset: {:x}", address),
},
Err(e) => Err(e),
@@ -102,8 +101,8 @@ pub trait MemoryInterface {
fn write_byte(&mut self, address: isa::Address, value: isa::Byte) -> Result<()> {
let result = self.read_word(address);
- let offset = address % 4;
- let value = value as isa::Word;
+ let offset = (address % 4).0;
+ let value = value.as_word();
match result {
Ok(word) => {
@@ -169,7 +168,7 @@ struct FetchRequest {
prefetch: bool, // is this a prefetch
cycles_left: u32,
tag: u32,
- data: Vec<u32>, // hold data temporarily while we wait for an entire line
+ data: Vec<isa::Word>, // hold data temporarily while we wait for an entire line
error: Option<MemoryError>, // in case next level returns an error
waiting_on: u32, // which word of the block are we waiting on
}
@@ -178,7 +177,7 @@ struct FetchRequest {
struct CacheBlock {
valid: bool,
tag: u32,
- contents: Vec<u32>,
+ contents: Vec<isa::Word>,
fetch_request: Option<FetchRequest>,
}
@@ -214,27 +213,16 @@ fn copy_u8_into_u32<T: Mmu>(mmu: &T, base: usize, src: &[u8], dst: &mut [u32]) {
word[0] as u32
};
- let addr = mmu.translate((base as isa::Address) + ((4 * offset) as isa::Address)) / 4;
- dst[addr as usize] = word;
+ let addr = isa::Word((base as u32) + ((4 * offset) as u32));
+ let addr = mmu.translate(addr) / 4;
+ dst[addr.0 as usize] = word;
}
}
impl Memory {
pub fn new(size: isa::Address) -> Memory {
Memory {
- memory: vec![0; size as usize],
- }
- }
-
- pub fn new_from_binary(size: isa::Address, binary: Binary) -> Memory {
- let mut memory = binary.words.clone();
- let size = size as usize;
- if size > memory.len() {
- let remainder = size - memory.len();
- memory.reserve(remainder);
- }
- Memory {
- memory: memory,
+ memory: vec![0; size.0 as usize],
}
}
@@ -252,31 +240,33 @@ impl MemoryInterface for Memory {
fn step(&mut self) {}
fn is_address_accessible(&self, address: isa::Address) -> bool {
- ((address / 4) as usize) < self.memory.len()
+ ((address / 4).0 as usize) < self.memory.len()
}
fn read_word(&mut self, address: isa::Address) -> Result<isa::Word> {
// memory is word-addressed but addresses are byte-addressed
- self.memory.get((address / 4) as usize)
+ self.memory.get((address / 4).0 as usize)
.map(Clone::clone)
+ .map(isa::Word)
.ok_or(MemoryError::InvalidAddress)
}
fn write_word(&mut self, address: isa::Address, value: isa::Word)
-> Result<()> {
- let address = (address / 4) as usize;
+ let address = (address / 4).0 as usize;
if address >= self.memory.len() || address <= 0 {
Err(MemoryError::InvalidAddress)
}
else {
- self.memory[address] = value;
+ self.memory[address] = value.0;
Ok(())
}
}
fn read_instruction(&mut self, pc: isa::Address) -> Option<Instruction> {
- self.memory.get((pc / 4) as usize)
+ self.memory.get((pc / 4).0 as usize)
.map(Clone::clone)
+ .map(isa::Word)
.map(Instruction::new)
}
}
@@ -287,7 +277,7 @@ impl<'a> DirectMappedCache<'a> {
let set = CacheBlock {
valid: false,
tag: 0,
- contents: vec![0; block_words as usize],
+ contents: vec![isa::Word(0); block_words as usize],
fetch_request: None,
};
DirectMappedCache {
@@ -308,7 +298,7 @@ impl<'a> DirectMappedCache<'a> {
let tag_shift = index_shift + (32 - self.num_sets.leading_zeros()) - 1;
let tag = address >> tag_shift;
- (tag, index, offset)
+ (tag.0, index.0, offset.0)
}
fn normalize_address(&self, address: isa::Address) -> isa::Address {
@@ -389,7 +379,7 @@ impl<'a> MemoryInterface for DirectMappedCache<'a> {
prefetch: false,
cycles_left: stall,
tag: new_tag,
- data: vec![0; self.block_words as usize],
+ data: vec![isa::Word(0); self.block_words as usize],
error: None,
waiting_on: 0,
});
diff --git a/src/register_file.rs b/src/register_file.rs
index 6437eed..0f6f6a4 100644
--- a/src/register_file.rs
+++ b/src/register_file.rs
@@ -23,7 +23,7 @@ pub struct RegisterFile {
impl RegisterFile {
pub fn new() -> RegisterFile {
RegisterFile {
- registers: [0; 32],
+ registers: [isa::Word(0); 32],
}
}
diff --git a/src/simulator.rs b/src/simulator.rs
index d625347..63b5eec 100644
--- a/src/simulator.rs
+++ b/src/simulator.rs
@@ -15,6 +15,7 @@
// along with rustv. If not, see <http://www.gnu.org/licenses/>.
use isa;
+use isa::IsaType;
use memory::{MemoryInterface, MemoryError, Mmu, SharedMemory};
use register_file::RegisterFile;
use syscall::SyscallHandler;
@@ -75,19 +76,19 @@ impl<'a> Core<'a> {
match inst.opcode() {
isa::opcodes::LUI => {
- self.registers.write_word(inst.rd(), inst.u_imm() as isa::Word)
+ self.registers.write_word(inst.rd(), inst.u_imm().as_word())
},
isa::opcodes::AUIPC => {
- let result = (pc as isa::SignedWord) + inst.u_imm();
- self.registers.write_word(inst.rd(), result as isa::Word);
+ let result = (pc.as_signed_word()) + inst.u_imm();
+ self.registers.write_word(inst.rd(), result.as_word());
},
isa::opcodes::JALR => {
// TODO: assert funct3 is 0
let base = self.registers.read_word(inst.rs1())
- as isa::SignedWord;
- let target = (base + inst.i_imm()) as isa::Address;
- let retval = (pc + 4) as isa::Word;
- if target == 0x0 {
+ .as_signed_word();
+ let target = (base + inst.i_imm()).as_address();
+ let retval = (pc + 4).as_word();
+ if target == isa::Word(0x0) {
// ret
self.running = false;
}
@@ -98,21 +99,21 @@ impl<'a> Core<'a> {
}
},
isa::opcodes::JAL => {
- let target = ((pc as isa::SignedWord) + inst.uj_imm()) as isa::Address;
- self.registers.write_word(inst.rd(), (pc + 4) as isa::Word);
+ let target = ((pc.as_signed_word()) + inst.uj_imm()).as_address();
+ self.registers.write_word(inst.rd(), (pc + 4).as_word());
self.pc = target;
// panic!("JAL to {:X} 0x{:X}", pc, target);
return;
}
isa::opcodes::BRANCH => {
- let target = ((pc as isa::SignedWord) + inst.sb_imm()) as isa::Address;
+ let target = ((pc.as_signed_word()) + inst.sb_imm()).as_address();
let rs1 = self.registers.read_word(inst.rs1());
let rs2 = self.registers.read_word(inst.rs2());
if match inst.funct3() {
isa::funct3::BEQ => rs1 == rs2,
isa::funct3::BNE => rs1 != rs2,
- isa::funct3::BLT => (rs1 as isa::SignedWord) < (rs2 as isa::SignedWord),
- isa::funct3::BGE => (rs1 as isa::SignedWord) >= (rs2 as isa::SignedWord),
+ isa::funct3::BLT => (rs1.as_signed_word()) < (rs2.as_signed_word()),
+ isa::funct3::BGE => (rs1.as_signed_word()) >= (rs2.as_signed_word()),
isa::funct3::BLTU => rs1 < rs2,
isa::funct3::BGEU => rs1 >= rs2,
_ => {
@@ -129,37 +130,37 @@ impl<'a> Core<'a> {
},
isa::opcodes::INTEGER_IMMEDIATE => {
let imm = inst.i_imm();
- let src = self.registers.read_word(inst.rs1()) as isa::SignedWord;
+ let src = self.registers.read_word(inst.rs1()).as_signed_word();
if let Some(value) = match inst.funct3() {
isa::funct3::ADDI => {
- Some(src.wrapping_add(imm) as isa::Word)
+ Some(src.wrapping_add(imm).as_word())
},
isa::funct3::SLLI => {
- Some((src << inst.shamt()) as isa::Word)
+ Some((src.as_word() << inst.shamt()))
},
isa::funct3::SLTI => {
if src < imm {
- Some(1)
+ Some(isa::Word(1))
}
else {
- Some(0)
+ Some(isa::Word(0))
}
},
isa::funct3::SLTIU => {
- if (src as isa::Word) < (imm as isa::Word) {
- Some(1)
+ if (src.as_word()) < (imm.as_word()) {
+ Some(isa::Word(1))
}
else {
- Some(0)
+ Some(isa::Word(0))
}
},
isa::funct3::XORI => {
- Some((src ^ imm) as isa::Word)
+ Some((src ^ imm).as_word())
},
isa::funct3::SRLI_SRAI => {
match inst.funct7() {
- isa::funct7::SRLI => Some(((src as isa::Word) >> inst.shamt()) as isa::Word),
- isa::funct7::SRAI => Some((src >> inst.shamt()) as isa::Word),
+ isa::funct7::SRLI => Some(((src.as_word()) >> inst.shamt()).as_word()),
+ isa::funct7::SRAI => Some((src >> inst.shamt() as i32).as_word()),
_ => {
self.trap(Trap::IllegalInstruction {
address: pc,
@@ -170,10 +171,10 @@ impl<'a> Core<'a> {
}
},
isa::funct3::ORI => {
- Some((src | imm) as isa::Word)
+ Some((src | imm).as_word())
},
isa::funct3::ANDI => {
- Some((src & imm) as isa::Word)
+ Some((src & imm).as_word())
},
_ => {
self.trap(Trap::IllegalInstruction {
@@ -193,8 +194,8 @@ impl<'a> Core<'a> {
if let Some(value) = match inst.funct3() {
isa::funct3::ADD_SUB => {
match inst.funct7() {
- isa::funct7::ADD_SRL => Some(((src1 as isa::SignedWord).wrapping_add(src2 as isa::SignedWord)) as isa::Word),
- isa::funct7::SUB_SRA => Some(((src1 as isa::SignedWord).wrapping_sub(src2 as isa::SignedWord)) as isa::Word),
+ isa::funct7::ADD_SRL => Some(((src1.as_signed_word()).wrapping_add(src2.as_signed_word())).as_word()),
+ isa::funct7::SUB_SRA => Some(((src1.as_signed_word()).wrapping_sub(src2.as_signed_word())).as_word()),
_ => {
self.trap(Trap::IllegalInstruction {
address: pc,
@@ -208,19 +209,19 @@ impl<'a> Core<'a> {
Some(src1 << src2_shift)
},
isa::funct3::SLT => {
- if (src1 as isa::SignedWord) < (src2 as isa::SignedWord) {
- Some(1)
+ if (src1.as_signed_word()) < (src2.as_signed_word()) {
+ Some(isa::Word(1))
}
else {
- Some(0)
+ Some(isa::Word(0))
}
},
isa::funct3::SLTU => {
if src1 < src2 {
- Some(1)
+ Some(isa::Word(1))
}
else {
- Some(0)
+ Some(isa::Word(0))
}
},
isa::funct3::XOR => {
@@ -229,7 +230,9 @@ impl<'a> Core<'a> {
isa::funct3::SRL_SRA => {
match inst.funct7() {
isa::funct7::ADD_SRL => Some(src1 >> src2_shift),
- isa::funct7::SUB_SRA => Some(((src1 as isa::SignedWord) >> src2_shift) as isa::Word),
+ isa::funct7::SUB_SRA =>
+ Some(((src1.as_signed_word()) >>
+ src2_shift.as_signed_word()).as_word()),
_ => {
self.trap(Trap::IllegalInstruction {
address: pc,
@@ -259,28 +262,28 @@ impl<'a> Core<'a> {
isa::opcodes::LOAD => {
let imm = inst.i_imm();
let base = self.registers.read_word(inst.rs1());
- let address = ((base as isa::SignedWord) + imm) as isa::Address;
+ let address = ((base.as_signed_word()) + imm).as_address();
let address = self.mmu.translate(address);
let result = match inst.funct3() {
isa::funct3::LB =>
self.cache.borrow_mut()
.read_byte(address)
- .map(|b| (b as isa::SignedByte) as isa::Word),
+ .map(|b| b.as_signed_word().as_word()),
isa::funct3::LH =>
self.cache.borrow_mut()
.read_halfword(address)
- .map(|b| (b as isa::SignedHalfWord) as isa::Word),
+ .map(|b| b.as_signed_word().as_word()),
isa::funct3::LW =>
self.cache.borrow_mut().read_word(address),
isa::funct3::LBU =>
self.cache.borrow_mut()
.read_byte(address)
- .map(|b| b as isa::Word),
+ .map(|b| b.as_word()),
isa::funct3::LHU =>
self.cache.borrow_mut()
.read_halfword(address)
- .map(|b| b as isa::Word),
+ .map(|b| b.as_word()),
_ => panic!("{:x}: Invalid load funct3code: 0x{:x}",
pc, inst.funct3()),
};
@@ -304,16 +307,16 @@ impl<'a> Core<'a> {
let imm = inst.s_imm();
let base = self.registers.read_word(inst.rs1());
let val = self.registers.read_word(inst.rs2());
- let address = ((base as isa::SignedWord) + imm) as isa::Address;
+ let address = ((base.as_signed_word()) + imm).as_address();
let address = self.mmu.translate(address);
let result = match inst.funct3() {
isa::funct3::SB =>
self.cache.borrow_mut()
- .write_byte(address, val as isa::Byte),
+ .write_byte(address, val.as_byte()),
isa::funct3::SH =>
self.cache.borrow_mut()
- .write_halfword(address, val as isa::HalfWord),
+ .write_halfword(address, val.as_half_word()),
isa::funct3::SW =>
self.cache.borrow_mut().write_word(address, val),
_ => panic!("PC {:x}: Invalid store funct3code: 0x{:x}",
@@ -337,7 +340,7 @@ impl<'a> Core<'a> {
}
},
isa::opcodes::SYSTEM => match inst.i_imm() {
- 0x0 => {
+ isa::SignedWord(0x0) => {
let result = system.syscall(self.id, &mut self.registers,
&*self.mmu);
if let Some(trap) = result {