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
|
// SPDX-License-Identifier: MIT
|
||||
// Copyright Murad Karammaev, Nikita Kuzmin
|
// 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