use self::super::super::isa::instruction::{InstructionLoadImmediateWideRegisterPair, InstructionMadrDirection, InstructionPortDirection,
InstructionStckDirection, InstructionRegisterPair, Instruction};
use self::super::MicroOp;
const FLAG_REGISTER_ADDRESS: u8 = 0b000;
const S_REGISTER_ADDRESS: u8 = 0b001;
const X_REGISTER_ADDRESS: u8 = 0b010;
const Y_REGISTER_ADDRESS: u8 = 0b011;
const A_REGISTER_ADDRESS: u8 = 0b100;
const B_REGISTER_ADDRESS: u8 = 0b101;
const C_REGISTER_ADDRESS: u8 = 0b110;
const D_REGISTER_ADDRESS: u8 = 0b111;
pub type MicroOpBlock = [MicroOp; 6];
impl MicroOp {
pub fn from_instruction(instr: Instruction) -> (MicroOpBlock, usize) {
match instr {
Instruction::Reserved(_) => {
([
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
6)
}
Instruction::LoadImmediateByte { rrr } => {
([
MicroOp::LoadImmediate,
MicroOp::WriteRegister(rrr),
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
2)
}
Instruction::LoadIndirect { rrr } => {
([
MicroOp::FetchAddress,
MicroOp::WriteRegister(rrr),
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
2)
}
Instruction::LoadImmediateWide { rr: InstructionLoadImmediateWideRegisterPair::Adr } => {
([
MicroOp::LoadImmediate,
MicroOp::LoadImmediate,
MicroOp::AdrWrite,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
3)
}
Instruction::LoadImmediateWide { rr } => {
let [f, s] = imm_address_pair(rr);
([
MicroOp::LoadImmediate,
MicroOp::LoadImmediate,
MicroOp::WriteRegister(s),
MicroOp::WriteRegister(f),
MicroOp::Nop,
MicroOp::Nop],
4)
}
Instruction::Jump(cond) => {
([
MicroOp::ReadRegister(FLAG_REGISTER_ADDRESS),
MicroOp::CheckJumpCondition(cond),
MicroOp::Jump,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
3)
}
Instruction::Save { rrr } => {
([
MicroOp::ReadRegister(rrr),
MicroOp::WriteAddress,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
2)
}
Instruction::Alu(op) => {
([
MicroOp::ReadRegister(X_REGISTER_ADDRESS),
MicroOp::ReadRegister(Y_REGISTER_ADDRESS),
MicroOp::ReadRegister(FLAG_REGISTER_ADDRESS),
MicroOp::Alu(op),
MicroOp::WriteRegister(FLAG_REGISTER_ADDRESS),
MicroOp::WriteRegister(S_REGISTER_ADDRESS)],
6)
}
Instruction::Move { qqq, rrr } => {
([
MicroOp::ReadRegister(qqq),
MicroOp::WriteRegister(rrr),
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
2)
}
Instruction::Madr { d: InstructionMadrDirection::Write, r } => {
let [f, s] = address_pair(r);
([
MicroOp::ReadRegister(f),
MicroOp::ReadRegister(s),
MicroOp::AdrWrite,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
3)
}
Instruction::Madr { d: InstructionMadrDirection::Read, r } => {
let [f, s] = address_pair(r);
([
MicroOp::AdrRead,
MicroOp::WriteRegister(s),
MicroOp::WriteRegister(f),
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
3)
}
Instruction::Port { d: InstructionPortDirection::In, rrr } => {
([
MicroOp::ReadRegister(A_REGISTER_ADDRESS),
MicroOp::PortIn,
MicroOp::WriteRegister(rrr),
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
3)
}
Instruction::Port { d: InstructionPortDirection::Out, rrr } => {
([
MicroOp::ReadRegister(rrr),
MicroOp::ReadRegister(A_REGISTER_ADDRESS),
MicroOp::PortOut,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
3)
}
Instruction::Comp { rrr } => {
([
MicroOp::ReadRegister(S_REGISTER_ADDRESS),
MicroOp::ReadRegister(rrr),
MicroOp::ReadRegister(FLAG_REGISTER_ADDRESS),
MicroOp::Compare,
MicroOp::WriteRegister(FLAG_REGISTER_ADDRESS),
MicroOp::Nop],
5)
}
Instruction::Stck { d: InstructionStckDirection::Push, r } => {
let [f, s] = address_pair(r);
([
MicroOp::ReadRegister(s),
MicroOp::StackPush,
MicroOp::ReadRegister(f),
MicroOp::StackPush,
MicroOp::Nop,
MicroOp::Nop],
4)
}
Instruction::Stck { d: InstructionStckDirection::Pop, r } => {
let [f, s] = address_pair(r);
([
MicroOp::StackPop,
MicroOp::WriteRegister(f),
MicroOp::StackPop,
MicroOp::WriteRegister(s),
MicroOp::Nop,
MicroOp::Nop],
4)
}
Instruction::Clrf => {
([
MicroOp::MakeImmediate(0),
MicroOp::WriteRegister(FLAG_REGISTER_ADDRESS),
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
2)
}
Instruction::Halt => {
([
MicroOp::Halt,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop,
MicroOp::Nop],
1)
}
}
}
}
fn address_pair(r: InstructionRegisterPair) -> [u8; 2] {
match r {
InstructionRegisterPair::Ab => [A_REGISTER_ADDRESS, B_REGISTER_ADDRESS],
InstructionRegisterPair::Cd => [C_REGISTER_ADDRESS, D_REGISTER_ADDRESS],
}
}
fn imm_address_pair(r: InstructionLoadImmediateWideRegisterPair) -> [u8; 2] {
match r {
InstructionLoadImmediateWideRegisterPair::Ab => [A_REGISTER_ADDRESS, B_REGISTER_ADDRESS],
InstructionLoadImmediateWideRegisterPair::Cd => [C_REGISTER_ADDRESS, D_REGISTER_ADDRESS],
InstructionLoadImmediateWideRegisterPair::Xy => [X_REGISTER_ADDRESS, Y_REGISTER_ADDRESS],
InstructionLoadImmediateWideRegisterPair::Adr => panic!("Wrong decomposition for LOAD IMM WIDE pair"),
}
}