1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use faucon_asm::{Instruction, InstructionKind};

use super::*;

mod alu;
mod branch;
mod control;
mod data;
mod intr;
mod utils;
mod vm;

/// Processes the given instruction on the microprocessor and returns the amount
/// of CPU cycles the operation took.
pub fn process_instruction(cpu: &mut Cpu, insn: &Instruction) -> usize {
    let handler = get_handler(insn);
    handler(cpu, insn)
}

fn get_handler(insn: &Instruction) -> impl FnOnce(&mut Cpu, &Instruction) -> usize {
    match insn.kind() {
        InstructionKind::CMPU => alu::cmp,
        InstructionKind::CMPS => alu::cmp,
        InstructionKind::CMP => alu::cmp,
        InstructionKind::ADD => alu::addsub,
        InstructionKind::ADC => alu::addsub,
        InstructionKind::SUB => alu::addsub,
        InstructionKind::SBB => alu::addsub,
        InstructionKind::SHL => alu::shift,
        InstructionKind::SHLC => alu::shift,
        InstructionKind::SAR => alu::shift,
        InstructionKind::SHR => alu::shift,
        InstructionKind::SHRC => alu::shift,
        InstructionKind::NOT => alu::unary,
        InstructionKind::NEG => alu::unary,
        InstructionKind::HSWAP => alu::unary,
        InstructionKind::SETHI => alu::sethi,
        InstructionKind::CLEAR => alu::clear,
        InstructionKind::MULU => alu::mul,
        InstructionKind::MULS => alu::mul,
        InstructionKind::SEXT => alu::sext,
        InstructionKind::AND => alu::bitwise,
        InstructionKind::OR => alu::bitwise,
        InstructionKind::XOR => alu::bitwise,
        InstructionKind::XBIT => alu::xbit,
        InstructionKind::BSET => alu::bitop,
        InstructionKind::BCLR => alu::bitop,
        InstructionKind::BTGL => alu::bitop,
        InstructionKind::DIV => alu::divmod,
        InstructionKind::MOD => alu::divmod,
        InstructionKind::SETP => alu::setp,
        InstructionKind::MOV => control::mov,
        InstructionKind::CALL => branch::call,
        InstructionKind::LCALL => branch::call,
        InstructionKind::LBRA => branch::bra,
        InstructionKind::RET => branch::ret,
        InstructionKind::LD => data::ld,
        InstructionKind::ST => data::st,
        InstructionKind::PUSH => data::push,
        InstructionKind::POP => data::pop,
        InstructionKind::MPUSH => data::mpush,
        InstructionKind::MPOP => data::mpop,
        InstructionKind::MPOPADD => data::mpopadd,
        InstructionKind::MPOPRET => data::mpopret,
        InstructionKind::MPOPADDRET => data::mpopaddret,
        InstructionKind::HALT => control::exit,
        InstructionKind::SLEEP => control::sleep,
        InstructionKind::IMBLK => vm::ptlb,
        InstructionKind::IMTAG => vm::vtlb,
        InstructionKind::IMINV => vm::itlb,
        InstructionKind::IRET => intr::iret,
        InstructionKind::TRAP => intr::trap,
        _ => unimplemented!(),
    }
}