c6000_disassembler/
lib.rs1use std::io::{Error, ErrorKind, Result};
2
3use crate::instruction::{
4 C6000Instruction, InstructionInput,
5 branching::BranchInstruction,
6 fphead::CompactInstructionHeader,
7 invalid::InvalidInstruction,
8 memory::MemoryInstruction,
9 moving::{MoveConstantInstruction, MoveRegisterInstruction},
10 nop::NOPInstruction,
11};
12
13pub mod instruction;
14
15pub fn read_compact_instruction(input: InstructionInput) -> Result<Box<dyn C6000Instruction>> {
18 if let Ok(instruction) = MoveConstantInstruction::new_compact(&input) {
19 return Ok(Box::new(instruction));
20 }
21
22 if let Ok(instruction) = MoveRegisterInstruction::new_compact(&input) {
23 return Ok(Box::new(instruction));
24 }
25
26 if let Ok(instruction) = BranchInstruction::new_compact(&input) {
27 return Ok(Box::new(instruction));
28 }
29
30 if let Ok(instruction) = NOPInstruction::new_compact(&input) {
31 return Ok(Box::new(instruction));
32 }
33
34 Ok(Box::new(InvalidInstruction::new_compact(&input)?))
35}
36
37pub fn read_instruction(input: InstructionInput) -> Result<Box<dyn C6000Instruction>> {
40 if let Ok(instruction) = MoveConstantInstruction::new(&input) {
41 return Ok(Box::new(instruction));
42 }
43
44 if let Ok(instruction) = MoveRegisterInstruction::new(&input) {
45 return Ok(Box::new(instruction));
46 }
47
48 if let Ok(instruction) = BranchInstruction::new(&input) {
49 return Ok(Box::new(instruction));
50 }
51
52 if let Ok(instruction) = MemoryInstruction::new(&input) {
53 return Ok(Box::new(instruction));
54 }
55
56 if let Ok(instruction) = NOPInstruction::new(&input) {
57 return Ok(Box::new(instruction));
58 }
59
60 Ok(Box::new(InvalidInstruction::new(&input)?))
61}
62
63pub const INSTRUCTION_SIZE: usize = 4;
65pub const COMPACT_INSTRUCTION_SIZE: usize = 2;
67pub const PACKET_SIZE: usize = 8 * INSTRUCTION_SIZE;
69
70pub fn read_packet(
71 packet: [u8; PACKET_SIZE],
72 address: u32,
73) -> Result<Vec<Box<dyn C6000Instruction>>> {
74 let mut vec: Vec<Box<dyn C6000Instruction>> = vec![];
75 let Ok(fphead) = CompactInstructionHeader::new(&InstructionInput {
76 opcode: u32::from_le_bytes([
77 packet[PACKET_SIZE - 4],
78 packet[PACKET_SIZE - 3],
79 packet[PACKET_SIZE - 2],
80 packet[PACKET_SIZE - 1],
81 ]),
82 fphead: None,
83 pce1_address: address,
84 }) else {
85 return Err(Error::new(
86 ErrorKind::InvalidInput,
87 "Not a fetch packet, use read_instruction instead.",
88 ));
89 };
90
91 let mut index = 0;
92 let mut previous_p_bit = false;
93 while index < 7 * 4 {
94 let instruction = {
95 if fphead.layout[index / 4] {
96 let mut compact_instruction = read_compact_instruction(InstructionInput {
97 opcode: u16::from_le_bytes([packet[index], packet[index + 1]]) as u32,
98 fphead: Some(fphead.clone()),
99 pce1_address: address,
100 })?;
101 compact_instruction.set_parallel(previous_p_bit);
102 previous_p_bit = fphead.compact_p_bits[index / 2];
103 compact_instruction
104 } else {
105 let mut instruction = read_instruction(InstructionInput {
106 opcode: u32::from_le_bytes([
107 packet[index],
108 packet[index + 1],
109 packet[index + 2],
110 packet[index + 3],
111 ]),
112 fphead: Some(fphead.clone()),
113 pce1_address: address,
114 })?;
115 instruction.set_parallel(previous_p_bit);
116 previous_p_bit = instruction.get_p_bit();
117 instruction
118 }
119 };
120
121 if instruction.as_any().is::<CompactInstructionHeader>() {
122 return Err(Error::new(
123 ErrorKind::InvalidData,
124 "Compact instruction header found in unusual place",
125 ));
126 }
127
128 if instruction.is_compact() {
129 index += 2;
130 } else {
131 index += 4;
132 }
133 vec.push(instruction);
134 }
135
136 vec.push(Box::new(fphead));
137
138 Ok(vec)
139}