1#![allow(missing_docs)]
2
3use cpclib_common::smol_str::SmolStr;
4use paste;
5
6use crate::tokens::*;
8
9pub fn nop() -> Token {
11 token_for_opcode_no_arg(Mnemonic::Nop)
12}
13
14pub fn halt() -> Token {
15 token_for_opcode_no_arg(Mnemonic::Halt)
16}
17
18pub fn di() -> Token {
19 token_for_opcode_no_arg(Mnemonic::Di)
20}
21
22pub fn ei() -> Token {
23 token_for_opcode_no_arg(Mnemonic::Ei)
24}
25
26pub fn ind() -> Token {
27 token_for_opcode_no_arg(Mnemonic::Ind)
28}
29
30pub fn indr() -> Token {
31 token_for_opcode_no_arg(Mnemonic::Indr)
32}
33
34pub fn ini() -> Token {
35 token_for_opcode_no_arg(Mnemonic::Ini)
36}
37
38pub fn inir() -> Token {
39 token_for_opcode_no_arg(Mnemonic::Inir)
40}
41
42pub fn outd() -> Token {
43 token_for_opcode_no_arg(Mnemonic::Outd)
44}
45
46pub fn outdr() -> Token {
47 token_for_opcode_no_arg(Mnemonic::Otdr)
48}
49
50pub fn outi() -> Token {
51 token_for_opcode_no_arg(Mnemonic::Outi)
52}
53
54pub fn outir() -> Token {
55 token_for_opcode_no_arg(Mnemonic::Otir)
56}
57
58pub fn neg() -> Token {
59 token_for_opcode_no_arg(Mnemonic::Neg)
60}
61
62pub fn exa() -> Token {
63 token_for_opcode_no_arg(Mnemonic::ExAf)
64}
65
66pub fn ex_hl_de() -> Token {
67 token_for_opcode_no_arg(Mnemonic::ExHlDe)
68}
69
70pub fn org<E: Into<Expr>>(val: E) -> Token {
72 Token::Org {
73 val1: val.into(),
74 val2: None
75 }
76}
77
78pub fn equ<S: AsRef<str>, E: Into<Expr>>(label: S, expr: E) -> Token {
79 Token::Equ {
80 label: label.as_ref().into(),
81 expr: expr.into()
82 }
83}
84
85#[allow(missing_docs)]
86pub fn label<S: AsRef<str>>(label: S) -> Token {
87 Token::Label(label.as_ref().into())
88}
89
90pub fn assert_str<S: AsRef<str>>(expr: S) -> Token {
92 Token::Assert(expr.as_ref().into(), None)
93}
94
95#[allow(missing_docs)]
98pub fn comment<S: AsRef<str>>(label: S) -> Token {
99 Token::Comment(label.as_ref().to_owned())
100}
101
102pub fn r#if(cond: TestKind, lst: Listing) -> Token {
103 IfBuilder::default().condition(cond, lst).build()
104}
105
106pub fn defs_expr<E: Into<Expr>>(expr: E) -> Token {
108 Token::Defs(vec![(expr.into(), None)])
109}
110
111pub fn defs_expr_expr<E1: Into<Expr>, E2: Into<Expr>>(count: E1, value: E2) -> Token {
113 Token::Defs(vec![(count.into(), value.into().into())])
114}
115
116pub fn defb<E: Into<Expr>>(val: E) -> Token {
118 Token::Defb(vec![val.into()])
119}
120
121pub fn defb_elements<E: Into<Expr>>(elements: &[E]) -> Token
123where E: Clone {
124 let mut data = Vec::new();
125 for val in elements {
126 let val = val.clone();
127 let expr = val.into();
128 data.push(expr);
129 }
130 Token::Defb(data)
131}
132
133pub fn defw<E: Into<Expr>>(val: E) -> Token {
135 Token::Defw(vec![val.into()])
136}
137
138pub fn djnz_expr<E: Into<Expr>>(expr: E) -> Token {
140 mnemonic_with_single_expr(Mnemonic::Djnz, expr)
141}
142
143pub fn call_expr<E: Into<Expr>>(expr: E) -> Token {
145 mnemonic_with_single_expr(Mnemonic::Call, expr)
146}
147
148fn mnemonic_with_single_expr<E: Into<Expr>>(mne: Mnemonic, expr: E) -> Token {
151 Token::OpCode(mne, Some(expr.into().into()), None, None)
152}
153
154#[allow(missing_docs)]
155pub fn out_c_b() -> Token {
156 out_c_register8(Register8::B)
157}
158#[allow(missing_docs)]
159pub fn out_c_c() -> Token {
160 out_c_register8(Register8::C)
161}
162#[allow(missing_docs)]
163pub fn out_c_d() -> Token {
164 out_c_register8(Register8::D)
165}
166#[allow(missing_docs)]
167pub fn out_c_e() -> Token {
168 out_c_register8(Register8::E)
169}
170#[allow(missing_docs)]
171pub fn out_c_h() -> Token {
172 out_c_register8(Register8::H)
173}
174#[allow(missing_docs)]
175pub fn out_c_l() -> Token {
176 out_c_register8(Register8::L)
177}
178#[allow(missing_docs)]
179pub fn out_c_a() -> Token {
180 out_c_register8(Register8::A)
181}
182
183#[allow(missing_docs)]
184pub fn out_c_register8(reg: Register8) -> Token {
185 token_for_opcode_two_args(Mnemonic::Out, DataAccess::PortC, reg.into())
186}
187
188#[allow(missing_docs)]
189pub fn push_af() -> Token {
190 push_or_pop(Mnemonic::Push, Register16::Af)
191}
192
193#[allow(missing_docs)]
194pub fn push_bc() -> Token {
195 push_or_pop(Mnemonic::Push, Register16::Bc)
196}
197
198#[allow(missing_docs)]
199pub fn push_de() -> Token {
200 push_or_pop(Mnemonic::Push, Register16::De)
201}
202
203#[allow(missing_docs)]
204pub fn push_hl() -> Token {
205 push_or_pop(Mnemonic::Push, Register16::Hl)
206}
207
208#[allow(missing_docs)]
209pub fn pop_af() -> Token {
210 push_or_pop(Mnemonic::Pop, Register16::Af)
211}
212
213#[allow(missing_docs)]
214pub fn pop_bc() -> Token {
215 push_or_pop(Mnemonic::Pop, Register16::Bc)
216}
217
218#[allow(missing_docs)]
219pub fn pop_de() -> Token {
220 push_or_pop(Mnemonic::Pop, Register16::De)
221}
222
223#[allow(missing_docs)]
224pub fn pop_hl() -> Token {
225 push_or_pop(Mnemonic::Pop, Register16::Hl)
226}
227
228#[inline]
229fn push_or_pop(op: Mnemonic, reg: Register16) -> Token {
230 token_for_opcode_one_arg(op, reg.into())
231}
232
233#[allow(missing_docs)]
234pub fn push_ix() -> Token {
235 Token::OpCode(
236 Mnemonic::Push,
237 Some(DataAccess::IndexRegister16(IndexRegister16::Ix)),
238 None,
239 None
240 )
241}
242
243#[allow(missing_docs)]
244pub fn push_iy() -> Token {
245 Token::OpCode(
246 Mnemonic::Push,
247 Some(DataAccess::IndexRegister16(IndexRegister16::Iy)),
248 None,
249 None
250 )
251}
252
253#[allow(missing_docs)]
254pub fn pop_ix() -> Token {
255 Token::OpCode(
256 Mnemonic::Pop,
257 Some(DataAccess::IndexRegister16(IndexRegister16::Ix)),
258 None,
259 None
260 )
261}
262
263#[allow(missing_docs)]
264pub fn pop_iy() -> Token {
265 Token::OpCode(
266 Mnemonic::Pop,
267 Some(DataAccess::IndexRegister16(IndexRegister16::Iy)),
268 None,
269 None
270 )
271}
272
273pub fn ret() -> Token {
275 Token::OpCode(Mnemonic::Ret, None, None, None)
276}
277
278#[allow(missing_docs)]
279pub fn breakpoint_winape() -> Token {
280 Token::Defb(vec![Expr::Value(0xED), Expr::Value(0xFF)])
281}
282
283#[allow(missing_docs)]
284pub fn breakpoint_snapshot() -> Token {
285 todo!()
286}
287
288#[allow(missing_docs)]
289pub fn jp_label(label: &str) -> Token {
290 token_for_opcode_latest_arg(Mnemonic::Jp, label.into())
291}
292
293#[allow(missing_docs)]
294pub fn jp_ix() -> Token {
295 token_for_opcode_latest_arg(
296 Mnemonic::Jp,
297 DataAccess::MemoryIndexRegister16(IndexRegister16::Ix)
298 )
299}
300
301#[allow(missing_docs)]
302pub fn jp_iy() -> Token {
303 token_for_opcode_latest_arg(
304 Mnemonic::Jp,
305 DataAccess::MemoryIndexRegister16(IndexRegister16::Iy)
306 )
307}
308
309#[allow(missing_docs)]
310pub fn jp_hl() -> Token {
311 token_for_opcode_latest_arg(Mnemonic::Jp, DataAccess::MemoryRegister16(Register16::Hl))
312}
313
314#[allow(missing_docs)]
315pub fn exx() -> Token {
316 token_for_opcode_no_arg(Mnemonic::Exx)
317}
318
319#[allow(missing_docs)]
320pub fn incbin<S: Into<SmolStr>>(fname: S) -> Token {
321 Token::Incbin {
322 fname: Expr::String(fname.into()),
323 transformation: BinaryTransformation::None,
324 offset: None,
325 length: None,
326 extended_offset: None,
327 off: false
328 }
329}
330
331macro_rules! math_op_r8 {
332 ($($reg:ident)*) => {$(
333 paste::paste! {
334 pub fn [<add_ $reg:lower>] () -> Token {
335 token_for_opcode_two_args(
336 Mnemonic::Add,
337 Register8::A.into(),
338 Register8::$reg.into()
339 )
340 }
341
342 pub fn [<sub_ $reg:lower>] () -> Token {
343 token_for_opcode_two_args(
344 Mnemonic::Sub,
345 Register8::A.into(),
346 Register8::$reg.into()
347 )
348 }
349
350 }
351 )*}
352}
353math_op_r8! { A B C D E H L}
354
355macro_rules! inc_r8 {
356 ($($reg:ident)*) => {$(
357 paste::paste! {
358 #[allow(missing_docs)] pub fn [<inc_ $reg:lower>] () -> Token {
360 token_for_opcode_one_arg(
361 Mnemonic::Inc,
362 Register8::$reg.into()
363 )
364 }
365
366 #[allow(missing_docs)] pub fn [<dec_ $reg:lower>] () -> Token {
368 token_for_opcode_one_arg(
369 Mnemonic::Dec,
370 Register8::$reg.into()
371 )
372 }
373 }
374 )*}
375}
376inc_r8! { A B C D E H L}
377
378macro_rules! inc_r16 {
379 ($($reg:ident)*) => {$(
380 paste::paste! {
381 #[allow(missing_docs)] pub fn [<inc_ $reg:lower>] () -> Token {
383 token_for_opcode_one_arg(
384 Mnemonic::Inc,
385 Register16::$reg.into()
386 )
387 }
388
389 #[allow(missing_docs)] pub fn [<dec_ $reg:lower>] () -> Token {
391 token_for_opcode_one_arg(
392 Mnemonic::Dec,
393 Register16::$reg.into()
394 )
395 }
396 }
397 )*}
398}
399inc_r16! {Af Bc De Hl}
400
401pub fn ld_r8_expr<R: Into<Register8>, E: Into<Expr>>(r: R, e: E) -> Token {
402 token_for_opcode_two_args(Mnemonic::Ld, r.into().into(), e.into().into())
403}
404
405pub fn ld_r16_expr<R: Into<Register16>, E: Into<Expr>>(r: R, e: E) -> Token {
406 token_for_opcode_two_args(Mnemonic::Ld, r.into().into(), e.into().into())
407}
408
409#[allow(missing_docs)]
411pub fn ld_l_mem_ix(expr: Expr) -> Token {
412 token_for_opcode_two_args(
413 Mnemonic::Ld,
414 Register8::L.into(),
415 DataAccess::IndexRegister16WithIndex(
416 IndexRegister16::Ix,
417 if expr.is_negated() {
418 BinaryOperation::Sub
419 }
420 else {
421 BinaryOperation::Add
422 },
423 if expr.is_negated() { expr.neg() } else { expr }
424 )
425 )
426}
427
428pub fn ld_mem_bc_a() -> Token {
429 token_for_opcode_two_args(
430 Mnemonic::Ld,
431 DataAccess::MemoryRegister16(Register16::Bc),
432 DataAccess::Register8(Register8::A)
433 )
434}
435
436pub fn ld_mem_de_a() -> Token {
437 token_for_opcode_two_args(
438 Mnemonic::Ld,
439 DataAccess::MemoryRegister16(Register16::Bc),
440 DataAccess::Register8(Register8::A)
441 )
442}
443
444pub fn ld_a_mem_bc() -> Token {
445 token_for_opcode_two_args(
446 Mnemonic::Ld,
447 DataAccess::Register8(Register8::A),
448 DataAccess::MemoryRegister16(Register16::Bc)
449 )
450}
451
452pub fn ld_a_mem_de() -> Token {
453 token_for_opcode_two_args(
454 Mnemonic::Ld,
455 DataAccess::Register8(Register8::A),
456 DataAccess::MemoryRegister16(Register16::De)
457 )
458}
459
460macro_rules! ld_r16_expr {
461 ($($reg:ident)*) => {$(
462 paste::paste! {
463 #[allow(missing_docs)] pub fn [<ld_ $reg:lower _expr>]<E:Into<Expr>> (val: E) -> Token {
465 token_for_opcode_two_args(
466 Mnemonic::Ld,
467 Register16::$reg.into(),
468 val.into().into()
469 )
470 }
471 }
472 )*}
473}
474
475ld_r16_expr! {
477 Af
478 Bc
479 De
480 Hl
481 Sp
482}
483
484macro_rules! ld_r8_expr {
485 ($($reg:ident)*) => {$(
486 paste::paste! {
487 #[allow(missing_docs)] pub fn [<ld_ $reg:lower _expr>]<E: Into<Expr>> (val: E) -> Token {
489 token_for_opcode_two_args(
490 Mnemonic::Ld,
491 Register8::$reg.into(),
492 val.into().into()
493 )
494 }
495 }
496 )*}
497}
498
499ld_r8_expr! {
500 A
501 B
502 C
503 D
504 E
505 H
506 L
507}
508
509macro_rules! ld_r8_r8 {
510 ($($reg:ident,$reg2:ident)*) => {$(
511 paste::paste! {
512 #[allow(missing_docs)] pub fn [<ld_ $reg:lower _ $reg2:lower>]() -> Token {
514 token_for_opcode_two_args(
515 Mnemonic::Ld,
516 Register8::$reg.into(),
517 Register8::$reg2.into(),
518 )
519 }
520 }
521 )*}
522}
523
524ld_r8_r8! {
525 A,A A,B A,C A,D A,E A,H A,L
526 B,A B,B B,C B,D B,E B,H B,L
527 C,A C,B C,C C,D C,E C,H C,L
528 D,A D,B D,C D,D D,E D,H D,L
529 E,A E,B E,C E,D E,E E,H E,L
530 H,A H,B H,C H,D H,E H,H H,L
531 L,A L,B L,C L,D L,E L,H L,L
532}
533
534#[allow(missing_docs)]
535pub fn ld_mem_expr_a<E: Into<Expr>>(e: E) -> Token {
536 token_for_opcode_two_args(
537 Mnemonic::Ld,
538 DataAccess::Memory(e.into()),
539 Register8::A.into()
540 )
541}
542
543#[allow(missing_docs)]
544pub fn ld_mem_hl_expr<E: Into<Expr>>(e: E) -> Token {
545 let e = e.into();
546 token_for_opcode_two_args(
547 Mnemonic::Ld,
548 DataAccess::MemoryRegister16(Register16::Hl),
549 e.into()
550 )
551}
552
553macro_rules! ld_mem_hl_r8 {
554 ($($reg:ident)*) => {$(
555 paste::paste! {
556 pub fn [<ld_mem_hl_ $reg:lower>]() -> Token {
557 ld_mem_hl_r8(Register8::$reg)
558 }
559
560 pub fn [<ld_ $reg:lower _mem_hl>]() -> Token {
561 ld_register8_mem_hl(Register8::$reg)
562 }
563 }
564 )*}
565}
566
567ld_mem_hl_r8! {
568 A
569 B
570 C
571 D
572 E
573 H
574 L
575}
576
577pub fn ld_mem_hl_r8(reg: Register8) -> Token {
578 token_for_opcode_two_args(
579 Mnemonic::Ld,
580 DataAccess::MemoryRegister16(Register16::Hl),
581 reg.into()
582 )
583}
584
585pub fn ld_register8_mem_hl(reg: Register8) -> Token {
586 token_for_opcode_two_args(
587 Mnemonic::Ld,
588 reg.into(),
589 DataAccess::MemoryRegister16(Register16::Hl)
590 )
591}
592
593#[allow(missing_docs)]
594pub fn ldi() -> Token {
595 token_for_opcode_no_arg(Mnemonic::Ldi)
596}
597
598#[allow(missing_docs)]
599pub fn ldd() -> Token {
600 token_for_opcode_no_arg(Mnemonic::Ldd)
601}
602
603#[allow(missing_docs)]
604pub fn ldir() -> Token {
605 token_for_opcode_no_arg(Mnemonic::Ldir)
606}
607
608#[allow(missing_docs)]
609pub fn lddr() -> Token {
610 token_for_opcode_no_arg(Mnemonic::Lddr)
611}
612
613macro_rules! set_res_reg8 {
614 ($($reg:ident), *) => {$(
615 paste::paste! {
616 #[allow(missing_docs)]
617 #[inline]
618 pub fn [<res_ $reg:lower>](bit: u8) -> Token {
619 res_reg_pos(Register8::$reg, bit)
620 }
621
622 #[allow(missing_docs)]
623 #[inline]
624 pub fn [<set_ $reg:lower>](bit: u8) -> Token {
625 set_reg_pos(Register8::$reg, bit)
626 }
627
628 })*
629 };
630}
631
632set_res_reg8! {A, B, C, D, E, H, L}
633
634#[allow(missing_docs)]
635pub fn set_mem_hl(bit: u8) -> Token {
636 token_for_opcode_two_args(
637 Mnemonic::Set,
638 bit.into(),
639 DataAccess::MemoryRegister16(Register16::Hl)
640 )
641}
642
643#[allow(missing_docs)]
644pub fn res_mem_hl(bit: u8) -> Token {
645 token_for_opcode_two_args(
646 Mnemonic::Res,
647 bit.into(),
648 DataAccess::MemoryRegister16(Register16::Hl)
649 )
650}
651
652#[allow(missing_docs)]
653#[inline]
654pub fn res_reg_pos(reg: Register8, bit: u8) -> Token {
655 token_for_opcode_two_args(Mnemonic::Res, bit.into(), reg.into())
656}
657
658#[allow(missing_docs)]
659#[inline]
660pub fn set_reg_pos(reg: Register8, bit: u8) -> Token {
661 token_for_opcode_two_args(Mnemonic::Set, bit.into(), reg.into())
662}
663
664#[allow(missing_docs)]
666pub fn token_for_opcode_no_arg(mne: Mnemonic) -> Token {
667 Token::OpCode(mne, None, None, None)
668}
669
670#[allow(missing_docs)]
672pub fn token_for_opcode_one_arg(mne: Mnemonic, data1: DataAccess) -> Token {
673 Token::OpCode(mne, Some(data1), None, None)
674}
675
676#[allow(missing_docs)]
678pub fn token_for_opcode_latest_arg(mne: Mnemonic, data2: DataAccess) -> Token {
679 Token::OpCode(mne, None, Some(data2), None)
680}
681
682#[allow(missing_docs)]
684pub fn token_for_opcode_two_args(mne: Mnemonic, data1: DataAccess, data2: DataAccess) -> Token {
685 Token::OpCode(mne, Some(data1), Some(data2), None)
686}
687
688#[allow(missing_docs)]
689pub fn section(section: &str) -> Token {
690 Token::Section(section.into())
691}
692
693#[derive(Default)]
694pub struct IfBuilder {
695 conditions: Vec<(TestKind, Listing)>,
696 r#else: Option<Listing>
697}
698
699impl IfBuilder {
700 pub fn build(self) -> Token {
701 assert!(!self.conditions.is_empty());
702 Token::If(self.conditions, self.r#else)
703 }
704
705 pub fn condition(mut self, cond: TestKind, lst: Listing) -> Self {
706 assert!(self.r#else.is_none());
707 self.conditions.push((cond, lst));
708 self
709 }
710
711 pub fn r#else(mut self, lst: Listing) -> Self {
712 self.r#else = Some(lst);
713 self
714 }
715}
716
717#[derive(Default)]
718pub struct ListingBuilder {
719 lst: Listing
720}
721
722macro_rules! ld_r8_expr_builder {
723 ($($reg:ident)*) => {$(
724 paste::paste! {
725 pub fn [<ld_ $reg:lower _expr>]<E: Into<Expr>>(mut self, expr: E) -> Self {
727 self.lst.add([<ld_ $reg:lower _expr>](expr));
728 self
729 }
730
731
732 pub fn [<inc_ $reg:lower>](mut self) -> Self {
733 self.lst.add([<inc_ $reg:lower>]());
734 self
735 }
736
737 pub fn [<dec_ $reg:lower>](mut self) -> Self {
738 self.lst.add([<dec_ $reg:lower>]());
739 self
740 }
741 }
742 )*}
743}
744
745macro_rules! ld_r16_expr_builder {
746 ($($reg:ident)*) => {$(
747 paste::paste! {
748 pub fn [<ld_ $reg:lower _expr>]<E: Into<Expr>>(mut self, expr: E) -> Self {
750 self.lst.add([<ld_ $reg:lower _expr>](expr));
751 self
752 }
753
754
755 pub fn [<inc_ $reg:lower>](mut self) -> Self {
756 self.lst.add([<inc_ $reg:lower>]());
757 self
758 }
759
760 pub fn [<dec_ $reg:lower>](mut self) -> Self {
761 self.lst.add([<dec_ $reg:lower>]());
762 self
763 }
764
765 }
766 )*}
767}
768
769macro_rules! ld_mem_r16_builder {
770 ($($reg:ident)*) => {$(
771 paste::paste! {
772
773 pub fn [<ld_mem_ $reg:lower _a>](mut self) -> Self {
774 self.lst.add([<ld_mem_ $reg:lower _a>]());
775 self
776 }
777
778 pub fn [<ld_a_ mem_ $reg:lower>](mut self) -> Self {
779 self.lst.add([<ld_a_mem_ $reg:lower>]());
780 self
781 }
782 }
783 )*}
784}
785
786macro_rules! ld_r8_r8_builder {
787 ($($reg1:ident,$reg2:ident)*) => {$(
788 paste::paste! {
789 pub fn [<ld_ $reg1:lower _ $reg2:lower>](mut self) -> Self {
791 self.lst.add([<ld_ $reg1:lower _ $reg2:lower>]());
792 self
793 }
794 }
795 )*}
796}
797
798macro_rules! ld_mem_hl_r8_builder {
799 ($($reg:ident)*) => {$(
800 paste::paste! {
801 pub fn [<ld_mem_hl_ $reg:lower>](mut self) -> Self {
802 self.lst.add(ld_mem_hl_r8(Register8::$reg));
803 self
804 }
805
806 pub fn [<ld_ $reg:lower _mem_hl>](mut self) -> Self {
807 self.lst.add(ld_register8_mem_hl(Register8::$reg));
808 self
809 }
810 }
811 )*}
812}
813
814macro_rules! no_arg_builder {
815 ($($op:ident)*) => {
816 $(
817 pub fn $op(mut self) -> Self {
818 self.lst.add($op());
819 self
820 }
821 )*
822 }
823}
824
825macro_rules! math_op_r8_builder {
826 ($($reg:ident)*) => {$(
827 paste::paste! {
828
829 pub fn [<add_ $reg:lower>] (mut self) -> Self {
830 self.lst.add([<add_ $reg:lower>] () );
831 self
832 }
833
834 pub fn [<sub_ $reg:lower>] (mut self) -> Self {
835 self.lst.add([<add_ $reg:lower>] () );
836 self
837 }
838 }
839 )*}
840}
841
842impl ListingBuilder {
843 ld_r8_expr_builder! {a b c d e h l}
844
845 ld_r16_expr_builder! {af bc de hl}
846
847 ld_mem_r16_builder! {bc de}
848
849 ld_mem_hl_r8_builder! {A B C D E H L}
850
851 no_arg_builder! {exx nop ldi ldd ldir lddr neg exa ex_hl_de halt di ei ind indr outd outdr outi outir ret}
852
853 ld_r8_r8_builder! {
854 A,A A,B A,C A,D A,E A,H A,L
855 B,A B,B B,C B,D B,E B,H B,L
856 C,A C,B C,C C,D C,E C,H C,L
857 D,A D,B D,C D,D D,E D,H D,L
858 E,A E,B E,C E,D E,E E,H E,L
859 H,A H,B H,C H,D H,E H,H H,L
860 L,A L,B L,C L,D L,E L,H L,L
861 }
862
863 math_op_r8_builder! { A B C D E H L}
864
865 pub fn ld_mem_hl_expr<E: Into<Expr>>(mut self, e: E) -> Self {
866 self.lst.add(ld_mem_hl_expr(e));
867 self
868 }
869
870 pub fn ld_mem_hl_r8<R: Into<Register8>>(mut self, r: R) -> Self {
871 self.lst.add(ld_mem_hl_r8(r.into()));
872 self
873 }
874
875 pub fn ld_r8_expr<R: Into<Register8>, E: Into<Expr>>(mut self, r: R, e: E) -> Self {
876 self.lst.add(ld_r8_expr(r, e));
877 self
878 }
879
880 pub fn ld_r16_expr<R: Into<Register16>, E: Into<Expr>>(mut self, r: R, e: E) -> Self {
881 self.lst.add(ld_r16_expr(r, e));
882 self
883 }
884
885 pub fn call<S: Into<SmolStr>>(self, label: S) -> Self {
886 self.call_expr(Expr::Label(label.into()))
887 }
888
889 pub fn call_expr<E: Into<Expr>>(mut self, expr: E) -> Self {
890 self.lst.add(call_expr(expr));
891 self
892 }
893
894 pub fn or_expr<E: Into<Expr>>(mut self, expr: E) -> Self {
895 let e = expr.into();
896 self.lst
897 .add(token_for_opcode_one_arg(Mnemonic::Or, e.into()));
898 self
899 }
900
901 pub fn xor_expr<E: Into<Expr>>(mut self, expr: E) -> Self {
902 let e = expr.into();
903 self.lst
904 .add(token_for_opcode_one_arg(Mnemonic::Xor, e.into()));
905 self
906 }
907
908 pub fn and_expr<E: Into<Expr>>(mut self, expr: E) -> Self {
909 let e = expr.into();
910 self.lst
911 .add(token_for_opcode_one_arg(Mnemonic::And, e.into()));
912 self
913 }
914
915 pub fn or_r8(mut self, r: Register8) -> Self {
916 self.lst
917 .add(token_for_opcode_one_arg(Mnemonic::Or, r.into()));
918 self
919 }
920
921 pub fn xor_r8(mut self, r: Register8) -> Self {
922 self.lst
923 .add(token_for_opcode_one_arg(Mnemonic::Xor, r.into()));
924 self
925 }
926
927 pub fn and_r8(mut self, r: Register8) -> Self {
928 self.lst
929 .add(token_for_opcode_one_arg(Mnemonic::And, r.into()));
930 self
931 }
932
933 pub fn comment<S: Into<String>>(mut self, comment: S) -> Self {
934 self.lst.add_comment(comment);
935 self
936 }
937
938 pub fn extend(mut self, other: Listing) -> Self {
939 self.lst.inject_listing(&other);
940 self
941 }
942
943 pub fn repeat<L: Into<Listing>>(mut self, count: i32, code: L) -> Self {
945 let test = Expr::Value(count);
946 let rpt = Token::Repeat(test, code.into(), None, None);
947 self.lst.add(rpt);
948 self
949 }
950
951 pub fn build(self) -> Listing {
952 self.lst
953 }
954}
955
956pub mod routines {
958 use crate::builder::*;
959 use crate::tokens::tokens::Listing;
960
961 #[allow(dead_code)]
965 pub fn wait(mut duration: u32) -> Listing {
966 let wait_code_for = |l_duration| {
967 assert!(l_duration > 0);
968 let loops = (l_duration - 1) / 4;
969 let loopsx4 = loops * 4;
970 let nops = l_duration - loopsx4 - 1;
971
972 let mut listing = Listing::default();
973 if loops != 0 {
974 listing.push(ld_b_expr(loops));
975 listing.push(djnz_expr("$"));
976 }
977
978 listing.push(defs_expr_expr(nops, 0));
979 listing
980 };
981
982 let mut full_code = Listing::new();
983 while duration > 1024 {
984 full_code.inject_listing(&wait_code_for(1024));
985 duration -= 1024;
986 }
987 if duration != 0 {
988 full_code.inject_listing(&wait_code_for(duration));
989 }
990
991 full_code
992 }
993}
994
995#[cfg(test)]
996mod tests {
997
998 #[test]
999 fn test_ld_r16() {
1000 use super::*;
1001 ld_af_expr(0);
1003 }
1004}