riscii

An emulator for the RISC II
Log | Files | Refs | LICENSE

commit 2d5716d89fd31c610875752ae74cee5739619d6c
parent 606b4df7aedfa2d430ddab7914f431ee3ca13637
Author: Ryan Jeffrey <ryan@ryanmj.xyz>
Date:   Tue, 18 Oct 2022 21:32:20 -0700

SCC to ALU, ALU docucomments

Diffstat:
Msrc/alu.rs | 302++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/data_path.rs | 18++++++++++++++++++
Msrc/instruction.rs | 1+
3 files changed, 310 insertions(+), 11 deletions(-)

diff --git a/src/alu.rs b/src/alu.rs @@ -17,6 +17,9 @@ use std::fmt; +use data_path::SCCBits; +use instruction::SIGN_BIT_LOC; + /// Representation of the Arithmetic Logic Unit of the RISCII. /// Implements bitwise and arithmetic operations, except for shifts. #[derive(Clone, Copy)] @@ -37,67 +40,344 @@ impl ALU { // Bitwise. - /// Bitwise AND the values in the input latches. + /// Bitwise AND the values in the input latches and return the result. pub fn and(&self) -> u32 { self.ai & self.bi } - /// Bitwise OR the values in the input latches. + /// Bitwise AND the values in the input latches, return the result + /// and SCC values. + /// For bitwise operators the SCC bits are as follows: + /// v = false + /// c = false + /// z = result == 0 + /// n = result as i32 < 0 + pub fn and_scc(&self) -> (u32, SCCBits) { + let result = self.and(); + ( + result, + SCCBits { + z: result == 0, + n: result & SIGN_BIT_LOC != 0, + v: false, + c: false, + }, + ) + } + + /// Bitwise OR the values in the input latches and return the result. pub fn or(&self) -> u32 { self.ai | self.bi } + /// Bitwise OR the values in the input latches, return the result + /// and the SCC values. + /// For bitwise operators the SCC bits are as follows: + /// v = false + /// c = false + /// z = result == 0 + /// n = result as i32 < 0 + pub fn or_scc(&self) -> (u32, SCCBits) { + let result = self.or(); + ( + result, + SCCBits { + z: result == 0, + n: result & SIGN_BIT_LOC != 0, + v: false, + c: false, + }, + ) + } + /// Bitwise XOR the values in the input latches. pub fn xor(&self) -> u32 { self.ai ^ self.bi } + /// Bitwise XOR the values in the input latches, return the result + /// and the SCC values. + /// For bitwise operators the SCC bits are as follows: + /// v = false + /// c = false + /// z = result == 0 + /// n = result as i32 < 0 + pub fn xor_scc(&self) -> (u32, SCCBits) { + let result = self.xor(); + ( + result, + SCCBits { + z: result == 0, + n: result & SIGN_BIT_LOC != 0, + v: false, + c: false, + }, + ) + } + // Arithmetics. - /// Add the values in the input latches. + /// Add the values in the input latches and return the sum. pub fn add(&self) -> u32 { self.ai + self.bi } + /// Add the values in the input latches, return the sum and SCC values. + /// For addition the SCC bits are as follows: + /// v = Signed overflow occurred + /// c = unsigned overflow occurred + /// z = result == 0 + /// n = result as i32 < 0 + pub fn add_scc(&self) -> (u32, SCCBits) { + let (iresult, v) = (self.ai as i32).overflowing_add(self.bi as i32); + let (result, c) = self.ai.overflowing_add(self.bi); + let z = result == 0; + let n = iresult < 0; + + ( + result, + SCCBits { + z: z, + n: n, + c: c, + v: v, + }, + ) + } + /// 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. + /// Add the values in the input latches with the carry bit, return the + /// sum and the SCC values. + /// For addition the SCC bits are as follows: + /// v = Signed overflow occurred + /// c = unsigned overflow occurred + /// z = result == 0 + /// n = result as i32 < 0 + pub fn addc_scc(&self, carry: bool) -> (u32, SCCBits) { + let (iresult, v) = (self.ai as i32 + carry as i32).overflowing_add(self.bi as i32); + let (result, c) = (self.ai as u32 + carry as u32).overflowing_add(self.bi); + let z = result == 0; + let n = iresult.is_negative(); + + ( + result, + SCCBits { + z: z, + n: n, + c: c, + v: v, + }, + ) + } + + /// Subtract the values in the input latches and return the difference. + /// Use `self.ai` is the minuend and use `self.bi` as the subtrahend. pub fn sub(&self) -> u32 { self.ai - self.bi } - /// Subtract the values in the input latches with the carry bit. + /// Subtract the values in the input latches, return SCC values. Return + /// difference and the SCC values. + /// Use `self.ai` is the minuend and use `self.bi` as the subtrahend. + /// For subtraction the SCC bits are as follows: + /// v = Signed overflow occurred + /// c = unsigned overflow NOT occurred + /// z = result == 0 + /// n = result as i32 < 0 + pub fn sub_scc(&self) -> (u32, SCCBits) { + let (iresult, v) = (self.ai as i32).overflowing_sub(self.bi as i32); + let (result, c) = self.ai.overflowing_sub(self.bi); + let z = result == 0; + let n = iresult.is_negative(); + + ( + result, + SCCBits { + z: z, + c: !c, + n: n, + v: v, + }, + ) + } + + /// Subtract the values in the input latches and add the carry bit to the difference. + /// Return the sum. + /// Use `self.ai` is the minuend and use `self.bi` as the subtrahend and add carry to the difference. pub fn subc(&self, carry: bool) -> u32 { - self.ai - self.bi - (!carry as u32) + self.ai - self.bi + carry as u32 } - /// Subtract (inverse) the values in the input latches. + /// Subtract the values in the input latches and add the carry bit. + /// Return the sum and SCC values. + /// Use `self.ai` is the minuend and use `self.bi` as the subtrahend and add carry to the difference. + /// For subtraction the SCC bits are as follows: + /// v = Signed overflow occurred + /// c = unsigned overflow NOT occurred + /// z = result == 0 + /// n = result as i32 < 0 + pub fn subc_scc(&self, carry: bool) -> (u32, SCCBits) { + let (iresult, v) = (self.ai as i32 - self.bi as i32).overflowing_add(carry as i32); + let (result, c) = (self.ai - self.bi).overflowing_add(carry as u32); + let z = result == 0; + let n = iresult.is_negative(); + + ( + result, + SCCBits { + z: z, + c: !c, + n: n, + v: v, + }, + ) + } + + /// Subtract the values in the input latches in the reverse order of `sub`, return + /// the difference. + /// Use `self.bi` is the minuend and use `self.ai` as the subtrahend. pub fn subi(&self) -> u32 { self.bi - self.ai } - /// Subtract (inverse) the values in the input latches with the carry bit. + /// Subtract the values in the input latches in the reverse order of `sub`, return + /// the difference and SCC bits. + /// Use `self.bi` is the minuend and use `self.ai` as the subtrahend. + /// For subtraction the SCC bits are as follows: + /// v = Signed overflow occurred + /// c = unsigned overflow NOT occurred + /// z = result == 0 + /// n = result as i32 < 0 + pub fn subi_scc(&self) -> (u32, SCCBits) { + let (iresult, v) = (self.bi as i32).overflowing_sub(self.ai as i32); + let (result, c) = self.bi.overflowing_sub(self.ai); + let z = result == 0; + let n = iresult.is_negative(); + + ( + result, + SCCBits { + z: z, + c: c, + n: n, + v: v, + }, + ) + } + + /// Subtract the values in the input latches in the reverse order of `sub`, + /// and add the carry bit. Return the sum. + /// Use `self.bi` is the minuend and use `self.ai` as the subtrahend. pub fn subci(&self, carry: bool) -> u32 { self.bi - self.ai - (!carry as u32) } - /// Right logical shift of the input latches. + /// Subtract the values in the input latches in the reverse order of `sub`, + /// and add the carry bit. Return the sum and the SCC values. + /// Use `self.bi` is the minuend and use `self.ai` as the subtrahend. + /// For subtraction the SCC bits are as follows: + /// v = Signed overflow occurred + /// c = unsigned overflow NOT occurred + /// z = result == 0 + /// n = result as i32 < 0 + pub fn subci_scc(&self, carry: bool) -> (u32, SCCBits) { + let (iresult, v) = (self.bi as i32 - self.ai as i32).overflowing_add(carry as i32); + let (result, c) = (self.bi - self.ai).overflowing_add(carry as u32); + let z = result == 0; + let n = iresult.is_negative(); + + ( + result, + SCCBits { + z: z, + c: c, + n: n, + v: v, + }, + ) + } + + /// Right logical shift of the input latches. Return the result. + /// Use `self.ai` as the value to shift, and `self.bi` and the amount to shift by. pub fn shift_right_logical(&self) -> u32 { self.ai >> self.bi } - /// Right arithmetic shift of the input latches. + /// Right logical shift of the input latches. Return the result and the SCC values. + /// Use `self.ai` as the value to shift, and `self.bi` and the amount to shift by. + /// For bitwise operators the SCC bits are as follows: + /// v = false + /// c = false + /// z = result == 0 + /// n = result as i32 < 0 + pub fn shift_right_logical_scc(&self) -> (u32, SCCBits) { + let result = self.shift_right_logical(); + ( + result, + SCCBits { + z: result == 0, + n: result & SIGN_BIT_LOC != 0, + v: false, + c: false, + }, + ) + } + + /// Right arithmetic shift of the input latches. Return the result. + /// Use `self.ai` as the value to shift, and `self.bi` and the amount to shift by. pub fn shift_right_arithmetic(&self) -> u32 { ((self.ai as i32) >> self.bi) as u32 } - /// Left arithmetic shift of the input latches. + /// Right logical shift of the input latches. Return the result and the SCC values. + /// Use `self.ai` as the value to shift, and `self.bi` and the amount to shift by. + /// For bitwise operators the SCC bits are as follows: + /// v = false + /// c = false + /// z = result == 0 + /// n = result as i32 < 0 + pub fn shift_right_arithmetic_scc(&self) -> (u32, SCCBits) { + let result = self.shift_right_arithmetic(); + ( + result, + SCCBits { + z: result == 0, + n: result & SIGN_BIT_LOC != 0, + v: false, + c: false, + }, + ) + } + + /// Left arithmetic shift of the input latches. Return the result. + /// Use `self.ai` as the value to shift, and `self.bi` and the amount to shift by. pub fn shift_left_logical(&self) -> u32 { self.ai << self.bi } + + /// Right logical shift of the input latches. Return the result and the SCC values. + /// Use `self.ai` as the value to shift, and `self.bi` and the amount to shift by. + /// For bitwise operators the SCC bits are as follows: + /// v = false + /// c = false + /// z = result == 0 + /// n = result as i32 < 0 + pub fn shift_left_arithmetic_scc(&self) -> (u32, SCCBits) { + let result = self.shift_left_logical(); + ( + result, + SCCBits { + z: result == 0, + n: result & SIGN_BIT_LOC != 0, + v: false, + c: false, + }, + ) + } } impl fmt::Display for ALU { diff --git a/src/data_path.rs b/src/data_path.rs @@ -26,6 +26,13 @@ use crate::shifter::Shifter; pub type MicroOp = fn(dp: &mut DataPath); +pub struct SCCBits { + pub z: bool, + pub n: bool, + pub v: bool, + pub c: bool, +} + #[derive(Debug, Clone)] pub struct Control { pub long: bool, @@ -417,6 +424,17 @@ impl DataPath { pub fn current_instruction_is_memory(&self) -> bool { self.control2.memory } + + pub fn add_step(&mut self) { + self.dst_latch = self.alu.add(); + } + + pub fn set_cc_codes_arithmetic(&mut self) { + if self.scc_flag3 { + self.psw.set_cc_zero(self.dst_latch == 0); + self.psw.set_cc_neg(self.dst_latch & SIGN_BIT_LOC != 0); + } + } } impl Control { diff --git a/src/instruction.rs b/src/instruction.rs @@ -30,6 +30,7 @@ pub const SHORT_SOURCE_TYPE_LOC: u32 = 0x2000; pub const OPCODE_LOC: u32 = 0xFE000000; pub const SHORT_IMM_SIGN_LOC: u32 = 0x1000; pub const SHORT_IMM_SIGNEXT_BITS: u32 = 0xFFFFE000; +pub const SIGN_BIT_LOC: u32 = 0x80000000; // Public functions.