foxpy
2 years ago
5 changed files with 184 additions and 1 deletions
@ -0,0 +1,7 @@ |
|||
# Mistakes |
|||
|
|||
## Don't design opcodes in your head |
|||
|
|||
You WILL frick up and your binary encodings WILL overlap. |
|||
You definitely need some tool to design instruction opcodes |
|||
for anything more complicated than just 1-byte instructions. |
@ -1,4 +1,144 @@ |
|||
// SPDX-License-Identifier: MIT
|
|||
// Copyright Murad Karammaev, Nikita Kuzmin
|
|||
|
|||
fn main() {} |
|||
use ux::{u2, u3, u4}; |
|||
|
|||
#[derive(Debug)] |
|||
enum Register { |
|||
R0, |
|||
R1, |
|||
} |
|||
|
|||
#[derive(Debug)] |
|||
enum ShiftMode { |
|||
Logical, |
|||
Circular, |
|||
} |
|||
|
|||
#[derive(Debug)] |
|||
enum Instruction { |
|||
Load { reg: Register, addr: u4 }, |
|||
Store { reg: Register, addr: u4 }, |
|||
LoadImmediate { low: bool, reg: Register, val: u4 }, |
|||
NearJumpBackward { use_carry: bool, offset: u2 }, |
|||
NearJumpForward { use_carry: bool, offset: u3 }, |
|||
FarJump { reg: Register, use_carry: bool }, |
|||
CmpEqual, |
|||
CmpGreater, |
|||
CmpLess, |
|||
Not, |
|||
BitShift { right: bool, reg: Register, mode: ShiftMode, len: u3 }, |
|||
Inc { reg: Register }, |
|||
Dec { reg: Register }, |
|||
Add, |
|||
Sub, |
|||
And, |
|||
Or, |
|||
Xor, |
|||
Xnor, |
|||
Complement { reg: Register }, |
|||
BitShiftVar { right: bool, mode: ShiftMode }, |
|||
Copy { reg_from: Register }, |
|||
Setc { carry: bool }, |
|||
Nop, |
|||
Reset, |
|||
Cload { reg: Register }, |
|||
Zero { reg: Register }, |
|||
Div, |
|||
Mul, |
|||
Swap, |
|||
PortReady, |
|||
ReadPort, |
|||
WritePort, |
|||
} |
|||
|
|||
fn decode(insn: u8) -> Instruction { |
|||
match insn { |
|||
0b00000000..=0b00111111 => { |
|||
let reg = if insn & 0b00010000 == 0 { Register::R0 } else { Register::R1 }; |
|||
let addr = u4::new(insn & 0b00001111); |
|||
match insn & 0b00100000 { |
|||
0 => Instruction::Load {reg, addr}, |
|||
_ => Instruction::Store {reg, addr}, |
|||
} |
|||
}, |
|||
0b01000000..=0b01111111 => Instruction::LoadImmediate { |
|||
low: insn & 0b00100000 != 0, |
|||
reg: if insn & 0b00010000 == 0 { Register::R0 } else { Register::R1 }, |
|||
val: u4::new(insn & 0b00001111), |
|||
}, |
|||
0b10001000..=0b10001111 => Instruction::NearJumpBackward { |
|||
use_carry: insn & 0b00000100 != 0, |
|||
offset: u2::new(insn & 0b00000011), |
|||
}, |
|||
0b10010000..=0b10011111 => Instruction::NearJumpForward { |
|||
use_carry: insn & 0b00001000 != 0, |
|||
offset: u3::new(insn & 0b00000111), |
|||
}, |
|||
0b10000000..=0b10000011 => Instruction::FarJump { |
|||
reg: if insn & 0b00000010 == 0 { Register::R0 } else { Register::R1 }, |
|||
use_carry: insn & 0b00000001 != 0, |
|||
}, |
|||
0b10000100 => Instruction::CmpEqual, |
|||
0b10000101 => Instruction::CmpGreater, |
|||
0b10000110 => Instruction::CmpLess, |
|||
0b10000111 => Instruction::Not, |
|||
0b10100000..=0b10111111 => Instruction::BitShift { |
|||
right: true, |
|||
reg: if insn & 0b00010000 == 0 { Register::R0 } else { Register::R1 }, |
|||
mode: if insn & 0b00001000 == 0 { ShiftMode::Logical } else { ShiftMode::Circular }, |
|||
len: u3::new(insn & 0b00000111), |
|||
}, |
|||
0b11000000..=0b11011111 => Instruction::BitShift { |
|||
right: false, |
|||
reg: if insn & 0b00010000 == 0 { Register::R0 } else { Register::R1 }, |
|||
mode: if insn & 0b00001000 == 0 { ShiftMode::Logical } else { ShiftMode::Circular }, |
|||
len: u3::new(insn & 0b00000111), |
|||
}, |
|||
0b11100000..=0b11100001 => Instruction::Inc { |
|||
reg: if insn & 0b00000001 == 0 { Register::R0 } else { Register::R1 }, |
|||
}, |
|||
0b11100010..=0b11100011 => Instruction::Dec { |
|||
reg: if insn & 0b00000001 == 0 { Register::R0 } else { Register::R1 }, |
|||
}, |
|||
0b11100100 => Instruction::Add, |
|||
0b11100101 => Instruction::Sub, |
|||
0b11100110 => Instruction::And, |
|||
0b11100111 => Instruction::Or, |
|||
0b11101000 => Instruction::Xor, |
|||
0b11101001 => Instruction::Xnor, |
|||
0b11101010..=0b11101011 => Instruction::Complement { |
|||
reg: if insn & 0b00000001 == 0 { Register::R0 } else { Register::R1 }, |
|||
}, |
|||
0b11101100..=0b11101111 => Instruction::BitShiftVar { |
|||
right: insn & 0b00000010 != 0, |
|||
mode: if insn & 0b00000001 == 0 { ShiftMode::Logical } else { ShiftMode::Circular }, |
|||
}, |
|||
0b11110000..=0b11110001 => Instruction::Copy { |
|||
reg_from: if insn & 0b00000001 == 0 { Register::R0 } else { Register::R1 }, |
|||
}, |
|||
0b11110010..=0b11110011 => Instruction::Setc { |
|||
carry: insn & 0b00000001 != 0, |
|||
}, |
|||
0b11110100 => Instruction::Nop, |
|||
0b11110101 => Instruction::Reset, |
|||
0b11110110..=0b11110111 => Instruction::Cload { |
|||
reg: if insn & 0b00000001 == 0 { Register::R0 } else { Register::R1 }, |
|||
}, |
|||
0b11111000..=0b11111001 => Instruction::Zero { |
|||
reg: if insn & 0b00000001 == 0 { Register::R0 } else { Register::R1 }, |
|||
}, |
|||
0b11111010 => Instruction::Div, |
|||
0b11111011 => Instruction::Mul, |
|||
0b11111100 => Instruction::Swap, |
|||
0b11111101 => Instruction::PortReady, |
|||
0b11111110 => Instruction::ReadPort, |
|||
0b11111111 => Instruction::WritePort, |
|||
} |
|||
} |
|||
|
|||
fn main() { |
|||
for i in 0..=255u8 { |
|||
println!("{:#08b} -> {:?}", i, decode(i)); |
|||
} |
|||
} |
|||
|
Loading…
Reference in new issue