1define!(
6 #[mask(0x08)]
7 pub enum Source {
8 K = 0x00,
9 X = 0x08,
10 }
11);
12
13macro_rules! impl_ld {
14 () => {
15 impl_ld!(ld, ldx, W);
16 impl_ld!(ldb, ldbx, B);
17 impl_ld!(ldh, ldhx, H);
18 };
19 ($ld:ident, $x:ident, $size:ident) => {
20 pub const fn $ld(k: K) -> Instruction {
21 Instruction::raw(
22 k.mode as u16 | Class::LD as u16 | Size::$size as u16,
23 0,
24 0,
25 k.value,
26 )
27 }
28
29 pub const fn $x(k: K) -> Instruction {
30 Instruction::raw(
31 k.mode as u16 | Class::LDX as u16 | Size::$size as u16,
32 0,
33 0,
34 k.value,
35 )
36 }
37 };
38}
39
40macro_rules! impl_alu {
41 () => {
42 impl_alu!(add, add_x, ADD);
43 impl_alu!(sub, sub_x, SUB);
44 impl_alu!(mul, mul_x, MUL);
45 impl_alu!(div, div_x, DIV);
46 impl_alu!(rem, rem_x, MOD);
47 impl_alu!(and, and_x, AND);
48 impl_alu!(or, or_x, OR);
49 impl_alu!(xor, xor_x, XOR);
50 impl_alu!(lsh, lsh_x, LSH);
51 impl_alu!(rsh, rsh_x, RSH);
52 };
53 ($lower:ident, $x:ident, $upper:ident) => {
54 pub const fn $lower(value: u32) -> Instruction {
55 Instruction::raw(
56 Mode::IMM as u16 | Class::ALU as u16 | Source::K as u16 | Alu::$upper as u16,
57 0,
58 0,
59 value,
60 )
61 }
62
63 pub const fn $x() -> Instruction {
64 Instruction::raw(
65 Mode::IMM as u16 | Class::ALU as u16 | Source::X as u16 | Alu::$upper as u16,
66 0,
67 0,
68 0,
69 )
70 }
71 };
72}
73
74macro_rules! impl_jmp {
75 () => {
76 pub const fn ja(value: u32) -> Instruction {
77 Instruction::raw(
78 Class::JMP as u16 | Source::K as u16 | Jump::JA as u16,
79 0,
80 0,
81 value,
82 )
83 }
84
85 impl_jmp!(jgt, jgt_x, JGT, false);
86 impl_jmp!(jle, jle_x, JGT, true);
87 impl_jmp!(jeq, jeq_x, JEQ, false);
88 impl_jmp!(jneq, jneq_x, JEQ, true);
89 impl_jmp!(jset, jset_x, JSET, false);
90 };
91 ($lower:ident, $x:ident, $upper:ident, $invert:expr) => {
92 pub const fn $lower(value: u32, mut jt: u8, mut jf: u8) -> Instruction {
93 if $invert {
94 let tmp = jt;
95 jt = jf;
96 jf = tmp;
97 }
98
99 Instruction::raw(
100 Class::JMP as u16 | Source::K as u16 | Jump::$upper as u16,
101 jt,
102 jf,
103 value,
104 )
105 }
106
107 pub const fn $x(mut jt: u8, mut jf: u8) -> Instruction {
108 if $invert {
109 let tmp = jt;
110 jt = jf;
111 jf = tmp;
112 }
113
114 Instruction::raw(
115 Class::JMP as u16 | Source::X as u16 | Jump::$upper as u16,
116 jt,
117 jf,
118 0,
119 )
120 }
121 };
122}
123
124macro_rules! impl_ret {
125 () => {
126 pub const fn ret(value: u32) -> Instruction {
127 Instruction::raw(Class::RET as u16 | Source::K as u16, 0, 0, value)
128 }
129
130 pub const fn ret_x() -> Instruction {
131 Instruction::raw(Class::RET as u16 | Source::X as u16, 0, 0, 0)
132 }
133
134 pub const fn ret_a() -> Instruction {
135 Instruction::raw(Class::RET as u16 | Size::B as u16, 0, 0, 0)
136 }
137 };
138}
139
140macro_rules! impl_ops {
141 () => {
142 #[derive(Clone, Copy)]
143 pub struct K {
144 pub mode: Mode,
145 pub value: u32,
146 }
147
148 pub const fn abs(value: u32) -> K {
149 K {
150 mode: Mode::ABS,
151 value,
152 }
153 }
154
155 pub const fn imm(value: u32) -> K {
156 K {
157 mode: Mode::IMM,
158 value,
159 }
160 }
161
162 pub const fn ind(value: u32) -> K {
163 K {
164 mode: Mode::IND,
165 value,
166 }
167 }
168
169 impl_ld!();
170 impl_alu!();
171 impl_jmp!();
172 impl_ancillary!();
173 };
174}