From f4c78f2b0588643a6723d24d1e5b074b7353f7bb Mon Sep 17 00:00:00 2001 From: c0repwn3r Date: Mon, 8 May 2023 12:19:10 -0400 Subject: [PATCH] op encoding --- .gitignore | 1 + .idea/.gitignore | 8 ++ .idea/misc.xml | 6 ++ .idea/modules.xml | 8 ++ .idea/tmcpu.iml | 11 ++ .idea/vcs.xml | 6 ++ Cargo.lock | 7 ++ Cargo.toml | 8 ++ hello_world.asm | 15 +++ src/main.rs | 5 + src/ops.rs | 268 ++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 343 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/tmcpu.iml create mode 100644 .idea/vcs.xml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 hello_world.asm create mode 100644 src/main.rs create mode 100644 src/ops.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..3ce3588 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..dcff435 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/tmcpu.iml b/.idea/tmcpu.iml new file mode 100644 index 0000000..c254557 --- /dev/null +++ b/.idea/tmcpu.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..343a2c6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "tmcpu" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c68ab8e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tmcpu" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/hello_world.asm b/hello_world.asm new file mode 100644 index 0000000..130785d --- /dev/null +++ b/hello_world.asm @@ -0,0 +1,15 @@ +ldi ra, 0x01 +ldi rb, 0x02 +add rc, ra rb ; should be 3 +out 0x02, rc ; displays 03 on the numeric display + +ldi ra, 0b10100000 ; load the num for red and blue into ra +mrm ra, 0x001 +mrm ra, 0x003 +mrm ra, 0x01e +mrm ra, 0x02e +mrm ra, 0x02f +mrm ra, 0x030 +mrm ra, 0x031 +mrm ra, 0x023 +; Draw a smiley face \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..38a0227 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,5 @@ +pub mod ops; + +fn main() { + println!("Hello, world!"); +} diff --git a/src/ops.rs b/src/ops.rs new file mode 100644 index 0000000..b382b68 --- /dev/null +++ b/src/ops.rs @@ -0,0 +1,268 @@ +pub fn nop() -> Vec { + vec![0b1111_1111] +} +pub fn hcf() -> Vec { + vec![0b1111_1110] +} + +pub enum Register { + R0, + RA, + RB, + RC, + RD, + RE, + PC, + FLG +} +impl Register { + fn byte(&self) -> u8 { + match self { + Register::R0 => 0b0000_0000, + Register::RA => 0b0000_0001, + Register::RB => 0b0000_0010, + Register::RC => 0b0000_0011, + Register::RD => 0b0000_0100, + Register::RE => 0b0000_0101, + Register::PC => 0b0000_0110, + Register::FLG => 0b0000_0111, + } + } +} + +pub fn add(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec { + vec![ + 0b1111_1101, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + reg_b.byte() << 5, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn sub(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec { + vec![ + 0b1111_1100, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + reg_b.byte() << 5, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn or(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec { + vec![ + 0b1111_1011, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + reg_b.byte() << 5, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn nor(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec { + vec![ + 0b1111_1010, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + reg_b.byte() << 5, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn and(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec { + vec![ + 0b1111_1001, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + reg_b.byte() << 5, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn xor(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec { + vec![ + 0b1111_1000, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + reg_b.byte() << 5, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn rsh(reg_dest: Register, reg_a: Register) -> Vec { + vec![ + 0b1111_0111, // opcode + reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1 + 0b0000_0000, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn ldi(reg_dest: Register, immediate: u8) -> Vec { + vec![ + 0b1111_0110, // opcode + reg_dest.byte() << 5, // operands 1 + immediate, // operands 2, + 0b0000_0000 // operands 3 + ] +} + +pub fn mmr(reg_dest: Register, address: u16) -> Vec { + // 0110 1001 1010 0101 + // want: 1001 1010 0101 + // &0000 1111 1111 0000, >> 4 + // &0000 0000 0000 1111, << 4 + vec![ + 0b1111_0101, // opcode, + reg_dest.byte() << 5, // operands 1 + address_higher_half(address), // operands 2 + address_lower_half(address), // operands 3 + ] +} + +pub fn mrm(reg_src: Register, address: u16) -> Vec { + vec![ + 0b1111_0100, // opcode + reg_src.byte() << 5, // operands 1 + address_higher_half(address), // operands 2 + address_lower_half(address), // operands 3 + ] +} + +pub fn jmp(address: u16) -> Vec { + vec![ + 0b1111_0011, // opcode + address_higher_half(address), // operands 1 + address_lower_half(address), // operands 2, + 0b0000_0000 + ] +} + +pub fn jez(address: u16) -> Vec { + vec![ + 0b1111_0010, // opcode + address_higher_half(address), // operands 1 + address_lower_half(address), // operands 2, + 0b0000_0000 + ] +} + +pub fn rmmr(reg_dest: Register, address: u16) -> Vec { + vec![ + 0b1111_0001, // opcode, + reg_dest.byte() << 5, // operands 1 + address_higher_half(address), // operands 2 + address_lower_half(address), // operands 3 + ] +} + +pub fn r#in(reg_dest: Register, port: u8) -> Vec { + vec![ + 0b1111_0000, + reg_dest.byte() << 5, + port, + 0b0000_0000 + ] +} + +pub fn out(reg_src: Register, port: u8) -> Vec { + vec![ + 0b1110_1111, + reg_src.byte() << 5, + port, + 0b0000_0000 + ] +} + +// See `mmr` for how these values are calculated +fn address_higher_half(address: u16) -> u8 { + ((address & 0b0000_1111_1111_0000) >> 4).try_into().unwrap() +} +// See `mmr` for how these values are calculated +fn address_lower_half(address: u16) -> u8 { + ((address & 0b0000_0000_0000_1111) << 4).try_into().unwrap() +} + +mod tests { + use crate::ops::{add, and, hcf, jez, jmp, ldi, mmr, mrm, nop, nor, or, out, r#in, Register, rmmr, rsh, sub, xor}; + + #[test] + fn test_nop() { + assert_eq!(nop(), vec![0b1111_1111]); + } + + #[test] + fn test_hcf() { + assert_eq!(hcf(), vec![0b1111_1110]); + } + + #[test] + fn test_add() { + assert_eq!(add(Register::R0, Register::RA, Register::RB), vec![0b1111_1101, 0b0000_0100, 0b0100_0000, 0b0000_0000]) + } + + #[test] + fn test_sub() { + assert_eq!(sub(Register::R0, Register::RA, Register::RB), vec![0b1111_1100, 0b0000_0100, 0b0100_0000, 0b0000_0000]) + } + + #[test] + fn test_or() { + assert_eq!(or(Register::R0, Register::RA, Register::RB), vec![0b1111_1011, 0b0000_0100, 0b0100_0000, 0b0000_0000]) + } + + #[test] + fn test_nor() { + assert_eq!(nor(Register::R0, Register::RA, Register::RB), vec![0b1111_1010, 0b0000_0100, 0b0100_0000, 0b0000_0000]) + } + + #[test] + fn test_and() { + assert_eq!(and(Register::R0, Register::RA, Register::RB), vec![0b1111_1001, 0b0000_0100, 0b0100_0000, 0b0000_0000]) + } + + #[test] + fn test_xor() { + assert_eq!(xor(Register::R0, Register::RA, Register::RB), vec![0b1111_1000, 0b0000_0100, 0b0100_0000, 0b0000_0000]) + } + + #[test] + fn test_rsh() { + assert_eq!(rsh(Register::R0, Register::RA), vec![0b1111_0111, 0b0000_0100, 0b0000_0000, 0b0000_0000]) + } + + #[test] + fn test_ldi() { + assert_eq!(ldi(Register::R0, 0b0101_1010), vec![0b1111_0110, 0b0000_0000, 0b0101_1010, 0b0000_0000]) + } + + #[test] + fn test_mmr() { + assert_eq!(mmr(Register::R0, 0b0000_0101_1010_0110), vec![0b1111_0101, 0b0000_0000, 0b0101_1010, 0b0110_0000]) + } + + #[test] + fn test_mrm() { + assert_eq!(mrm(Register::R0, 0b0000_0101_1010_0110), vec![0b1111_0100, 0b0000_0000, 0b0101_1010, 0b0110_0000]) + } + + #[test] + fn test_jmp() { + assert_eq!(jmp(0b0000_0101_1010_0110), vec![0b1111_0011, 0b0101_1010, 0b0110_0000, 0b0000_0000]) + } + + #[test] + fn test_jez() { + assert_eq!(jez(0b0000_0101_1010_0110), vec![0b1111_0010, 0b0101_1010, 0b0110_0000, 0b0000_0000]) + } + + #[test] + fn test_rmmr() { + assert_eq!(rmmr(Register::R0, 0b0000_0101_1010_0110), vec![0b1111_0001, 0b0000_0000, 0b0101_1010, 0b0110_0000]) + } + + #[test] + fn test_in() { + assert_eq!(r#in(Register::R0, 0b0101_1010), vec![0b1111_0000, 0b0000_0000, 0b0101_1010, 0b0000_0000]) + } + + #[test] + fn test_out() { + assert_eq!(out(Register::R0, 0b0101_1010), vec![0b1110_1111, 0b0000_0000, 0b0101_1010, 0b0000_0000]) + } +} \ No newline at end of file