From 3ea6fe6dc17b15405f185f27170a00fd49460fe0 Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Sat, 18 Jan 2020 00:43:39 -0500 Subject: [PATCH] [WIP] Implementing encoding --- isa.txt | 2 +- toolchain/src/inst.rs | 42 ++++++++++++++------------ toolchain/src/inst/encode.rs | 58 ++++++++++++++++++++++++++++++++++-- toolchain/src/inst/test.rs | 16 +++++++++- 4 files changed, 95 insertions(+), 23 deletions(-) diff --git a/isa.txt b/isa.txt index 98bada1..89ece1a 100644 --- a/isa.txt +++ b/isa.txt @@ -1,6 +1,6 @@ 4 16-bit general-purpose registers r0, r1, r2, r3 -ALU2: misc ???? add sub addpc and or xor +ALU2: misc ??? add sub addpc and or xor ALU1: inc dec neg comp ALUA: add ALUI: lsl lsr asr rol clr set tog ext diff --git a/toolchain/src/inst.rs b/toolchain/src/inst.rs index 07ffded..5f20e61 100644 --- a/toolchain/src/inst.rs +++ b/toolchain/src/inst.rs @@ -39,12 +39,16 @@ pub enum Op1 { #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(test, derive(Arbitrary))] -pub enum OpI { - Add(I8), - Lsl(U4), - Lsr(U4), - Asr(U4), - Rol(U4), +#[repr(u8)] +pub enum OpC { + Lsl, + Lsr, + Asr, + Rol, + Clr, + Set, + Tog, + Ext, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -61,22 +65,16 @@ pub enum Op2 { #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(test, derive(Arbitrary))] -pub struct U4(#[cfg_attr(test, proptest(strategy = "0..=16u8"))]u8); +pub struct U4(#[cfg_attr(test, proptest(strategy = "0..=16u8"))] u8); #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(test, derive(Arbitrary))] -pub struct I5(#[cfg_attr(test, proptest(strategy = "-16..=15i8"))]i8); +pub struct I5(#[cfg_attr(test, proptest(strategy = "-16..=15i8"))] i8); #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(test, derive(Arbitrary))] pub struct I7(#[cfg_attr(test, proptest(strategy = "-64..=63i8"))] i8); #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(test, derive(Arbitrary))] -pub struct U7(#[cfg_attr(test, proptest(strategy = "0..=128u8"))]u8); -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct U8(u8); -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(test, derive(Arbitrary))] -pub struct I8(i8); +pub struct U7(#[cfg_attr(test, proptest(strategy = "0..=128u8"))] u8); #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(test, derive(Arbitrary))] @@ -109,13 +107,18 @@ pub enum Addr { #[derive(Clone, Copy, Debug, Eq)] #[cfg_attr(test, derive(Arbitrary))] -#[cfg_attr(test, proptest(no_params))] pub enum Cond { + #[cfg_attr(test, proptest(strategy = "test::cond_strategy(Cond::Eql)"))] Eql(Reg, Reg), + #[cfg_attr(test, proptest(strategy = "test::cond_strategy(Cond::Neq)"))] Neq(Reg, Reg), + #[cfg_attr(test, proptest(strategy = "test::cond_strategy(Cond::Test)"))] Test(Reg, Reg), + #[cfg_attr(test, proptest(strategy = "test::cond_strategy(Cond::TestNot)"))] TestNot(Reg, Reg), + #[cfg_attr(test, proptest(strategy = "test::cond_strategy(Cond::Lt)"))] Lt(Reg, Reg), + #[cfg_attr(test, proptest(strategy = "test::cond_strategy(Cond::Ult)"))] Ult(Reg, Reg), } @@ -130,9 +133,10 @@ pub enum Inst { Alu1(Reg, Op1), Mem(LdSt, Reg, Addr), Branch(Cond, I7), - JumpI(I8), - AluI(Reg, OpI), - LdImm(Half, Reg, U8), + JumpI(i8), + AddI(Reg, i8), + AluCompact(Reg, OpC, U4), + LdImm(Half, Reg, u8), } impl PartialEq for Cond { diff --git a/toolchain/src/inst/encode.rs b/toolchain/src/inst/encode.rs index e4832e2..0103e46 100644 --- a/toolchain/src/inst/encode.rs +++ b/toolchain/src/inst/encode.rs @@ -1,13 +1,67 @@ -use crate::inst::Inst; +use crate::inst::{Addr, Cond, Inst, Reg, I7, U4}; use std::io::{self, Write}; pub trait Encode { fn encode(&self, out: &mut impl Write) -> io::Result<()>; } +fn unpack_cond(c: Cond) -> (u8, u8, Reg, Reg) { + use Cond::*; + let (o2, o1, ra, rb) = match c { + Eql(ra, rb) => (0, 0, ra.min(rb), ra.max(rb)), + Neq(ra, rb) => (0, 0, ra.max(rb), ra.min(rb)), + Test(ra, rb) => (0, 1, ra.min(rb), ra.max(rb)), + TestNot(ra, rb) => (0, 1, ra.min(rb), ra.max(rb)), + Lt(ra, rb) => (1, 0, ra, rb), + Ult(ra, rb) => (1, 1, ra, rb), + }; + debug_assert_ne!(ra, rb, "ra == rb reserved for fixed addressing"); + (o2, o1, ra, rb) +} + impl Encode for Inst { fn encode(&self, out: &mut impl Write) -> io::Result<()> { - out.write_all(&[0x00])?; + use Inst::*; + match *self { + Halt => out.write_all(&[0x00])?, + Nope => out.write_all(&[0x01])?, + Alu2(rd, op, r2) => { + out.write_all(&[0x00 | (op as u8) << 4 | (rd as u8) << 2 | r2 as u8])? + } + Jalr(r) => out.write_all(&[0x80 | (r as u8) << 2 | r as u8])?, + Move(rd, r2) => { + debug_assert_ne!(rd, r2, "Can't move to self"); + out.write_all(&[0x00, (rd as u8) << 2 | r2 as u8])? + } + Alu1(r, op) => out.write_all(&[0x90 | (r as u8) << 2 | op as u8])?, + Mem(op, r_data, Addr::Reg(r_addr)) => { + out.write_all(&[0xa0 | (op as u8) << 4 | (r_data as u8) << 2 | r_addr as u8])? + } + Branch(cond, I7(off)) => { + let (o2, o1, ra, rb) = unpack_cond(cond); + out.write_all(&[ + 0xc0 | o2 << 4 | (ra as u8) << 2 | rb as u8, + o1 << 7 | off as u8, + ])? + } + JumpI(off) => out.write_all(&[0xc0, off as u8])?, + Mem(op, rd, Addr::Fixed(addr)) => out.write_all(&[])?, + AddI(rd, imm) => out.write_all(&[0xe0 | (rd as u8) << 2, imm as u8])?, + AluCompact(rd, op, U4(imm)) => { + out.write_all(&[0xe1 | (rd as u8) << 2, (op as u8) << 4 | imm as u8])? + } + LdImm(h, rd, imm) => out.write_all(&[0xe2 | (h as u8) << 1, imm])?, + Mem( + op, + rd, + Addr::Extended { + base, + offset, + stack, + size, + }, + ) => out.write_all(&[])?, + } Ok(()) } } diff --git a/toolchain/src/inst/test.rs b/toolchain/src/inst/test.rs index e62a444..826da5a 100644 --- a/toolchain/src/inst/test.rs +++ b/toolchain/src/inst/test.rs @@ -1,7 +1,21 @@ -use super::{Decode, Encode, Inst}; +use super::{Cond, Decode, Encode, Inst, Reg}; use proptest::prelude::*; use std::io::Cursor; +pub(super) fn cond_strategy(op: impl Fn(Reg, Reg) -> Cond) -> impl Strategy { + (0..4u8, 1..4u8).prop_map(move |(a, b)| op(reg_num(a), reg_num(a + b))) +} + +fn reg_num(x: u8) -> Reg { + match x & 0x3 { + 0 => Reg::R0, + 1 => Reg::R1, + 2 => Reg::R2, + 3 => Reg::R3, + _ => unreachable!(), + } +} + proptest! { #[test] fn encoding_roundtrip(inst: Inst) { -- 2.47.0