1use super::Opcode;
2use std::collections::HashMap;
3use std::{num, str};
4
5trait NumFromStrRadix: Sized + PartialOrd + Ord + Eq {
6 type FromStrRadixErr;
7 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
8}
9
10impl NumFromStrRadix for u8 {
11 type FromStrRadixErr = num::ParseIntError;
12 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
13 Self::from_str_radix(str, radix)
14 }
15}
16impl NumFromStrRadix for u16 {
17 type FromStrRadixErr = num::ParseIntError;
18 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
19 Self::from_str_radix(str, radix)
20 }
21}
22
23fn parse_prefix<T: NumFromStrRadix<FromStrRadixErr = num::ParseIntError> + str::FromStr>(
24 s: &str,
25) -> Result<T, ()> {
26 if let Some(s) = s.trim().strip_prefix("0x") {
27 T::from_str_radix(s, 16).or(Err(()))
28 } else if let Some(s) = s.strip_prefix("0o") {
29 T::from_str_radix(s, 8).or(Err(()))
30 } else if let Some(s) = s.strip_prefix("0b") {
31 T::from_str_radix(s, 2).or(Err(()))
32 } else {
33 s.parse::<T>().or(Err(()))
34 }
35}
36
37pub fn tokenize(src: &str) -> Result<Vec<Opcode>, ()> {
38 let mut out = Vec::new();
39
40 let mut err = false;
41 let mut err2 = false;
42 let mut err3 = false;
43
44 let mut s = String::new();
45
46 for line in src.lines() {
47 if let Some(com) = line.find('#') {
48 s.push_str(&line[..com]);
49 } else if let Some(com) = line.find(';') {
50 s.push_str(&line[..com]);
51 } else {
52 s.push_str(&line[..]);
53 }
54 s.push('\n');
55 }
56
57 let mut splitted = s.split_ascii_whitespace();
58
59 let mut pc = 0;
60 let mut labels = HashMap::new();
61 let mut defined = HashMap::new();
62
63 let mut next_byte = |s: &str| {
64 if let Ok(v) = parse_prefix(s) {
65 v
66 } else {
67 eprintln!("Expected literal byte instead of {}.", s);
68 err2 = true;
69 0u8
70 }
71 };
72
73 let mut next_word = |s: &str| {
74 if let Ok(v) = parse_prefix(s) {
75 v
76 } else {
77 eprintln!("Expected literal word instead of {}.", s);
78 err3 = true;
79 0u16
80 }
81 };
82
83 let next_address = |idx: usize,
84 pc: u16,
85 s: &str,
86 h: &mut HashMap<String, Vec<usize>>,
87 h2: &mut HashMap<String, u16>| {
88 if let Ok(v) = parse_prefix(s) {
89 v
90 } else if s == "$" {
91 pc - 3
92 } else if let Some(v) = h2.get(s) {
93 *v as u16
94 } else if let Some(vec) = h.get_mut(s) {
95 vec.push(idx);
96 0u16
97 } else {
98 h.insert(s.into(), vec![idx]);
99 0u16
100 }
101 };
102
103 while let Some(w) = splitted.next() {
104 let w = w.to_ascii_lowercase();
105
106 if w.ends_with(':') {
107 if defined.insert(w[..w.len() - 1].to_string(), pc).is_some() {
108 eprintln!("Labels redefined ({}).", &w[..w.len() - 1]);
109 err = true;
110 }
111 } else {
112 match &w[..] {
113 "nop" => {
114 pc += 1;
115 out.push(Opcode::Nop);
116 }
117 "rlc" => {
118 pc += 1;
119 out.push(Opcode::Rlc);
120 }
121 "rrc" => {
122 pc += 1;
123 out.push(Opcode::Rrc);
124 }
125 "ral" => {
126 pc += 1;
127 out.push(Opcode::Ral);
128 }
129 "rar" => {
130 pc += 1;
131 out.push(Opcode::Rar);
132 }
133 "shld" => {
134 pc += 3;
135 out.push(Opcode::Shld(next_address(
136 out.len(),
137 pc,
138 splitted.next().unwrap(),
139 &mut labels,
140 &mut defined,
141 )));
142 }
143 "daa" => {
144 pc += 1;
145 out.push(Opcode::Daa);
146 }
147 "lhld" => {
148 pc += 3;
149 out.push(Opcode::Lhld(next_address(
150 out.len(),
151 pc,
152 splitted.next().unwrap(),
153 &mut labels,
154 &mut defined,
155 )));
156 }
157 "cma" => {
158 pc += 1;
159 out.push(Opcode::Cma);
160 }
161 "sta" => {
162 pc += 3;
163 out.push(Opcode::Sta(next_address(
164 out.len(),
165 pc,
166 splitted.next().unwrap(),
167 &mut labels,
168 &mut defined,
169 )));
170 }
171 "stc" => {
172 pc += 1;
173 out.push(Opcode::Stc);
174 }
175 "lda" => {
176 pc += 3;
177 out.push(Opcode::Lda(next_address(
178 out.len(),
179 pc,
180 splitted.next().unwrap(),
181 &mut labels,
182 &mut defined,
183 )));
184 }
185 "cmc" => {
186 pc += 1;
187 out.push(Opcode::Cmc);
188 }
189 "hlt" => {
190 pc += 1;
191 out.push(Opcode::Hlt);
192 }
193 "rnz" => {
194 pc += 1;
195 out.push(Opcode::Rnz);
196 }
197 "jnz" => {
198 pc += 3;
199 out.push(Opcode::Jnz(next_address(
200 out.len(),
201 pc,
202 splitted.next().unwrap(),
203 &mut labels,
204 &mut defined,
205 )));
206 }
207 "jmp" => {
208 pc += 3;
209 out.push(Opcode::Jmp(next_address(
210 out.len(),
211 pc,
212 splitted.next().unwrap(),
213 &mut labels,
214 &mut defined,
215 )));
216 }
217 "cnz" => {
218 pc += 3;
219 out.push(Opcode::Cnz(next_address(
220 out.len(),
221 pc,
222 splitted.next().unwrap(),
223 &mut labels,
224 &mut defined,
225 )));
226 }
227 "rz" => {
228 pc += 1;
229 out.push(Opcode::Rz);
230 }
231 "ret" => {
232 pc += 1;
233 out.push(Opcode::Ret);
234 }
235 "jz" => {
236 pc += 3;
237 out.push(Opcode::Jz(next_address(
238 out.len(),
239 pc,
240 splitted.next().unwrap(),
241 &mut labels,
242 &mut defined,
243 )));
244 }
245 "cz" => {
246 pc += 3;
247 out.push(Opcode::Cz(next_address(
248 out.len(),
249 pc,
250 splitted.next().unwrap(),
251 &mut labels,
252 &mut defined,
253 )));
254 }
255 "call" => {
256 pc += 3;
257 out.push(Opcode::Call(next_address(
258 out.len(),
259 pc,
260 splitted.next().unwrap(),
261 &mut labels,
262 &mut defined,
263 )));
264 }
265 "rnc" => {
266 pc += 1;
267 out.push(Opcode::Rnc);
268 }
269 "jnc" => {
270 pc += 3;
271 out.push(Opcode::Jnc(next_address(
272 out.len(),
273 pc,
274 splitted.next().unwrap(),
275 &mut labels,
276 &mut defined,
277 )));
278 }
279 "cnc" => {
280 pc += 3;
281 out.push(Opcode::Cnc(next_address(
282 out.len(),
283 pc,
284 splitted.next().unwrap(),
285 &mut labels,
286 &mut defined,
287 )));
288 }
289 "rc" => {
290 pc += 1;
291 out.push(Opcode::Rc);
292 }
293 "jc" => {
294 pc += 3;
295 out.push(Opcode::Jc(next_address(
296 out.len(),
297 pc,
298 splitted.next().unwrap(),
299 &mut labels,
300 &mut defined,
301 )));
302 }
303 "cc" => {
304 pc += 3;
305 out.push(Opcode::Cc(next_address(
306 out.len(),
307 pc,
308 splitted.next().unwrap(),
309 &mut labels,
310 &mut defined,
311 )));
312 }
313 "rpo" => {
314 pc += 1;
315 out.push(Opcode::Rpo);
316 }
317 "jpo" => {
318 pc += 3;
319 out.push(Opcode::Jpo(next_address(
320 out.len(),
321 pc,
322 splitted.next().unwrap(),
323 &mut labels,
324 &mut defined,
325 )));
326 }
327 "xthl" => {
328 pc += 1;
329 out.push(Opcode::Xthl);
330 }
331 "cpo" => {
332 pc += 3;
333 out.push(Opcode::Cpo(next_address(
334 out.len(),
335 pc,
336 splitted.next().unwrap(),
337 &mut labels,
338 &mut defined,
339 )));
340 }
341 "rpe" => {
342 pc += 1;
343 out.push(Opcode::Rpe);
344 }
345 "pchl" => {
346 pc += 1;
347 out.push(Opcode::Pchl);
348 }
349 "jpe" => {
350 pc += 3;
351 out.push(Opcode::Jpe(next_address(
352 out.len(),
353 pc,
354 splitted.next().unwrap(),
355 &mut labels,
356 &mut defined,
357 )));
358 }
359 "xchg" => {
360 pc += 1;
361 out.push(Opcode::Xchg);
362 }
363 "cpe" => {
364 pc += 3;
365 out.push(Opcode::Cpe(next_address(
366 out.len(),
367 pc,
368 splitted.next().unwrap(),
369 &mut labels,
370 &mut defined,
371 )));
372 }
373 "rp" => {
374 pc += 1;
375 out.push(Opcode::Rp);
376 }
377 "jp" => {
378 pc += 3;
379 out.push(Opcode::Jp(next_address(
380 out.len(),
381 pc,
382 splitted.next().unwrap(),
383 &mut labels,
384 &mut defined,
385 )));
386 }
387 "di" => {
388 pc += 1;
389 out.push(Opcode::Di);
390 }
391 "cp" => {
392 pc += 3;
393 out.push(Opcode::Cp(next_address(
394 out.len(),
395 pc,
396 splitted.next().unwrap(),
397 &mut labels,
398 &mut defined,
399 )));
400 }
401 "rm" => {
402 pc += 1;
403 out.push(Opcode::Rm);
404 }
405 "sphl" => {
406 pc += 1;
407 out.push(Opcode::Sphl);
408 }
409 "jm" => {
410 pc += 3;
411 out.push(Opcode::Jm(next_address(
412 out.len(),
413 pc,
414 splitted.next().unwrap(),
415 &mut labels,
416 &mut defined,
417 )));
418 }
419 "ei" => {
420 pc += 1;
421 out.push(Opcode::Ei);
422 }
423 "cm" => {
424 pc += 3;
425 out.push(Opcode::Cm(next_address(
426 out.len(),
427 pc,
428 splitted.next().unwrap(),
429 &mut labels,
430 &mut defined,
431 )));
432 }
433
434 "ani" => {
435 pc += 2;
436 out.push(Opcode::Ani(next_byte(splitted.next().unwrap())));
437 }
438 "adi" => {
439 pc += 2;
440 out.push(Opcode::Adi(next_byte(splitted.next().unwrap())));
441 }
442 "aci" => {
443 pc += 2;
444 out.push(Opcode::Aci(next_byte(splitted.next().unwrap())));
445 }
446 "out" => {
447 pc += 2;
448 out.push(Opcode::Out(next_byte(splitted.next().unwrap())));
449 }
450 "sui" => {
451 pc += 2;
452 out.push(Opcode::Sui(next_byte(splitted.next().unwrap())));
453 }
454 "in" => {
455 pc += 2;
456 out.push(Opcode::In(next_byte(splitted.next().unwrap())));
457 }
458 "sbi" => {
459 pc += 2;
460 out.push(Opcode::Sbi(next_byte(splitted.next().unwrap())));
461 }
462 "xri" => {
463 pc += 2;
464 out.push(Opcode::Xri(next_byte(splitted.next().unwrap())));
465 }
466 "ori" => {
467 pc += 2;
468 out.push(Opcode::Ori(next_byte(splitted.next().unwrap())));
469 }
470 "cpi" => {
471 pc += 2;
472 out.push(Opcode::Cpi(next_byte(splitted.next().unwrap())));
473 }
474
475 "ldax" => {
476 pc += 1;
477 let w2 = splitted.next().unwrap().trim();
478
479 match w2 {
480 "b" => out.push(Opcode::LdaxB),
481 "d" => out.push(Opcode::LdaxD),
482 x => {
483 eprintln!("Unknown operand for ldax ({}).", x);
484 err = true;
485 }
486 }
487 }
488 "lxi" => {
489 pc += 3;
490 let mut w2 = splitted.next().unwrap().trim();
491 if let Some(w3) = w2.strip_suffix(',') {
492 w2 = w3.trim();
493 }
494
495 match w2 {
496 "b" => out.push(Opcode::LxiB(
497 next_byte(splitted.next().unwrap()),
498 next_byte(splitted.next().unwrap()),
499 )),
500 "d" => out.push(Opcode::LxiD(
501 next_byte(splitted.next().unwrap()),
502 next_byte(splitted.next().unwrap()),
503 )),
504 "h" => out.push(Opcode::LxiH(
505 next_byte(splitted.next().unwrap()),
506 next_byte(splitted.next().unwrap()),
507 )),
508 x => {
509 eprintln!("Unknown operand for lxi ({}).", x);
510 err = true;
511 }
512 }
513 }
514 "stax" => {
515 pc += 1;
516 let w2 = splitted.next().unwrap().trim();
517
518 match w2 {
519 "b" => out.push(Opcode::StaxB),
520 "d" => out.push(Opcode::StaxD),
521 x => {
522 eprintln!("Unknown operand for stax ({}).", x);
523 err = true;
524 }
525 }
526 }
527 "pop" => {
528 pc += 1;
529 let w2 = splitted.next().unwrap().trim();
530
531 match w2 {
532 "b" => out.push(Opcode::PopB),
533 "d" => out.push(Opcode::PopD),
534 "h" => out.push(Opcode::PopH),
535 "psw" => out.push(Opcode::PopPsw),
536 x => {
537 eprintln!("Unknown operand for pop ({}).", x);
538 err = true;
539 }
540 }
541 }
542 "push" => {
543 pc += 1;
544 let w2 = splitted.next().unwrap().trim();
545
546 match w2 {
547 "b" => out.push(Opcode::PushB),
548 "d" => out.push(Opcode::PushD),
549 "h" => out.push(Opcode::PushH),
550 "psw" => out.push(Opcode::PushPsw),
551 x => {
552 eprintln!("Unknown operand for push ({}).", x);
553 err = true;
554 }
555 }
556 }
557 "dad" => {
558 pc += 1;
559 let w2 = splitted.next().unwrap().trim();
560
561 match w2 {
562 "b" => out.push(Opcode::DadB),
563 "d" => out.push(Opcode::DadD),
564 "h" => out.push(Opcode::DadH),
565 "sp" => out.push(Opcode::DadSp),
566 x => {
567 eprintln!("Unknown operand for dad ({}).", x);
568 err = true;
569 }
570 }
571 }
572 "inx" => {
573 pc += 1;
574 let w2 = splitted.next().unwrap().trim();
575
576 match w2 {
577 "b" => out.push(Opcode::InxB),
578 "d" => out.push(Opcode::InxD),
579 "h" => out.push(Opcode::InxH),
580 "sp" => out.push(Opcode::InxSp),
581 x => {
582 eprintln!("Unknown operand for inx ({}).", x);
583 err = true;
584 }
585 }
586 }
587 "dcx" => {
588 pc += 1;
589 let w2 = splitted.next().unwrap().trim();
590
591 match w2 {
592 "b" => out.push(Opcode::DcxB),
593 "d" => out.push(Opcode::DcxD),
594 "h" => out.push(Opcode::DcxH),
595 "sp" => out.push(Opcode::DcxSp),
596 x => {
597 eprintln!("Unknown operand for dcx ({}).", x);
598 err = true;
599 }
600 }
601 }
602 "inr" => {
603 pc += 1;
604 let w2 = splitted.next().unwrap().trim();
605
606 match w2 {
607 "b" => out.push(Opcode::InrB),
608 "c" => out.push(Opcode::InrC),
609 "d" => out.push(Opcode::InrD),
610 "e" => out.push(Opcode::InrE),
611 "h" => out.push(Opcode::InrH),
612 "l" => out.push(Opcode::InrL),
613 "m" => out.push(Opcode::InrM),
614 "a" => out.push(Opcode::InrA),
615 x => {
616 eprintln!("Unknown operand for inr ({}).", x);
617 err = true;
618 }
619 }
620 }
621 "dcr" => {
622 pc += 1;
623 let w2 = splitted.next().unwrap().trim();
624
625 match w2 {
626 "b" => out.push(Opcode::DcrB),
627 "c" => out.push(Opcode::DcrC),
628 "d" => out.push(Opcode::DcrD),
629 "e" => out.push(Opcode::DcrE),
630 "h" => out.push(Opcode::DcrH),
631 "l" => out.push(Opcode::DcrL),
632 "m" => out.push(Opcode::DcrM),
633 "a" => out.push(Opcode::DcrA),
634 x => {
635 eprintln!("Unknown operand for dcr ({}).", x);
636 err = true;
637 }
638 }
639 }
640 "add" => {
641 pc += 1;
642 let w2 = splitted.next().unwrap().trim();
643
644 match w2 {
645 "b" => out.push(Opcode::AddB),
646 "c" => out.push(Opcode::AddC),
647 "d" => out.push(Opcode::AddD),
648 "e" => out.push(Opcode::AddE),
649 "h" => out.push(Opcode::AddH),
650 "l" => out.push(Opcode::AddL),
651 "m" => out.push(Opcode::AddM),
652 "a" => out.push(Opcode::AddA),
653 x => {
654 eprintln!("Unknown operand for add ({}).", x);
655 err = true;
656 }
657 }
658 }
659 "adc" => {
660 pc += 1;
661 let w2 = splitted.next().unwrap().trim();
662
663 match w2 {
664 "b" => out.push(Opcode::AdcB),
665 "c" => out.push(Opcode::AdcC),
666 "d" => out.push(Opcode::AdcD),
667 "e" => out.push(Opcode::AdcE),
668 "h" => out.push(Opcode::AdcH),
669 "l" => out.push(Opcode::AdcL),
670 "m" => out.push(Opcode::AdcM),
671 "a" => out.push(Opcode::AdcA),
672 x => {
673 eprintln!("Unknown operand for adc ({}).", x);
674 err = true;
675 }
676 }
677 }
678 "sub" => {
679 pc += 1;
680 let w2 = splitted.next().unwrap().trim();
681
682 match w2 {
683 "b" => out.push(Opcode::SubB),
684 "c" => out.push(Opcode::SubC),
685 "d" => out.push(Opcode::SubD),
686 "e" => out.push(Opcode::SubE),
687 "h" => out.push(Opcode::SubH),
688 "l" => out.push(Opcode::SubL),
689 "m" => out.push(Opcode::SubM),
690 "a" => out.push(Opcode::SubA),
691 x => {
692 eprintln!("Unknown operand for sub ({}).", x);
693 err = true;
694 }
695 }
696 }
697 "sbb" => {
698 pc += 1;
699 let w2 = splitted.next().unwrap().trim();
700
701 match w2 {
702 "b" => out.push(Opcode::SbbB),
703 "c" => out.push(Opcode::SbbC),
704 "d" => out.push(Opcode::SbbD),
705 "e" => out.push(Opcode::SbbE),
706 "h" => out.push(Opcode::SbbH),
707 "l" => out.push(Opcode::SbbL),
708 "m" => out.push(Opcode::SbbM),
709 "a" => out.push(Opcode::SbbA),
710 x => {
711 eprintln!("Unknown operand for sbb ({}).", x);
712 err = true;
713 }
714 }
715 }
716 "ana" => {
717 pc += 1;
718 let w2 = splitted.next().unwrap().trim();
719
720 match w2 {
721 "b" => out.push(Opcode::AnaB),
722 "c" => out.push(Opcode::AnaC),
723 "d" => out.push(Opcode::AnaD),
724 "e" => out.push(Opcode::AnaE),
725 "h" => out.push(Opcode::AnaH),
726 "l" => out.push(Opcode::AnaL),
727 "m" => out.push(Opcode::AnaM),
728 "a" => out.push(Opcode::AnaA),
729 x => {
730 eprintln!("Unknown operand for ana ({}).", x);
731 err = true;
732 }
733 }
734 }
735 "xra" => {
736 pc += 1;
737 let w2 = splitted.next().unwrap().trim();
738
739 match w2 {
740 "b" => out.push(Opcode::XraB),
741 "c" => out.push(Opcode::XraC),
742 "d" => out.push(Opcode::XraD),
743 "e" => out.push(Opcode::XraE),
744 "h" => out.push(Opcode::XraH),
745 "l" => out.push(Opcode::XraL),
746 "m" => out.push(Opcode::XraM),
747 "a" => out.push(Opcode::XraA),
748 x => {
749 eprintln!("Unknown operand for xra ({}).", x);
750 err = true;
751 }
752 }
753 }
754 "ora" => {
755 pc += 1;
756 let w2 = splitted.next().unwrap().trim();
757
758 match w2 {
759 "b" => out.push(Opcode::OraB),
760 "c" => out.push(Opcode::OraC),
761 "d" => out.push(Opcode::OraD),
762 "e" => out.push(Opcode::OraE),
763 "h" => out.push(Opcode::OraH),
764 "l" => out.push(Opcode::OraL),
765 "m" => out.push(Opcode::OraM),
766 "a" => out.push(Opcode::OraA),
767 x => {
768 eprintln!("Unknown operand for ora ({}).", x);
769 err = true;
770 }
771 }
772 }
773 "cmp" => {
774 pc += 1;
775 let w2 = splitted.next().unwrap().trim();
776
777 match w2 {
778 "b" => out.push(Opcode::CmpB),
779 "c" => out.push(Opcode::CmpC),
780 "d" => out.push(Opcode::CmpD),
781 "e" => out.push(Opcode::CmpE),
782 "h" => out.push(Opcode::CmpH),
783 "l" => out.push(Opcode::CmpL),
784 "m" => out.push(Opcode::CmpM),
785 "a" => out.push(Opcode::CmpA),
786 x => {
787 eprintln!("Unknown operand for cmp ({}).", x);
788 err = true;
789 }
790 }
791 }
792 "mov" => {
793 pc += 1;
794 let mut w2 = splitted.next().unwrap().trim();
795 if let Some(w3) = w2.strip_suffix(',') {
796 w2 = w3.trim();
797 }
798
799 match w2 {
800 "b" => {
801 let w3 = splitted.next().unwrap().trim();
802
803 match w3 {
804 "b" => out.push(Opcode::MovBB),
805 "c" => out.push(Opcode::MovBC),
806 "d" => out.push(Opcode::MovBD),
807 "e" => out.push(Opcode::MovBE),
808 "h" => out.push(Opcode::MovBH),
809 "l" => out.push(Opcode::MovBL),
810 "m" => out.push(Opcode::MovBM),
811 "a" => out.push(Opcode::MovBA),
812
813 y => {
814 eprintln!("Unknown operand for mov ({}).", y);
815 err = true;
816 }
817 }
818 }
819 "c" => {
820 let w3 = splitted.next().unwrap().trim();
821
822 match w3 {
823 "b" => out.push(Opcode::MovCB),
824 "c" => out.push(Opcode::MovCC),
825 "d" => out.push(Opcode::MovCD),
826 "e" => out.push(Opcode::MovCE),
827 "h" => out.push(Opcode::MovCH),
828 "l" => out.push(Opcode::MovCL),
829 "m" => out.push(Opcode::MovCM),
830 "a" => out.push(Opcode::MovCA),
831
832 y => {
833 eprintln!("Unknown operand for mov ({}).", y);
834 err = true;
835 }
836 }
837 }
838 "d" => {
839 let w3 = splitted.next().unwrap().trim();
840
841 match w3 {
842 "b" => out.push(Opcode::MovDB),
843 "c" => out.push(Opcode::MovDC),
844 "d" => out.push(Opcode::MovDD),
845 "e" => out.push(Opcode::MovDE),
846 "h" => out.push(Opcode::MovDH),
847 "l" => out.push(Opcode::MovDL),
848 "m" => out.push(Opcode::MovDM),
849 "a" => out.push(Opcode::MovDA),
850
851 y => {
852 eprintln!("Unknown operand for mov ({}).", y);
853 err = true;
854 }
855 }
856 }
857 "e" => {
858 let w3 = splitted.next().unwrap().trim();
859
860 match w3 {
861 "b" => out.push(Opcode::MovEB),
862 "c" => out.push(Opcode::MovEC),
863 "d" => out.push(Opcode::MovED),
864 "e" => out.push(Opcode::MovEE),
865 "h" => out.push(Opcode::MovEH),
866 "l" => out.push(Opcode::MovEL),
867 "m" => out.push(Opcode::MovEM),
868 "a" => out.push(Opcode::MovEA),
869
870 y => {
871 eprintln!("Unknown operand for mov ({}).", y);
872 err = true;
873 }
874 }
875 }
876 "h" => {
877 let w3 = splitted.next().unwrap().trim();
878
879 match w3 {
880 "b" => out.push(Opcode::MovHB),
881 "c" => out.push(Opcode::MovHC),
882 "d" => out.push(Opcode::MovHD),
883 "e" => out.push(Opcode::MovHE),
884 "h" => out.push(Opcode::MovHH),
885 "l" => out.push(Opcode::MovHL),
886 "m" => out.push(Opcode::MovHM),
887 "a" => out.push(Opcode::MovHA),
888
889 y => {
890 eprintln!("Unknown operand for mov ({}).", y);
891 err = true;
892 }
893 }
894 }
895 "l" => {
896 let w3 = splitted.next().unwrap().trim();
897
898 match w3 {
899 "b" => out.push(Opcode::MovLB),
900 "c" => out.push(Opcode::MovLC),
901 "d" => out.push(Opcode::MovLD),
902 "e" => out.push(Opcode::MovLE),
903 "h" => out.push(Opcode::MovLH),
904 "l" => out.push(Opcode::MovLL),
905 "m" => out.push(Opcode::MovLM),
906 "a" => out.push(Opcode::MovLA),
907
908 y => {
909 eprintln!("Unknown operand for mov ({}).", y);
910 err = true;
911 }
912 }
913 }
914 "m" => {
915 let w3 = splitted.next().unwrap().trim();
916
917 match w3 {
918 "b" => out.push(Opcode::MovMB),
919 "c" => out.push(Opcode::MovMC),
920 "d" => out.push(Opcode::MovMD),
921 "e" => out.push(Opcode::MovME),
922 "h" => out.push(Opcode::MovMH),
923 "l" => out.push(Opcode::MovML),
924 "a" => out.push(Opcode::MovMA),
925
926 y => {
927 eprintln!("Unknown operand for mov ({}).", y);
928 err = true;
929 }
930 }
931 }
932 "a" => {
933 let w3 = splitted.next().unwrap().trim();
934
935 match w3 {
936 "b" => out.push(Opcode::MovAB),
937 "c" => out.push(Opcode::MovAC),
938 "d" => out.push(Opcode::MovAD),
939 "e" => out.push(Opcode::MovAE),
940 "h" => out.push(Opcode::MovAH),
941 "l" => out.push(Opcode::MovAL),
942 "m" => out.push(Opcode::MovAM),
943 "a" => out.push(Opcode::MovAA),
944
945 y => {
946 eprintln!("Unknown operand for mov ({}).", y);
947 err = true;
948 }
949 }
950 }
951 x => {
952 eprintln!("Unknown operand for mov ({}).", x);
953 err = true;
954 }
955 }
956 }
957 "mvi" => {
958 pc += 2;
959 let mut w2 = splitted.next().unwrap().trim();
960 if let Some(w3) = w2.strip_suffix(',') {
961 w2 = w3.trim();
962 }
963
964 match w2 {
965 "b" => out.push(Opcode::MviB(next_byte(splitted.next().unwrap()))),
966 "c" => out.push(Opcode::MviC(next_byte(splitted.next().unwrap()))),
967 "d" => out.push(Opcode::MviD(next_byte(splitted.next().unwrap()))),
968 "e" => out.push(Opcode::MviE(next_byte(splitted.next().unwrap()))),
969 "h" => out.push(Opcode::MviH(next_byte(splitted.next().unwrap()))),
970 "l" => out.push(Opcode::MviL(next_byte(splitted.next().unwrap()))),
971 "m" => out.push(Opcode::MviM(next_byte(splitted.next().unwrap()))),
972 "a" => out.push(Opcode::MviA(next_byte(splitted.next().unwrap()))),
973 x => {
974 eprintln!("Unknown operand for mvi ({}).", x);
975 err = true;
976 }
977 }
978 }
979 "rst" => {
980 pc += 1;
981 let w2 = splitted.next().unwrap().trim();
982
983 match w2 {
984 "0" => out.push(Opcode::Rst0),
985 "1" => out.push(Opcode::Rst1),
986 "2" => out.push(Opcode::Rst2),
987 "3" => out.push(Opcode::Rst3),
988 "4" => out.push(Opcode::Rst4),
989 "5" => out.push(Opcode::Rst5),
990 "6" => out.push(Opcode::Rst6),
991 "7" => out.push(Opcode::Rst7),
992 x => {
993 eprintln!("Unknown operand for mvi ({}).", x);
994 err = true;
995 }
996 }
997 }
998 "org" => {
999 let new_pc = next_word(splitted.next().unwrap());
1000 if let Some(diff) = new_pc.checked_sub(pc) {
1001 for _ in 0..diff {
1002 out.push(Opcode::Nop);
1003 }
1004 pc = new_pc;
1005 } else if !err {
1006 eprintln!("org operand overflows pc.");
1007 err = true;
1008 }
1009 }
1010 z => {
1011 eprintln!("Unknown opcode ({}).", z);
1012 err = true;
1013 }
1014 }
1015 }
1016 }
1017
1018 for (k, v) in labels.iter() {
1019 if let Some(label) = defined.get(k) {
1020 for pc in v {
1021 match out[*pc] {
1022 Opcode::Jnz(ref mut addr)
1023 | Opcode::Jmp(ref mut addr)
1024 | Opcode::Cnz(ref mut addr)
1025 | Opcode::Jz(ref mut addr)
1026 | Opcode::Cz(ref mut addr)
1027 | Opcode::Call(ref mut addr)
1028 | Opcode::Jnc(ref mut addr)
1029 | Opcode::Cnc(ref mut addr)
1030 | Opcode::Jc(ref mut addr)
1031 | Opcode::Cc(ref mut addr)
1032 | Opcode::Jpo(ref mut addr)
1033 | Opcode::Cpo(ref mut addr)
1034 | Opcode::Jpe(ref mut addr)
1035 | Opcode::Cpe(ref mut addr)
1036 | Opcode::Jp(ref mut addr)
1037 | Opcode::Cp(ref mut addr)
1038 | Opcode::Jm(ref mut addr)
1039 | Opcode::Cm(ref mut addr) => {
1040 *addr = *label as u16;
1041 }
1042
1043 _ => continue,
1044 }
1045 }
1046 } else {
1047 eprintln!("Use of undefined label ({}).", k);
1048 err = true;
1049 }
1050 }
1051
1052 if err || err2 || err3 {
1053 Err(())
1054 } else {
1055 Ok(out)
1056 }
1057}