intel_8080_kit/asm/
lexer.rs

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}