commit d5803d8d078c79dd1c73ab31c56a1384124eba5e
parent fc978975c6fb9a3fddd5dbb64cfdfd0bcc3ee9ee
Author: Ryan Jeffrey <ryan@ryanmj.xyz>
Date: Sat, 15 Oct 2022 14:06:06 -0700
ALU
Diffstat:
3 files changed, 110 insertions(+), 8 deletions(-)
diff --git a/src/alu.rs b/src/alu.rs
@@ -0,0 +1,102 @@
+// RISCII ALU emulator.
+// (C) Ryan Jeffrey <ryan@ryanmj.xyz>, 2022
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or (at
+// your option) any later version.
+
+// This program 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 Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+// Public structs.
+
+use std::fmt;
+
+/// Representation of the Arithmetic Logic Unit of the RISCII.
+/// Implements bitwise and arithmetic operations, except for shifts.
+#[derive(Clone, Copy)]
+pub struct ALU {
+ /// Input latch 1 for the ALU (fed by src1 or dest).
+ pub ai: u32,
+ /// Input latch 2 for the ALU (fed by src2 or dest).
+ pub bi: u32,
+}
+
+// Impls.
+
+impl ALU {
+ /// Create a 0'd out ALU.
+ pub fn new() -> Self {
+ Self { ai: 0, bi: 0 }
+ }
+
+ // Bitwise.
+
+ /// Bitwise AND the values in the input latches.
+ pub fn and(&self) -> u32 {
+ self.ai & self.bi
+ }
+
+ /// Bitwise OR the values in the input latches.
+ pub fn or(&self) -> u32 {
+ self.ai | self.bi
+ }
+
+ /// Bitwise XOR the values in the input latches.
+ pub fn xor(&self) -> u32 {
+ self.ai ^ self.bi
+ }
+
+ // Arithmetics.
+
+ /// Add the values in the input latches.
+ pub fn add(&self) -> u32 {
+ self.ai + self.bi
+ }
+
+ /// Add the values in the input latches with the carry bit.
+ pub fn addc(&self, carry: bool) -> u32 {
+ self.ai + self.bi + (carry as u32)
+ }
+
+ /// Subtract the values in the input latches.
+ pub fn sub(&self) -> u32 {
+ self.ai - self.bi
+ }
+
+ /// Subtract the values in the input latches with the carry bit.
+ pub fn subc(&self, carry: bool) -> u32 {
+ self.ai - self.bi - (!carry as u32)
+ }
+
+ /// Subtract (inverse) the values in the input latches.
+ pub fn subi(&self) -> u32 {
+ self.bi - self.ai
+ }
+
+ /// Subtract (inverse) the values in the input latches with the carry bit.
+ pub fn subci(&self, carry: bool) -> u32 {
+ self.bi - self.ai - (!carry as u32)
+ }
+}
+
+impl fmt::Display for ALU {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}, {}", self.ai, self.bi,)
+ }
+}
+
+impl fmt::Debug for ALU {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "Input register: {}, Output register: {}",
+ self.ai, self.bi,
+ )
+ }
+}
diff --git a/src/data_path.rs b/src/data_path.rs
@@ -14,6 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
+use alu::ALU;
use config::Config;
use cpu::{OutputPins, ProcessorStatusWord, RegisterFile, SIZEOF_INSTRUCTION};
use instruction::*;
@@ -54,10 +55,9 @@ pub struct DataPath {
pins_in: u32,
/// Pins for communicating with the outside world (memory).
output_pins: OutputPins,
- /// Input latch 1 for the ALU (fed by src1).
- ai: u32,
- /// Input latch 2 for the ALU (fed by src2).
- bi: u32,
+ /// Arithmetic logic unit.
+ alu: ALU,
+
// Control unit latches and registers.
/// Data from memory.
dimm: u32,
@@ -110,8 +110,7 @@ impl DataPath {
psw: ProcessorStatusWord::new(),
src_latch: 0,
dst_latch: 0,
- ai: 0,
- bi: 0,
+ alu: ALU::new(),
bar: 0,
rd1: 0,
rd2: 0,
@@ -151,8 +150,8 @@ impl DataPath {
let cwp = self.psw.get_cwp();
let read1 = self.regs.read(src1, cwp);
let read2 = self.regs.read(src2, cwp);
- self.ai = read1;
- self.bi = read2;
+ self.alu.ai = read1;
+ self.alu.bi = read2;
}
/// Decode the next instruction's (in `self.pins_in`) source registers.
diff --git a/src/main.rs b/src/main.rs
@@ -25,6 +25,7 @@ mod encode_test;
mod main_test;
// Modules declared as pub to shut up rust-analyzer about dead code.
+pub mod alu;
pub mod clock;
pub mod config;
pub mod cpu;