op encoding

This commit is contained in:
c0repwn3r 2023-05-08 12:19:10 -04:00
commit f4c78f2b05
Signed by: core
GPG Key ID: FDBF740DADDCEECF
11 changed files with 343 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

8
.idea/.gitignore vendored Normal file
View File

@ -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

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/tmcpu.iml" filepath="$PROJECT_DIR$/.idea/tmcpu.iml" />
</modules>
</component>
</project>

11
.idea/tmcpu.iml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

7
Cargo.lock generated Normal file
View File

@ -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"

8
Cargo.toml Normal file
View File

@ -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]

15
hello_world.asm Normal file
View File

@ -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

5
src/main.rs Normal file
View File

@ -0,0 +1,5 @@
pub mod ops;
fn main() {
println!("Hello, world!");
}

268
src/ops.rs Normal file
View File

@ -0,0 +1,268 @@
pub fn nop() -> Vec<u8> {
vec![0b1111_1111]
}
pub fn hcf() -> Vec<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
// 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<u8> {
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<u8> {
vec![
0b1111_0011, // opcode
address_higher_half(address), // operands 1
address_lower_half(address), // operands 2,
0b0000_0000
]
}
pub fn jez(address: u16) -> Vec<u8> {
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<u8> {
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<u8> {
vec![
0b1111_0000,
reg_dest.byte() << 5,
port,
0b0000_0000
]
}
pub fn out(reg_src: Register, port: u8) -> Vec<u8> {
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])
}
}