diff --git a/src/main.rs b/src/main.rs index 41e96c2..eadce69 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,12 @@ +use clap::Parser; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct DoCoreOptions { + #[clap(short, long)] + instruction: String +} + #[derive(Debug)] struct Instruction { opcode: OpCode, @@ -28,6 +37,8 @@ enum OpCode { STW = 0x01, ADD = 0x02, XOR = 0x03, + SHL = 0x04, + SHR = 0x05 } impl OpCode { @@ -37,6 +48,8 @@ impl OpCode { 0x01 => OpCode::STW, 0x02 => OpCode::ADD, 0x03 => OpCode::XOR, + 0x04 => OpCode::SHL, + 0x05 => OpCode::SHR, _ => panic!("Unknown opcode {:?}", opcode), } } @@ -49,6 +62,37 @@ fn xor(op0: u32, op1: u32) -> u32 { op0 ^ op1 } +/// Logical shift to the left of op0, by op1 times. +/// +/// op0 << op1 +/// +/// # Arguments +/// +/// * `op0` - The number on which the operation will be done +/// * `op1` - How many shifts we do +/// +/// Returns the result +/// +fn shl(op0: u32, op1: u32) -> u32 { + op0 << op1 +} + +/// Logical shift to the right of op0, by op1 times. +/// +/// op0 >> op1 +/// +/// # Arguments +/// +/// * `op0` - The number on which the operation will be done +/// * `op1` - How many shifts we do +/// +/// Returns the result +/// +fn shr(op0: u32, op1: u32) -> u32 { + op0 >> op1 +} + + fn main() { // ADD R1, R3 -> Opcode is 2 (ADD), op0 is 1 (R1) and op1 is 3 (R3) // The first 6 bits of the instruction are the opcode (2): 0b000010 @@ -61,7 +105,7 @@ fn main() { // 1 8 4 2 // 0b0001100001000010 = 0x1842 let insn: u32 = 0x1842; - let mut r1: u32 = 20; + let mut r1: u32 = 0x10; let r3: u32 = 12; println!( @@ -75,11 +119,18 @@ fn main() { decoded_instruction ); - match decoded_instruction.opcode { - OpCode::ADD => r1 = add(r1, r3), - OpCode::XOR => r1 = xor(r1, r3), + let args = DoCoreOptions::parse(); + let instruction = u32::from_str_radix(args.instruction.trim_start_matches("0x"), 16).unwrap(); + + println!("{}", instruction); + + r1 = match decoded_instruction.opcode { + OpCode::ADD => add(r1, r3), + OpCode::XOR => xor(r1, r3), + OpCode::SHL => shl(r1, decoded_instruction.op1.into()), + OpCode::SHR => shr(r1, decoded_instruction.op1.into()), _ => panic!("Unknown opcode {:?}", decoded_instruction.opcode), - } + }; println!( "do-core-1: instruction {:#x?} Final CPU state [R1:{:#x?} R3:{:#x?}]", @@ -100,4 +151,79 @@ mod tests { assert_eq!(insn.op0, 1); assert_eq!(insn.op1, 3); } + + #[test] + fn test_instruction_disassemble_xor_r1_r3() { + let insn_bytes: u32 = 0x1843; + let insn = Instruction::disassemble(insn_bytes); + + assert_eq!(insn.opcode, OpCode::XOR); + assert_eq!(insn.op0, 1); + assert_eq!(insn.op1, 3); + } + + + #[test] + fn test_instruction_disassemble_ldw_r1_r3() { + let insn_bytes: u32 = 0x1840; + let insn = Instruction::disassemble(insn_bytes); + + assert_eq!(insn.opcode, OpCode::LDW); + assert_eq!(insn.op0, 1); + assert_eq!(insn.op1, 3); + } + + + #[test] + fn test_instruction_disassemble_stw_r2_r4() { + let insn_bytes: u32 = 0x2081; + let insn = Instruction::disassemble(insn_bytes); + + assert_eq!(insn.opcode, OpCode::STW); + assert_eq!(insn.op0, 2); + assert_eq!(insn.op1, 4); + } + + #[test] + fn test_instruction_disassemble_shl_r1_r3() { + let insn_bytes: u32 = 0x1844; + let insn = Instruction::disassemble(insn_bytes); + + assert_eq!(insn.opcode, OpCode::SHL); + assert_eq!(insn.op0, 1); + assert_eq!(insn.op1, 3); + } + + + #[test] + fn test_instruction_disassemble_shr_r1_r3() { + let insn_bytes: u32 = 0x1845; + let insn = Instruction::disassemble(insn_bytes); + + assert_eq!(insn.opcode, OpCode::SHR); + assert_eq!(insn.op0, 1); + assert_eq!(insn.op1, 3); + } + + #[test] + fn test_instruction_execution_shl_one_three() { + assert_eq!(crate::shl(0b1, 3), 0b1000) + } + + #[test] + #[should_panic] + fn test_instruction_execution_shl_one_thousand() { + assert_eq!(crate::shl(0b1, 1000), 0b0) + } + + #[test] + fn test_instruction_execution_shr_0b1000_three() { + assert_eq!(crate::shr(0b1000, 3), 0b1) + } + + #[test] + #[should_panic] + fn test_instruction_execution_shr_0b1000_thousand() { + assert_eq!(crate::shr(0b1000, 1000), 0b1) + } }