1use std::fmt;
2
3use crate::DecodeError;
4use crate::Result;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
16pub enum Operand {
17 RegisterDirect(u8),
19 Indexed((u8, i16)),
24 RegisterIndirect(u8),
28 RegisterIndirectAutoIncrement(u8),
31 Symbolic(i16),
35 Immediate(u16),
39 Absolute(u16),
44 Constant(i8),
47}
48
49impl Operand {
50 pub fn size(&self) -> usize {
51 match self {
52 Self::RegisterDirect(_) => 0,
53 Self::Indexed(_) => 2,
54 Self::RegisterIndirect(_) => 0,
55 Self::RegisterIndirectAutoIncrement(_) => 0,
56 Self::Symbolic(_) => 2,
57 Self::Immediate(_) => 2,
58 Self::Absolute(_) => 2,
59 Self::Constant(_) => 0,
60 }
61 }
62}
63
64impl fmt::Display for Operand {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 Self::RegisterDirect(r) => match r {
68 0 => write!(f, "pc"),
69 1 => write!(f, "sp"),
70 2 => write!(f, "sr"),
71 3 => write!(f, "cg"),
72 _ => write!(f, "r{}", r),
73 },
74 Self::Indexed((r, i)) => match r {
75 1 => {
76 if *i >= 0 {
77 write!(f, "{:#x}(sp)", i)
78 } else {
79 write!(f, "-{:#x}(sp)", -i)
80 }
81 }
82 3 => {
83 if *i >= 0 {
84 write!(f, "{:#x}(cg)", i)
85 } else {
86 write!(f, "-{:#x}(cg)", -i)
87 }
88 }
89 4..=15 => {
90 if *i >= 0 {
91 write!(f, "{:#x}(r{})", i, r)
92 } else {
93 write!(f, "-{:#x}(r{})", -i, r)
94 }
95 }
96 _ => unreachable!(),
97 },
98 Self::RegisterIndirect(r) => {
99 if *r == 1 {
100 write!(f, "@sp")
101 } else {
102 write!(f, "@r{}", r)
103 }
104 }
105 Self::RegisterIndirectAutoIncrement(r) => {
106 if *r == 1 {
107 write!(f, "@sp+")
108 } else {
109 write!(f, "@r{}+", r)
110 }
111 }
112 Self::Symbolic(i) => {
113 if *i >= 0 {
114 write!(f, "#{:#x}(pc)", i)
115 } else {
116 write!(f, "#-{:#x}(pc)", -i)
117 }
118 }
119 Self::Immediate(i) => {
120 if *i & 0x8000 == 0 {
121 write!(f, "#{:#x}", i)
122 } else {
123 write!(f, "#-{:#x}", *i as i16)
124 }
125 }
126 Self::Absolute(a) => write!(f, "&{:#x}", a),
127 Self::Constant(i) => {
128 if *i >= 0 {
129 write!(f, "#{:#x}", i)
130 } else {
131 write!(f, "#-{:#x}", -i)
132 }
133 }
134 }
135 }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq)]
143pub enum OperandWidth {
144 Byte,
145 Word,
146}
147
148impl From<u8> for OperandWidth {
149 fn from(val: u8) -> Self {
150 match val {
151 0 => OperandWidth::Word,
152 1 => OperandWidth::Byte,
153 _ => unreachable!(),
154 }
155 }
156}
157
158pub fn parse_source(register: u8, source: u16, data: &[u8]) -> Result<(Operand, &[u8])> {
163 match source {
164 0 => match register {
165 3 => Ok((Operand::Constant(0), data)),
166 0..=2 | 4..=15 => Ok((Operand::RegisterDirect(register), data)),
167 _ => Err(DecodeError::InvalidSource((source, register))),
168 },
169 1 => match register {
170 0 => {
171 if data.len() < 2 {
172 Err(DecodeError::MissingSource)
173 } else {
174 let (bytes, remaining_data) = data.split_at(std::mem::size_of::<u16>());
175 let second_word = i16::from_le_bytes(bytes.try_into().unwrap());
176 Ok((Operand::Symbolic(second_word), remaining_data))
177 }
178 }
179 2 => {
180 if data.len() < 2 {
181 Err(DecodeError::MissingSource)
182 } else {
183 let (bytes, remaining_data) = data.split_at(std::mem::size_of::<u16>());
184 let second_word = u16::from_le_bytes(bytes.try_into().unwrap());
185 Ok((Operand::Absolute(second_word), remaining_data))
186 }
187 }
188 3 => Ok((Operand::Constant(1), data)),
189 1 | 4..=15 => {
190 if data.len() < 2 {
191 Err(DecodeError::MissingSource)
192 } else {
193 let (bytes, remaining_data) = data.split_at(std::mem::size_of::<u16>());
194 let second_word = i16::from_le_bytes(bytes.try_into().unwrap());
195 Ok((Operand::Indexed((register, second_word)), remaining_data))
196 }
197 }
198 _ => Err(DecodeError::InvalidSource((source, register))),
199 },
200 2 => match register {
201 2 => Ok((Operand::Constant(4), data)),
202 3 => Ok((Operand::Constant(2), data)),
203 0..=1 | 4..=15 => Ok((Operand::RegisterIndirect(register), data)),
204 _ => Err(DecodeError::InvalidSource((source, register))),
205 },
206 3 => match register {
207 0 => {
208 if data.len() < 2 {
209 Err(DecodeError::MissingSource)
210 } else {
211 let (bytes, remaining_data) = data.split_at(std::mem::size_of::<u16>());
212 let second_word = u16::from_le_bytes(bytes.try_into().unwrap());
213 Ok((Operand::Immediate(second_word), remaining_data))
214 }
215 }
216 2 => Ok((Operand::Constant(8), data)),
217 3 => Ok((Operand::Constant(-1), data)),
218 1 | 4..=15 => Ok((Operand::RegisterIndirectAutoIncrement(register), data)),
219 _ => Err(DecodeError::InvalidSource((source, register))),
220 },
221 _ => Err(DecodeError::InvalidSource((source, register))),
222 }
223}
224
225pub fn parse_destination(register: u8, source: u16, data: &[u8]) -> Result<Operand> {
230 match source {
231 0 => Ok(Operand::RegisterDirect(register)),
232 1 => {
233 if data.len() < 2 {
234 Err(DecodeError::MissingDestination)
235 } else {
236 let (bytes, _) = data[0..2].split_at(std::mem::size_of::<u16>());
237 let raw_operand = u16::from_le_bytes(bytes.try_into().unwrap());
238 let index = raw_operand;
239 match register {
240 0 => Ok(Operand::Symbolic(index as i16)),
241 2 => Ok(Operand::Absolute(raw_operand)),
242 1 | 3..=15 => Ok(Operand::Indexed((register, index as i16))),
243 _ => Err(DecodeError::InvalidDestination((source, register))),
244 }
245 }
246 }
247 _ => Err(DecodeError::InvalidDestination((source, register))),
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn source_pc_symbolic() {
257 let data = [0x2, 0x0];
258 let source = parse_source(0, 1, &data);
259 assert_eq!(source, Ok((Operand::Symbolic(2), &data[2..])));
260 }
261
262 #[test]
263 fn source_pc_symbolic_missing_data() {
264 let data = [];
265 let source = parse_source(0, 1, &data);
266 assert_eq!(source, Err(DecodeError::MissingSource))
267 }
268
269 #[test]
270 fn source_pc_immediate() {
271 let data = [0x2, 0x0];
272 let source = parse_source(0, 3, &data);
273 assert_eq!(source, Ok((Operand::Immediate(2), &data[2..])));
274 }
275
276 #[test]
277 fn source_pc_immediate_high_bit() {
278 let data = [0xfe, 0xff];
279 let source = parse_source(0, 3, &data);
280 assert_eq!(source, Ok((Operand::Immediate(65534), &data[2..])));
281 }
282
283 #[test]
284 fn source_pc_immediate_missing_data() {
285 let data = [];
286 let source = parse_source(0, 3, &data);
287 assert_eq!(source, Err(DecodeError::MissingSource))
288 }
289
290 #[test]
291 fn source_pc_invalid_source() {
292 let data = [0xfe, 0xff];
293 let source = parse_source(0, 5, &data);
294 assert_eq!(source, Err(DecodeError::InvalidSource((5, 0))));
295 }
296
297 #[test]
298 fn source_sr_absolute() {
299 let data = [0x2, 0x0];
300 let source = parse_source(2, 1, &data);
301 assert_eq!(source, Ok((Operand::Absolute(2), &data[2..])));
302 }
303
304 #[test]
305 fn source_sr_absolute_missing_data() {
306 let data = [];
307 let source = parse_source(2, 1, &data);
308 assert_eq!(source, Err(DecodeError::MissingSource));
309 }
310
311 #[test]
312 fn source_sr_constant_four() {
313 let data = [];
314 let source = parse_source(2, 2, &data);
315 assert_eq!(source, Ok((Operand::Constant(4), &data[..])));
316 }
317
318 #[test]
319 fn source_sr_constant_eight() {
320 let data = [];
321 let source = parse_source(2, 3, &data);
322 assert_eq!(source, Ok((Operand::Constant(8), &data[..])));
323 }
324
325 #[test]
326 fn source_sr_invalid_source() {
327 let data = [];
328 let source = parse_source(2, 4, &data);
329 assert_eq!(source, Err(DecodeError::InvalidSource((4, 2))));
330 }
331
332 #[test]
333 fn source_cg_zero() {
334 let data = [];
335 let source = parse_source(3, 0, &data);
336 assert_eq!(source, Ok((Operand::Constant(0), &data[..])));
337 }
338
339 #[test]
340 fn source_cg_one() {
341 let data = [];
342 let source = parse_source(3, 1, &data);
343 assert_eq!(source, Ok((Operand::Constant(1), &data[..])));
344 }
345
346 #[test]
347 fn source_cg_two() {
348 let data = [];
349 let source = parse_source(3, 2, &data);
350 assert_eq!(source, Ok((Operand::Constant(2), &data[..])));
351 }
352
353 #[test]
354 fn source_cg_negative_one() {
355 let data = [];
356 let source = parse_source(3, 3, &data);
357 assert_eq!(source, Ok((Operand::Constant(-1), &data[..])));
358 }
359
360 #[test]
361 fn source_cg_invalid_source() {
362 let data = [];
363 let source = parse_source(3, 4, &data);
364 assert_eq!(source, Err(DecodeError::InvalidSource((4, 3))));
365 }
366
367 #[test]
368 fn source_gp_register_direct() {
369 let data = [];
370 let source = parse_source(9, 0, &data);
371 assert_eq!(source, Ok((Operand::RegisterDirect(9), &data[..])));
372 }
373
374 #[test]
375 fn source_gp_register_indexed() {
376 let data = [0x2, 0x0];
377 let source = parse_source(9, 1, &data);
378 assert_eq!(source, Ok((Operand::Indexed((9, 2)), &data[2..])));
379 }
380
381 #[test]
382 fn source_gp_register_indexed_negative() {
383 let data = [0xfd, 0xff];
384 let source = parse_source(9, 1, &data);
385 assert_eq!(source, Ok((Operand::Indexed((9, -3)), &data[2..])));
386 }
387
388 #[test]
389 fn source_gp_register_indirect() {
390 let data = [];
391 let source = parse_source(9, 2, &data);
392 assert_eq!(source, Ok((Operand::RegisterIndirect(9), &data[..])));
393 }
394
395 #[test]
396 fn source_gp_register_indirect_auto_increment() {
397 let data = [];
398 let source = parse_source(9, 3, &data);
399 assert_eq!(
400 source,
401 Ok((Operand::RegisterIndirectAutoIncrement(9), &data[..]))
402 );
403 }
404
405 #[test]
406 fn source_gp_invalid_source() {
407 let data = [];
408 let source = parse_source(9, 4, &data);
409 assert_eq!(source, Err(DecodeError::InvalidSource((4, 9))));
410 }
411
412 #[test]
413 fn destination_register_direct() {
414 let data = [];
415 let destination = parse_destination(9, 0, &data);
416 assert_eq!(destination, Ok(Operand::RegisterDirect(9)));
417 }
418
419 #[test]
420 fn destination_register_indexed() {
421 let data = [0x2, 0x0];
422 let destination = parse_destination(9, 1, &data);
423 assert_eq!(destination, Ok(Operand::Indexed((9, 2))));
424 }
425
426 #[test]
427 fn destination_register_indexed_negative() {
428 let data = [0xfe, 0xff];
429 let destination = parse_destination(9, 1, &data);
430 assert_eq!(destination, Ok(Operand::Indexed((9, -2))));
431 }
432
433 #[test]
434 fn destination_register_symbolic() {
435 let data = [0x2, 0x0];
436 let destination = parse_destination(0, 1, &data);
437 assert_eq!(destination, Ok(Operand::Symbolic(2)));
438 }
439
440 #[test]
441 fn destination_register_symbolic_negative() {
442 let data = [0xfe, 0xff];
443 let destination = parse_destination(0, 1, &data);
444 assert_eq!(destination, Ok(Operand::Symbolic(-2)));
445 }
446
447 #[test]
448 fn destination_register_absolute() {
449 let data = [0x2, 0x0];
450 let destination = parse_destination(2, 1, &data);
451 assert_eq!(destination, Ok(Operand::Absolute(2)));
452 }
453
454 #[test]
455 fn destination_invalid_source() {
456 let data = [];
457 let destination = parse_destination(9, 3, &data);
458 assert_eq!(destination, Err(DecodeError::InvalidDestination((3, 9))));
459 }
460}