1extern crate core;
2
3use core::fmt;
4
5use yaxpeax_arch::AddressDiff;
6use yaxpeax_arch::Arch;
7use yaxpeax_arch::Decoder;
8use yaxpeax_arch::LengthedInstruction;
9use yaxpeax_arch::Reader;
10use yaxpeax_arch::StandardDecodeError;
11
12#[cfg_attr(feature="use-serde", derive(Serialize, Deserialize))]
13#[derive(Debug)]
14pub struct SM83;
15
16impl Arch for SM83 {
17 type Address = u16;
18 type Word = u8;
19 type Instruction = Instruction;
20 type DecodeError = StandardDecodeError;
21 type Decoder = InstDecoder;
22 type Operand = Operand;
23}
24
25#[derive(Debug, Copy, Clone)]
26pub struct Instruction {
27 opcode: Opcode,
28 operands: [Operand; 2],
29 length: u8,
30}
31
32impl Instruction {
33 pub fn opcode(&self) -> Opcode {
34 self.opcode
35 }
36
37 pub fn operands(&self) -> &[Operand; 2] {
38 &self.operands
39 }
40
41 pub fn length(&self) -> u8 {
42 self.length
43 }
44}
45
46impl Default for Instruction {
47 fn default() -> Instruction {
48 Instruction {
49 opcode: Opcode::NOP,
50 operands: [Operand::Nothing, Operand::Nothing],
51 length: 1,
52 }
53 }
54}
55
56impl fmt::Display for Instruction {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 write!(f, "{}", self.opcode())?;
59 let ops = self.operands();
60 if ops[0] != Operand::Nothing {
61 write!(f, " {}", ops[0])?;
62 }
63 if ops[1] != Operand::Nothing {
64 write!(f, ", {}", ops[1])?;
65 }
66 Ok(())
67 }
68}
69
70impl LengthedInstruction for Instruction {
71 type Unit = AddressDiff<<SM83 as Arch>::Address>;
72 fn min_size() -> Self::Unit {
73 AddressDiff::from_const(1)
74 }
75 fn len(&self) -> Self::Unit {
76 AddressDiff::from_const(self.length as u16)
77 }
78}
79
80impl yaxpeax_arch::Instruction for Instruction {
81 fn well_defined(&self) -> bool { true }
83}
84
85#[derive(Debug, Copy, Clone, PartialEq, Eq)]
86pub enum Operand {
87 A,
88 B,
89 C,
90 D,
91 E,
92 H,
93 L,
94 AF,
95 BC,
96 DE,
97 HL,
98 SP,
99 DerefHL,
100 DerefBC,
101 DerefDE,
102 DerefDecHL,
103 DerefIncHL,
104 DerefHighC,
105 DerefHighD8(u8),
106 SPWithOffset(i8),
107 Bit(u8),
108 D8(u8),
109 I8(i8),
110 R8(i8),
111 A16(u16),
112 D16(u16),
113
114 CondC,
115 CondNC,
116 CondZ,
117 CondNZ,
118
119 Nothing,
120}
121
122impl fmt::Display for Operand {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 match self {
125 Operand::A => write!(f, "a"),
126 Operand::B => write!(f, "b"),
127 Operand::C => write!(f, "c"),
128 Operand::D => write!(f, "d"),
129 Operand::E => write!(f, "e"),
130 Operand::H => write!(f, "h"),
131 Operand::L => write!(f, "l"),
132 Operand::AF => write!(f, "af"),
133 Operand::BC => write!(f, "bc"),
134 Operand::DE => write!(f, "de"),
135 Operand::HL => write!(f, "hl"),
136 Operand::SP => write!(f, "sp"),
137 Operand::DerefHL => write!(f, "[hl]"),
138 Operand::DerefBC => write!(f, "[bc]"),
139 Operand::DerefDE => write!(f, "[de]"),
140 Operand::DerefDecHL => write!(f, "[hl-]"),
141 Operand::DerefIncHL => write!(f, "[hl+]"),
142 Operand::DerefHighC => write!(f, "[0xff00 + c]"),
143 Operand::DerefHighD8(imm) => write!(f, "[$ff00 + ${:02x}]", imm),
144 Operand::SPWithOffset(imm) => {
145 if *imm == -128 {
146 write!(f, "[sp - $80]")
147 } else if *imm >= 0 {
148 write!(f, "[sp + ${:02x}]", imm)
149 } else {
150 write!(f, "[sp - ${:02x}]", -imm)
151 }
152 }
153 Operand::Bit(imm) => write!(f, "{}", imm),
154 Operand::D8(imm) => write!(f, "${:02x}", imm),
155 Operand::D16(imm) => write!(f, "${:04x}", imm),
156 Operand::I8(imm) => {
157 if *imm == -128 {
158 write!(f, "-0x80")
159 } else if *imm >= 0 {
160 write!(f, "${:02x}", imm)
161 } else {
162 write!(f, "-${:02x}", -imm)
163 }
164 }
165 Operand::R8(imm) => {
166 if *imm == -128 {
167 write!(f, "$-0x80")
168 } else if *imm >= 0 {
169 write!(f, "$+${:02x}", imm)
170 } else {
171 write!(f, "$-${:02x}", -imm)
172 }
173 }
174 Operand::A16(addr) => write!(f, "[${:4x}]", addr),
175
176 Operand::CondC => write!(f, "C"),
177 Operand::CondNC => write!(f, "nC"),
178 Operand::CondZ => write!(f, "Z"),
179 Operand::CondNZ => write!(f, "nZ"),
180
181 Operand::Nothing => write!(f, "nothing (BUG: should not be shown)"),
182 }
183 }
184}
185
186#[derive(Debug, Copy, Clone)]
187enum OperandSpec {
188 A,
189 B,
190 C,
191 D,
192 E,
193 H,
194 L,
195 AF,
196 BC,
197 DE,
198 HL,
199 SP,
200 DerefHL,
201 DerefBC,
202 DerefDE,
203 DerefDecHL,
204 DerefIncHL,
205 DerefHighC,
206 DerefHighD8,
207 SPWithOffset,
208 D8,
209 R8,
210 I8,
211 A16,
212 D16,
213
214 CondC,
215 CondNC,
216 CondZ,
217 CondNZ,
218
219 Bit(u8),
220 Imm(u8),
221
222 Nothing,
223}
224
225#[derive(Debug, Copy, Clone)]
226pub enum Opcode {
227 NOP,
228
229 LD,
230
231 DEC,
232 INC,
233
234 ADC,
235 ADD,
236 SBC,
237 SUB,
238
239 AND,
240 XOR,
241 OR,
242 CP,
243
244 POP,
245 PUSH,
246
247 JP,
248 JR,
249 CALL,
250 RET,
251 RETI,
252 HALT,
253 RST,
254 STOP,
255
256 RLCA,
257 RRCA,
258 RLA,
259 RRA,
260
261 DAA,
262 CPL,
263 SCF,
264 CCF,
265
266 DI,
267 EI,
268
269 LDH,
270
271 RLC,
272 RRC,
273 RL,
274 RR,
275 SLA,
276 SRA,
277 SWAP,
278 SRL,
279 BIT,
280 RES,
281 SET,
282}
283
284impl fmt::Display for Opcode {
285 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
286 match self {
287 Opcode::NOP => write!(f, "nop"),
288
289 Opcode::LD => write!(f, "ld"),
290
291 Opcode::DEC => write!(f, "dec"),
292 Opcode::INC => write!(f, "inc"),
293
294 Opcode::ADC => write!(f, "adc"),
295 Opcode::ADD => write!(f, "add"),
296 Opcode::SBC => write!(f, "sbc"),
297 Opcode::SUB => write!(f, "sub"),
298
299 Opcode::AND => write!(f, "and"),
300 Opcode::XOR => write!(f, "xor"),
301 Opcode::OR => write!(f, "or"),
302 Opcode::CP => write!(f, "cp"),
303
304 Opcode::POP => write!(f, "pop"),
305 Opcode::PUSH => write!(f, "push"),
306
307 Opcode::JP => write!(f, "jp"),
308 Opcode::JR => write!(f, "jr"),
309 Opcode::CALL => write!(f, "call"),
310 Opcode::RET => write!(f, "ret"),
311 Opcode::RETI => write!(f, "reti"),
312 Opcode::HALT => write!(f, "halt"),
313 Opcode::RST => write!(f, "rst"),
314 Opcode::STOP => write!(f, "stop"),
315
316 Opcode::RLCA => write!(f, "rlca"),
317 Opcode::RRCA => write!(f, "rrca"),
318 Opcode::RLA => write!(f, "rla"),
319 Opcode::RRA => write!(f, "rra"),
320
321 Opcode::DAA => write!(f, "daa"),
322 Opcode::CPL => write!(f, "cpl"),
323 Opcode::SCF => write!(f, "scf"),
324 Opcode::CCF => write!(f, "ccf"),
325
326 Opcode::DI => write!(f, "di"),
327 Opcode::EI => write!(f, "ei"),
328
329 Opcode::LDH => write!(f, "ldh"),
330
331 Opcode::RLC => write!(f, "rlc"),
332 Opcode::RRC => write!(f, "rrc"),
333 Opcode::RL => write!(f, "rl"),
334 Opcode::RR => write!(f, "rr"),
335 Opcode::SLA => write!(f, "sla"),
336 Opcode::SRA => write!(f, "sra"),
337 Opcode::SWAP => write!(f, "swap"),
338 Opcode::SRL => write!(f, "srl"),
339 Opcode::BIT => write!(f, "bit"),
340 Opcode::RES => write!(f, "res"),
341 Opcode::SET => write!(f, "set"),
342 }
343 }
344}
345
346#[derive(Debug)]
347pub struct InstDecoder { }
348
349impl Default for InstDecoder {
350 fn default() -> Self {
351 InstDecoder { }
352 }
353}
354
355const OPMAP: [OperandSpec; 8] = [
357 OperandSpec::B,
358 OperandSpec::C,
359 OperandSpec::D,
360 OperandSpec::E,
361 OperandSpec::H,
362 OperandSpec::L,
363 OperandSpec::DerefHL,
364 OperandSpec::A,
365];
366
367const UPPER_INSTRUCTIONS: [(Option<Opcode>, [OperandSpec; 2]); 64] = [
368 (Some(Opcode::RET), [OperandSpec::CondNZ, OperandSpec::Nothing]),
370 (Some(Opcode::POP), [OperandSpec::BC, OperandSpec::Nothing]),
371 (Some(Opcode::JP), [OperandSpec::CondNZ, OperandSpec::D16]),
372 (Some(Opcode::JP), [OperandSpec::D16, OperandSpec::Nothing]),
373 (Some(Opcode::CALL), [OperandSpec::CondNZ, OperandSpec::D16]),
374 (Some(Opcode::PUSH), [OperandSpec::BC, OperandSpec::Nothing]),
375 (Some(Opcode::ADD), [OperandSpec::D8, OperandSpec::Nothing]),
376 (Some(Opcode::RST), [OperandSpec::Imm(0x00), OperandSpec::Nothing]),
377 (Some(Opcode::RET), [OperandSpec::CondZ, OperandSpec::Nothing]),
379 (Some(Opcode::RET), [OperandSpec::Nothing, OperandSpec::Nothing]),
380 (Some(Opcode::JP), [OperandSpec::CondNC, OperandSpec::D16]),
381 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
382 (Some(Opcode::CALL), [OperandSpec::CondZ, OperandSpec::D16]),
383 (Some(Opcode::CALL), [OperandSpec::D16, OperandSpec::Nothing]),
384 (Some(Opcode::ADC), [OperandSpec::D8, OperandSpec::Nothing]),
385 (Some(Opcode::RST), [OperandSpec::Imm(0x08), OperandSpec::Nothing]),
386 (Some(Opcode::RET), [OperandSpec::CondNC, OperandSpec::Nothing]),
388 (Some(Opcode::POP), [OperandSpec::DE, OperandSpec::Nothing]),
389 (Some(Opcode::JP), [OperandSpec::CondNC, OperandSpec::D16]),
390 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
391 (Some(Opcode::CALL), [OperandSpec::CondNC, OperandSpec::D16]),
392 (Some(Opcode::PUSH), [OperandSpec::DE, OperandSpec::Nothing]),
393 (Some(Opcode::SUB), [OperandSpec::D8, OperandSpec::Nothing]),
394 (Some(Opcode::RST), [OperandSpec::Imm(0x10), OperandSpec::Nothing]),
395 (Some(Opcode::RET), [OperandSpec::CondC, OperandSpec::Nothing]),
397 (Some(Opcode::RETI), [OperandSpec::Nothing, OperandSpec::Nothing]),
398 (Some(Opcode::JP), [OperandSpec::CondC, OperandSpec::D16]),
399 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
400 (Some(Opcode::CALL), [OperandSpec::CondC, OperandSpec::D16]),
401 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
402 (Some(Opcode::SBC), [OperandSpec::D8, OperandSpec::Nothing]),
403 (Some(Opcode::RST), [OperandSpec::Imm(0x18), OperandSpec::Nothing]),
404 (Some(Opcode::LDH), [OperandSpec::DerefHighD8, OperandSpec::A]),
406 (Some(Opcode::POP), [OperandSpec::HL, OperandSpec::Nothing]),
407 (Some(Opcode::LDH), [OperandSpec::DerefHighC, OperandSpec::A]),
408 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
409 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
410 (Some(Opcode::PUSH), [OperandSpec::HL, OperandSpec::Nothing]),
411 (Some(Opcode::AND), [OperandSpec::D8, OperandSpec::Nothing]),
412 (Some(Opcode::RST), [OperandSpec::Imm(0x20), OperandSpec::Nothing]),
413 (Some(Opcode::ADD), [OperandSpec::SP, OperandSpec::I8]),
415 (Some(Opcode::JP), [OperandSpec::HL, OperandSpec::Nothing]),
416 (Some(Opcode::LD), [OperandSpec::A16, OperandSpec::A]),
417 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
418 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
419 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
420 (Some(Opcode::XOR), [OperandSpec::D8, OperandSpec::Nothing]),
421 (Some(Opcode::RST), [OperandSpec::Imm(0x28), OperandSpec::Nothing]),
422 (Some(Opcode::LDH), [OperandSpec::A, OperandSpec::DerefHighD8]),
424 (Some(Opcode::POP), [OperandSpec::AF, OperandSpec::Nothing]),
425 (Some(Opcode::LDH), [OperandSpec::A, OperandSpec::DerefHighC]),
426 (Some(Opcode::DI), [OperandSpec::Nothing, OperandSpec::Nothing]),
427 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
428 (Some(Opcode::PUSH), [OperandSpec::AF, OperandSpec::Nothing]),
429 (Some(Opcode::OR), [OperandSpec::D8, OperandSpec::Nothing]),
430 (Some(Opcode::RST), [OperandSpec::Imm(0x30), OperandSpec::Nothing]),
431 (Some(Opcode::LD), [OperandSpec::HL, OperandSpec::SPWithOffset]),
433 (Some(Opcode::LD), [OperandSpec::SP, OperandSpec::HL]),
434 (Some(Opcode::LD), [OperandSpec::A, OperandSpec::A16]),
435 (Some(Opcode::EI), [OperandSpec::Nothing, OperandSpec::Nothing]),
436 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
437 (None, [OperandSpec::Nothing, OperandSpec::Nothing]),
438 (Some(Opcode::CP), [OperandSpec::D8, OperandSpec::Nothing]),
439 (Some(Opcode::RST), [OperandSpec::Imm(0x38), OperandSpec::Nothing]),
440];
441
442impl Decoder<SM83> for InstDecoder {
443 fn decode_into<T: Reader<<SM83 as Arch>::Address, <SM83 as Arch>::Word>>(&self, inst: &mut Instruction, words: &mut T) -> Result<(), <SM83 as Arch>::DecodeError> {
444 let opc: u8 = words.next()?;
445 inst.length = 1;
446
447 let high = ((opc >> 3) & 0b111) as usize;
448 let low = (opc & 0b111) as usize;
449
450 if opc < 0x40 {
452 let (opcode, operands) = match low {
453 0 => {
454 match high {
456 0 => { (Opcode::NOP, [OperandSpec::Nothing, OperandSpec::Nothing]) },
457 1 => { (Opcode::LD, [OperandSpec::A16, OperandSpec::SP]) },
458 2 => { (Opcode::STOP, [OperandSpec::Nothing, OperandSpec::Nothing]) },
459 3 => { (Opcode::JR, [OperandSpec::R8, OperandSpec::Nothing]) },
460 4 => { (Opcode::JR, [OperandSpec::CondNZ, OperandSpec::R8]) },
461 5 => { (Opcode::JR, [OperandSpec::CondZ, OperandSpec::R8]) },
462 6 => { (Opcode::JR, [OperandSpec::CondNC, OperandSpec::R8]) },
463 7 => { (Opcode::JR, [OperandSpec::CondC, OperandSpec::R8]) },
464 _ => { unreachable!("impossible bit pattern"); }
465 }
466 }
467 1 => {
468 if high & 1 == 0 {
470 let opcode = Opcode::LD;
471 let ops = [[
472 OperandSpec::BC,
473 OperandSpec::DE,
474 OperandSpec::HL,
475 OperandSpec::SP,
476 ][high as usize >> 1], OperandSpec::D16];
477 (opcode, ops)
478 } else {
479 let opcode = Opcode::ADD;
480 let ops = [OperandSpec::HL, [
481 OperandSpec::BC,
482 OperandSpec::DE,
483 OperandSpec::HL,
484 OperandSpec::SP,
485 ][high as usize >> 1]];
486 (opcode, ops)
487 }
488 }
489 2 => {
490 let op = Opcode::LD;
491 if high & 1 == 0 {
492 let op0 = [
493 OperandSpec::DerefBC,
494 OperandSpec::DerefDE,
495 OperandSpec::DerefIncHL,
496 OperandSpec::DerefDecHL,
497 ][high as usize >> 1];
498 (op, [op0, OperandSpec::A])
499 } else {
500 let op1 = [
501 OperandSpec::DerefBC,
502 OperandSpec::DerefDE,
503 OperandSpec::DerefIncHL,
504 OperandSpec::DerefDecHL,
505 ][high as usize >> 1];
506 (op, [OperandSpec::A, op1])
507 }
508 }
509 3 => {
510 if high & 1 == 0 {
511 let op0 = [
512 OperandSpec::BC,
513 OperandSpec::DE,
514 OperandSpec::HL,
515 OperandSpec::SP,
516 ][high as usize >> 1];
517 (Opcode::INC, [op0, OperandSpec::Nothing])
518 } else {
519 let op0 = [
520 OperandSpec::BC,
521 OperandSpec::DE,
522 OperandSpec::HL,
523 OperandSpec::SP,
524 ][high as usize >> 1];
525 (Opcode::DEC, [op0, OperandSpec::Nothing])
526 }
527 }
528 4 => {
529 let op = Opcode::INC;
530 let op0 = [
531 OperandSpec::B,
532 OperandSpec::C,
533 OperandSpec::D,
534 OperandSpec::E,
535 OperandSpec::H,
536 OperandSpec::L,
537 OperandSpec::DerefHL,
538 OperandSpec::A,
539 ][high as usize];
540 (op, [op0, OperandSpec::Nothing])
541 }
542 5 => {
543 let op = Opcode::DEC;
544 let op0 = [
545 OperandSpec::B,
546 OperandSpec::C,
547 OperandSpec::D,
548 OperandSpec::E,
549 OperandSpec::H,
550 OperandSpec::L,
551 OperandSpec::DerefHL,
552 OperandSpec::A,
553 ][high as usize];
554 (op, [op0, OperandSpec::Nothing])
555 }
556 6 => {
557 let op = Opcode::LD;
558 let op0 = [
559 OperandSpec::B,
560 OperandSpec::C,
561 OperandSpec::D,
562 OperandSpec::E,
563 OperandSpec::H,
564 OperandSpec::L,
565 OperandSpec::DerefHL,
566 OperandSpec::A,
567 ][high as usize];
568 (op, [op0, OperandSpec::D8])
569 }
570 7 => {
571 let op = [
573 Opcode::RLCA,
574 Opcode::RRCA,
575 Opcode::RLA,
576 Opcode::RRA,
577 Opcode::DAA,
578 Opcode::CPL,
579 Opcode::SCF,
580 Opcode::CCF,
581 ][high as usize];
582 (op, [OperandSpec::Nothing, OperandSpec::Nothing])
583 }
584 _ => {
585 unreachable!("impossible bit pattern");
586 }
587 };
588 inst.opcode = opcode;
589 interpret_operands(words, inst, operands)?;
590 return Ok(());
591 } else if opc < 0x80 {
592 if opc == 0x76 {
593 inst.opcode = Opcode::HALT;
594 inst.operands = [Operand::Nothing, Operand::Nothing];
595 return Ok(());
596 } else {
597 inst.opcode = Opcode::LD;
598 interpret_operands(words, inst, [OPMAP[high], OPMAP[low]])?;
599 return Ok(());
600 }
601 } else if opc < 0xc0 {
602 const OPCODES: [Opcode; 8] = [
603 Opcode::ADD,
604 Opcode::ADC,
605 Opcode::SUB,
606 Opcode::SBC,
607 Opcode::AND,
608 Opcode::XOR,
609 Opcode::OR,
610 Opcode::CP,
611 ];
612 inst.opcode = OPCODES[high];
613 let operands = [OPMAP[low], OperandSpec::Nothing];
614 interpret_operands(words, inst, operands)?;
615 return Ok(());
616 } else {
617 if opc == 0xcb {
618 let opc: u8 = words.next()?;
620 inst.length += 1;
621 if opc < 0x40 {
622 let high = (opc >> 3) & 0b111;
623 let low = opc & 0b111;
624 const LOW_OP: [OperandSpec; 8] = [
625 OperandSpec::B,
626 OperandSpec::C,
627 OperandSpec::D,
628 OperandSpec::E,
629 OperandSpec::H,
630 OperandSpec::L,
631 OperandSpec::DerefHL,
632 OperandSpec::A,
633 ];
634 let operands = [LOW_OP[low as usize], OperandSpec::Nothing];
635 const OPCODES: [Opcode; 8] = [
636 Opcode::RLC,
637 Opcode::RRC,
638 Opcode::RL,
639 Opcode::RR,
640 Opcode::SLA,
641 Opcode::SRA,
642 Opcode::SWAP,
643 Opcode::SRL,
644 ];
645 inst.opcode = OPCODES[high as usize];
646 interpret_operands(words, inst, operands)?;
647 return Ok(());
648 } else {
649 let bit = (opc >> 3) & 0b111;
650 let low = opc & 0b111;
651 const LOW_OP: [OperandSpec; 8] = [
652 OperandSpec::B,
653 OperandSpec::C,
654 OperandSpec::D,
655 OperandSpec::E,
656 OperandSpec::H,
657 OperandSpec::L,
658 OperandSpec::DerefHL,
659 OperandSpec::A,
660 ];
661 let operands = [OperandSpec::Bit(bit), LOW_OP[low as usize]];
662 const OPCODES: [Opcode; 3] = [
663 Opcode::BIT,
664 Opcode::RES,
665 Opcode::SET,
666 ];
667 inst.opcode = OPCODES[(opc >> 6) as usize - 1];
668 interpret_operands(words, inst, operands)?;
669 return Ok(());
670 }
671 } else {
672 let (maybe_opcode, operands) = UPPER_INSTRUCTIONS[opc as usize - 0xc0];
674 if let Some(opcode) = maybe_opcode {
675 inst.opcode = opcode;
676 interpret_operands(words, inst, operands)?;
677 return Ok(());
678 } else {
679 return Err(StandardDecodeError::InvalidOpcode);
680 }
681 }
682 }
683 }
684}
685
686fn interpret_operands<T: Reader<<SM83 as Arch>::Address, <SM83 as Arch>::Word>>(words: &mut T, inst: &mut Instruction, operands: [OperandSpec; 2]) -> Result<(), <SM83 as Arch>::DecodeError> {
687 inst.operands[0] = interpret_operand(words, inst, operands[0])?;
688 inst.operands[1] = interpret_operand(words, inst, operands[1])?;
689 Ok(())
690}
691
692fn interpret_operand<T: Reader<<SM83 as Arch>::Address, <SM83 as Arch>::Word>>(words: &mut T, inst: &mut Instruction, operand: OperandSpec) -> Result<Operand, <SM83 as Arch>::DecodeError> {
693 let operand = match operand {
694 OperandSpec::A => Operand::A,
695 OperandSpec::B => Operand::B,
696 OperandSpec::C => Operand::C,
697 OperandSpec::D => Operand::D,
698 OperandSpec::E => Operand::E,
699 OperandSpec::H => Operand::H,
700 OperandSpec::L => Operand::L,
701 OperandSpec::AF => Operand::AF,
702 OperandSpec::BC => Operand::BC,
703 OperandSpec::DE => Operand::DE,
704 OperandSpec::HL => Operand::HL,
705 OperandSpec::SP => Operand::SP,
706 OperandSpec::DerefHL => Operand::DerefHL,
707 OperandSpec::DerefBC => Operand::DerefBC,
708 OperandSpec::DerefDE => Operand::DerefDE,
709 OperandSpec::DerefDecHL => Operand::DerefDecHL,
710 OperandSpec::DerefIncHL => Operand::DerefIncHL,
711 OperandSpec::D8 => {
712 let imm = words.next()?;
713 inst.length += 1;
714 Operand::D8(imm)
715 }
716 OperandSpec::DerefHighC => {
717 Operand::DerefHighC
718 }
719 OperandSpec::DerefHighD8 => {
720 let imm = words.next()?;
721 inst.length += 1;
722 Operand::DerefHighD8(imm)
723 }
724 OperandSpec::R8 => {
725 let imm = words.next()?;
726 inst.length += 1;
727 Operand::R8(imm as i8)
728 }
729 OperandSpec::I8 => {
730 let imm = words.next()?;
731 inst.length += 1;
732 Operand::I8(imm as i8)
733 }
734 OperandSpec::A16 => {
735 let imm =
736 (words.next()? as u16) |
737 ((words.next()? as u16) << 8);
738 inst.length += 2;
739 Operand::A16(imm as u16)
740 }
741 OperandSpec::D16 => {
742 let imm =
743 (words.next()? as u16) |
744 ((words.next()? as u16) << 8);
745 inst.length += 2;
746 Operand::D16(imm as u16)
747 }
748 OperandSpec::SPWithOffset => {
749 let imm = words.next()?;
750 inst.length += 1;
751 Operand::SPWithOffset(imm as i8)
752 }
753
754 OperandSpec::Imm(u) => {
755 Operand::D8(u)
756 }
757 OperandSpec::Bit(u) => {
758 Operand::Bit(u)
759 }
760
761 OperandSpec::CondC => Operand::CondC,
762 OperandSpec::CondNC => Operand::CondNC,
763 OperandSpec::CondZ => Operand::CondZ,
764 OperandSpec::CondNZ => Operand::CondNZ,
765
766 OperandSpec::Nothing => Operand::Nothing,
767 };
768 Ok(operand)
769}