asar coverage - build #153


src/asar/
File: src/asar/arch-65816.cpp
Date: 2024-01-25 19:41:38
Lines:
274/306
89.5%
Functions:
140/141
99.3%
Branches:
390/605
64.5%

Line Branch Exec Source
1 #include "asar.h"
2 #include "assembleblock.h"
3 #include "asar_math.h"
4
5 #define write1 write1_pick
6
7 2127 void asinit_65816()
8 {
9 2127 }
10
11 1989 void asend_65816()
12 {
13 1989 }
14
15 // like an address mode, but without a specific width
16 enum class addr_kind {
17 abs, // $00
18 x, // $00,x
19 y, // $00,y
20 ind, // ($00)
21 lind, // [$00]
22 xind, // ($00,x)
23 indy, // ($00),y
24 lindy, // [$00],y
25 s, // $00,s
26 sy, // ($00,s),y
27 imp, // implied (no argument)
28 a, // 'A' as argument
29 imm, // #$00
30 };
31
32 struct insn_context {
33 string arg;
34 char orig_insn[3]; // oops i didn't end up using this... could be useful in some error messages maybe
35 char modifier;
36 // right now these 2 are only used for autoclean, so not set for some weird opcodes
37 string parsed_arg;
38 int written_len;
39 uint8_t written_opcode;
40 };
41
42 6597 struct parse_result {
43 addr_kind kind;
44 string arg;
45 };
46
47 // checks for matching characters at the start of haystack, ignoring spaces.
48 // returns index into haystack right after the match
49 template<char... chars>
50 59586 int64_t startmatch(const string& haystack) {
51 static const char needle[] = {chars...};
52 29814 size_t haystack_i = 0;
53
2/2
✓ Branch 0 taken 29793 times.
✓ Branch 1 taken 2415 times.
64416 for(size_t i = 0; i < sizeof...(chars); i++) {
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29793 times.
59586 while(haystack[haystack_i] == ' ') haystack_i++;
55
2/2
✓ Branch 0 taken 14904 times.
✓ Branch 1 taken 14889 times.
59586 if(needle[i] != to_lower(haystack[haystack_i++])) return -1;
56 }
57 4830 return haystack_i;
58 }
59
60 // checks for matching characters at the end of haystack, ignoring spaces.
61 // returns index into haystack right before the match
62 template<char... chars>
63
1/2
✓ Branch 0 taken 12447 times.
✗ Branch 1 not taken.
49824 int64_t endmatch(const string& haystack) {
64 static const char needle[] = {chars...};
65 49824 int64_t haystack_i = haystack.length()-1;
66
2/2
✓ Branch 0 taken 29016 times.
✓ Branch 1 taken 2934 times.
63900 for(int64_t i = sizeof...(chars)-1; i >= 0; i--) {
67
4/6
✓ Branch 0 taken 20178 times.
✓ Branch 1 taken 8838 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20178 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14517 times.
58032 while(haystack_i >= 0 && haystack[haystack_i] == ' ') haystack_i--;
68
6/6
✓ Branch 0 taken 20178 times.
✓ Branch 1 taken 8838 times.
✓ Branch 2 taken 10098 times.
✓ Branch 3 taken 10080 times.
✓ Branch 4 taken 10998 times.
✓ Branch 5 taken 3519 times.
58032 if(haystack_i < 0 || needle[i] != to_lower(haystack[haystack_i--])) return -1;
69 }
70 5868 return haystack_i+1;
71 }
72
73 /*
74 * Parses the address kind from an argument, given a list of allowed address kinds.
75 * Throws "invalid address mode" if the argument does not match any kinds.
76 */
77 // i still don't like this function...
78 template<addr_kind... allowed_kinds>
79
1/2
✓ Branch 0 taken 4860 times.
✗ Branch 1 not taken.
22194 parse_result parse_addr_kind(insn_context& ctx) {
80 11106 int64_t start_i = 0, end_i = ctx.arg.length();
81 // If this addressing kind is allowed, return it, along with a trimmed version of the string.
82 #define RETURN_IF_ALLOWED(kind) \
83 if constexpr(((allowed_kinds == addr_kind::kind) || ...)) { \
84 string out(ctx.arg.data() + start_i, end_i - start_i); \
85 ctx.parsed_arg = out; \
86 return parse_result{addr_kind::kind, out}; \
87 }
88
2/2
✓ Branch 0 taken 1425 times.
✓ Branch 1 taken 9672 times.
22194 if((start_i = startmatch<'#'>(ctx.arg)) >= 0) {
89
2/4
✓ Branch 0 taken 714 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 714 times.
✗ Branch 3 not taken.
5700 RETURN_IF_ALLOWED(imm);
90 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
91 }
92
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 9024 times.
19344 if((start_i = startmatch<'('>(ctx.arg)) >= 0) {
93
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 504 times.
1296 if((end_i = endmatch<',', 's', ')', ',', 'y'>(ctx.arg)) >= 0) {
94
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
576 RETURN_IF_ALLOWED(sy);
95 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
96 }
97
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 360 times.
1008 if((end_i = endmatch<')', ',', 'y'>(ctx.arg)) >= 0) {
98
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
576 RETURN_IF_ALLOWED(indy);
99 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
100 }
101
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 180 times.
720 if((end_i = endmatch<',', 'x', ')'>(ctx.arg)) >= 0) {
102
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
720 RETURN_IF_ALLOWED(xind);
103 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
104 }
105
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
360 if((end_i = endmatch<')'>(ctx.arg)) >= 0) {
106
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
720 RETURN_IF_ALLOWED(ind);
107 asar_throw_warning(1, warning_id_assuming_address_mode, "($00)", "$00", " (if this was intentional, add a +0 after the parentheses.)");
108 }
109 }
110
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 8682 times.
18048 if((start_i = startmatch<'['>(ctx.arg)) >= 0) {
111
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 198 times.
684 if((end_i = endmatch<']', ',', 'y'>(ctx.arg)) >= 0) {
112
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
576 RETURN_IF_ALLOWED(lindy);
113 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
114 }
115
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
396 if((end_i = endmatch<']'>(ctx.arg)) >= 0) {
116
2/4
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
792 RETURN_IF_ALLOWED(lind);
117 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
118 }
119 }
120 8688 start_i = 0;
121
2/2
✓ Branch 0 taken 1566 times.
✓ Branch 1 taken 7116 times.
17364 if((end_i = endmatch<',', 'x'>(ctx.arg)) >= 0) {
122
2/4
✓ Branch 0 taken 783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 783 times.
✗ Branch 3 not taken.
6264 RETURN_IF_ALLOWED(x);
123 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
124 }
125
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 6882 times.
14232 if((end_i = endmatch<',', 'y'>(ctx.arg)) >= 0) {
126
2/4
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
✗ Branch 3 not taken.
936 RETURN_IF_ALLOWED(y);
127 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
128 }
129
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 6738 times.
13764 if((end_i = endmatch<',', 's'>(ctx.arg)) >= 0) {
130
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
576 RETURN_IF_ALLOWED(s);
131 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
132 }
133 6744 end_i = ctx.arg.length();
134 // hoping that by now, something would have stripped whitespace lol
135
2/2
✓ Branch 0 taken 2934 times.
✓ Branch 1 taken 3804 times.
13476 if(ctx.arg.length() == 0) {
136
2/4
✓ Branch 0 taken 1467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1467 times.
✗ Branch 3 not taken.
11736 RETURN_IF_ALLOWED(imp);
137 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
138 }
139
6/6
✓ Branch 0 taken 3786 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 3678 times.
✓ Branch 4 taken 63 times.
✓ Branch 5 taken 1842 times.
7608 if(ctx.arg == "a" || ctx.arg == "A") {
140
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
432 RETURN_IF_ALLOWED(a);
141 // todo: some hint for "don't name your label "a" "?
142 36 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
143 }
144
2/4
✓ Branch 0 taken 1842 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1842 times.
✗ Branch 3 not taken.
14712 RETURN_IF_ALLOWED(abs);
145 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
146 #undef RETURN_IF_ALLOWED
147 // clang doesn't know that asar_throw_error is noreturn in this case... :(
148 return {};
149
11/22
✓ Branch 0 taken 1119 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2178 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 198 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 141 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 288 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 72 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 450 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 72 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 72 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 882 times.
✗ Branch 21 not taken.
22158 }
150
151 const char* format_valid_widths(int min, int max) {
152 if(min == 1) {
153 if(max == 1) return "only 8-bit";
154 if(max == 2) return "only 8-bit or 16-bit";
155 if(max == 3) return "any width"; // shouldn't actually happen lol
156 } else if(min == 2) {
157 if(max == 2) return "only 16-bit";
158 if(max == 3) return "only 16-bit or 24-bit";
159 } else if(min == 3) {
160 return "only 24-bit";
161 }
162 return "???";
163 }
164
165 7557 int get_real_len(int min_len, int max_len, insn_context& ctx, const parse_result& parsed) {
166 // we can theoretically give min_len to getlen now :o
167
1/2
✓ Branch 0 taken 3783 times.
✗ Branch 1 not taken.
7557 int arg_min_len = getlen(parsed.arg, parsed.kind == addr_kind::imm);
168 int out_len;
169
2/2
✓ Branch 0 taken 2340 times.
✓ Branch 1 taken 5217 times.
7557 if(ctx.modifier != 0) {
170
2/2
✓ Branch 0 taken 1161 times.
✓ Branch 1 taken 9 times.
2340 out_len = getlenfromchar(ctx.modifier);
171
2/4
✓ Branch 0 taken 2322 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2322 times.
2322 if(out_len < min_len || out_len > max_len)
172 asar_throw_error(2, error_type_block, error_id_bad_access_width, format_valid_widths(min_len, max_len), out_len*8);
173 } else {
174
2/2
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 4608 times.
5217 if(parsed.kind == addr_kind::imm) {
175
4/4
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 261 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 261 times.
609 if(!is_hex_constant(parsed.arg.data()))
176
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
87 asar_throw_warning(2, warning_id_implicitly_sized_immediate);
177
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 609 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
609 if(arg_min_len == 3 && max_len == 2) {
178 // lda #label
179 // todo: throw pedantic warning
180 ctx.written_len = max_len;
181 return max_len;
182 }
183 }
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5217 times.
5217 if(arg_min_len > max_len) {
185 asar_throw_error(2, error_type_block, error_id_bad_access_width, format_valid_widths(min_len, max_len), arg_min_len*8);
186 }
187 // todo warn about widening when dpbase != 0
188 5217 out_len = std::max(arg_min_len, min_len);
189 }
190 7539 ctx.written_len = out_len;
191 7539 return out_len;
192 }
193
194 216 void handle_implicit_rep(string& arg, int opcode) {
195 216 int64_t rep_count = getnum(arg);
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
216 if(foundlabel) asar_throw_error(0, error_type_block, error_id_no_labels_here);
197
2/2
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 216 times.
720 for (int64_t i=0;i<rep_count;i++) { write1(opcode); }
198 216 }
199
200 5790 void opcode0(insn_context& ctx, uint8_t opcode) {
201 11571 ctx.written_opcode = opcode;
202
13/26
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1404 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 9 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 9 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 9 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 9 times.
✗ Branch 25 not taken.
7653 write1(opcode);
203 7302 }
204 3441 void opcode1(insn_context& ctx, uint8_t opcode, int num) {
205 1722 opcode0(ctx, opcode);
206 3441 write1(num);
207 3441 }
208 3054 void opcode2(insn_context& ctx, uint8_t opcode, int num) {
209 1530 opcode0(ctx, opcode);
210 3054 write2(num);
211 3054 }
212 1350 void opcode3(insn_context& ctx, uint8_t opcode, int num) {
213 675 opcode0(ctx, opcode);
214 1350 write3(num);
215 1350 }
216
217 template<int base, bool allow_imm = true>
218 9150 void the8(insn_context& ctx) {
219 using K = addr_kind;
220
1/2
✓ Branch 0 taken 2289 times.
✗ Branch 1 not taken.
9150 auto parsed = parse_addr_kind<K::xind, K::s, K::abs, K::lind, K::imm, K::indy, K::ind, K::sy, K::x, K::y, K::lindy>(ctx);
221 9150 addr_kind kind = parsed.kind;
222 4578 int min_len = 0, max_len = 4;
223
14/14
✓ Branch 0 taken 4359 times.
✓ Branch 1 taken 216 times.
✓ Branch 2 taken 2145 times.
✓ Branch 3 taken 2214 times.
✓ Branch 4 taken 2073 times.
✓ Branch 5 taken 72 times.
✓ Branch 6 taken 2001 times.
✓ Branch 7 taken 72 times.
✓ Branch 8 taken 1929 times.
✓ Branch 9 taken 72 times.
✓ Branch 10 taken 1857 times.
✓ Branch 11 taken 72 times.
✓ Branch 12 taken 72 times.
✓ Branch 13 taken 1785 times.
9150 if(kind == K::xind || kind == K::s || kind == K::sy || kind == K::indy || kind == K::ind || kind == K::lind || kind == K::lindy) min_len = max_len = 1;
224
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 903 times.
3570 else if(kind == K::abs) min_len = 1, max_len = 3;
225
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 453 times.
1806 else if(kind == K::x) min_len = 1, max_len = 3;
226
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 381 times.
906 else if(kind == K::y) min_len = max_len = 2;
227
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
762 else if(kind == K::imm) min_len = 1, max_len = 2;
228
4/4
✓ Branch 0 taken 1525 times.
✓ Branch 1 taken 3050 times.
✓ Branch 2 taken 1513 times.
✓ Branch 3 taken 12 times.
9150 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
229
2/2
✓ Branch 0 taken 4545 times.
✓ Branch 1 taken 18 times.
9126 int real_len = get_real_len(min_len, max_len, ctx, parsed);
230 4548 int opcode_offset = 0;
231
2/2
✓ Branch 0 taken 1965 times.
✓ Branch 1 taken 2580 times.
9090 if(real_len == 1) {
232
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 984 times.
3930 if(kind == K::xind) opcode_offset = 0x1;
233
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::s) opcode_offset = 0x3;
234
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::abs) opcode_offset = 0x5;
235
2/2
✓ Branch 0 taken 801 times.
✓ Branch 1 taken 984 times.
3570 if(kind == K::lind) opcode_offset = 0x7;
236
2/2
✓ Branch 0 taken 912 times.
✓ Branch 1 taken 981 times.
3786 if(kind == K::imm) opcode_offset = 0x9;
237
2/2
✓ Branch 0 taken 828 times.
✓ Branch 1 taken 984 times.
3624 if(kind == K::indy) opcode_offset = 0x11;
238
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::ind) opcode_offset = 0x12;
239
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::sy) opcode_offset = 0x13;
240
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::x) opcode_offset = 0x15;
241
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 1677 times.
3642 if(kind == K::lindy) opcode_offset = 0x17;
242
1/2
✓ Branch 0 taken 1965 times.
✗ Branch 1 not taken.
3930 opcode1(ctx, base + opcode_offset, the_num);
243
2/2
✓ Branch 0 taken 1626 times.
✓ Branch 1 taken 954 times.
5160 } else if(real_len == 2) {
244
2/2
✓ Branch 0 taken 813 times.
✓ Branch 1 taken 813 times.
3252 if(kind == K::imm) opcode_offset = 0x9;
245
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 813 times.
2826 if(kind == K::abs) opcode_offset = 0xd;
246
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 813 times.
2496 if(kind == K::y) opcode_offset = 0x19;
247
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 1254 times.
3108 if(kind == K::x) opcode_offset = 0x1d;
248
1/2
✓ Branch 0 taken 1626 times.
✗ Branch 1 not taken.
3252 opcode2(ctx, base + opcode_offset, the_num);
249
1/2
✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
1908 } else if(real_len == 3) {
250
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 477 times.
1908 if(kind == K::abs) opcode_offset = 0xf;
251
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 321 times.
1266 if(kind == K::x) opcode_offset = 0x1f;
252
1/2
✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
1908 opcode3(ctx, base + opcode_offset, the_num);
253 }
254 9120 }
255
256 template<int base, int accum_opc, bool is_bit = false>
257 2448 void thenext8(insn_context& ctx) {
258 using K = addr_kind;
259 1224 parse_result parsed;
260 if constexpr(is_bit) {
261
2/4
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
✗ Branch 3 not taken.
432 parsed = parse_addr_kind<K::x, K::abs, K::imm>(ctx);
262 } else {
263
2/4
✓ Branch 0 taken 1008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 504 times.
✗ Branch 3 not taken.
2016 parsed = parse_addr_kind<K::x, K::abs, K::imm, K::a, K::imp>(ctx);
264 // todo: some checks on ctx.modifier here
265
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 972 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
2016 if(parsed.kind == K::imm) return handle_implicit_rep(parsed.arg, accum_opc);
266
3/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 486 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 432 times.
1944 if(parsed.kind == K::a || parsed.kind == K::imp) {
267
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 opcode0(ctx, accum_opc);
268 108 return;
269 }
270 }
271
3/4
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 720 times.
✓ Branch 2 taken 360 times.
✗ Branch 3 not taken.
2160 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
272
1/2
✓ Branch 0 taken 1080 times.
✗ Branch 1 not taken.
2160 int real_len = get_real_len(1, 2, ctx, parsed);
273 1080 int opcode = 0;
274
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1008 times.
2160 if(parsed.kind == K::imm) {
275 72 opcode = accum_opc;
276 }
277
2/2
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 540 times.
2160 if(real_len == 1) {
278
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 288 times.
1080 if(parsed.kind == K::abs) opcode = base+0x6;
279
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 288 times.
1080 if(parsed.kind == K::x) opcode = base+0x16;
280
1/2
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
1080 opcode1(ctx, opcode, the_num);
281
1/2
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
1080 } else if(real_len == 2) {
282
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 288 times.
1080 if(parsed.kind == K::abs) opcode = base+0xe;
283
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 288 times.
1080 if(parsed.kind == K::x) opcode = base+0x1e;
284
1/2
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
1080 opcode2(ctx, opcode, the_num);
285 }
286
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 72 times.
1440 }
287
288 template<int base>
289 288 void tsb_trb(insn_context& ctx) {
290 using K = addr_kind;
291
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
288 auto parsed = parse_addr_kind<K::abs>(ctx);
292
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
288 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
293
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
288 int real_len = get_real_len(1, 2, ctx, parsed);
294
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
288 if(real_len == 1) opcode1(ctx, base + 0x04, the_num);
295
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
144 else opcode2(ctx, base + 0x0c, the_num);
296 288 }
297
298 template<int opc, int width = 1>
299 432 void branch(insn_context& ctx) {
300 using K = addr_kind;
301
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 9 times.
432 auto parsed = parse_addr_kind<K::abs>(ctx);
302 198 int64_t num = 0;
303
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 132 times.
396 if(pass == 2) {
304
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
132 num = getnum(parsed.arg);
305
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 6 times.
132 if(foundlabel) {
306 // cast delta to signed 16-bit, this makes it possible to handle bank-border-wrapping automatically
307 120 int16_t delta = num - (snespos + width + 1);
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
120 if((num & ~0xffff) != (snespos & ~0xffff)) {
309 // todo: should throw error "can't branch to different bank"
310 asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(delta).data());
311 }
312
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
108 if(width==1 && (delta < -128 || delta > 127)) {
313 asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(delta).data());
314 }
315 120 num = delta;
316 } else {
317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 if(num & ~(width==2 ? 0xffff : 0xff)) {
318 asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(num).data());
319 }
320 12 num = (int16_t)(width==2 ? num : (int8_t)num);
321 }
322 }
323
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
324 if(width == 1) opcode1(ctx, opc, num);
324
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 else if(width == 2) opcode2(ctx, opc, num);
325 396 }
326
327 template<int opc>
328 1404 void implied(insn_context& ctx) {
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 702 times.
1404 if(ctx.arg != "") {
330 // todo: some kind of "this instruction doesn't take an argument" message?
331 asar_throw_error(0, error_type_block, error_id_bad_addr_mode);
332 }
333 // also should check that ctx.modifier == 0
334 702 opcode0(ctx, opc);
335 1404 }
336
337 template<int opc>
338 6120 void implied_rep(insn_context& ctx) {
339 using K = addr_kind;
340
1/2
✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
6120 auto parsed = parse_addr_kind<K::imm, K::imp>(ctx);
341
2/2
✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 180 times.
6120 if(parsed.kind == K::imp) {
342
1/2
✓ Branch 0 taken 1440 times.
✗ Branch 1 not taken.
2880 opcode0(ctx, opc);
343 } else {
344
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
360 handle_implicit_rep(parsed.arg, opc);
345 }
346 6120 }
347
348 template<int base, char op, char xy>
349 1800 void xy_ops(insn_context& ctx) {
350 using K = addr_kind;
351 900 parse_result parsed;
352 if(op == 'S') { // stx
353
2/4
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
360 parsed = parse_addr_kind<K::abs, (xy == 'X' ? K::y : K::x)>(ctx);
354 } else if(op == 'L') { // ldx
355
2/4
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
✗ Branch 3 not taken.
864 parsed = parse_addr_kind<K::abs, K::imm, (xy == 'X' ? K::y : K::x)>(ctx);
356 } else { // cpx
357
2/4
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
576 parsed = parse_addr_kind<K::abs, K::imm>(ctx);
358 }
359
3/4
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 600 times.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
1800 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
360
1/2
✓ Branch 0 taken 900 times.
✗ Branch 1 not taken.
1800 int real_len = get_real_len(1, 2, ctx, parsed);
361 900 int opcode = 0;
362
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 450 times.
1800 if(parsed.kind == K::imm) {
363 288 opcode = base;
364
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 180 times.
1224 } else if(parsed.kind == K::abs) {
365
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 216 times.
864 if(real_len == 1) opcode = base + 0x4;
366 216 else opcode = base + 0xc;
367 } else { // ,x or ,y
368
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 72 times.
360 if(real_len == 1) opcode = base + 0x14;
369 72 else opcode = base + 0x1c;
370 }
371
3/4
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 468 times.
✗ Branch 3 not taken.
1512 if(real_len == 1) opcode1(ctx, opcode, the_num);
372
2/4
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 432 times.
✗ Branch 3 not taken.
864 else if(real_len == 2) opcode2(ctx, opcode, the_num);
373 1800 }
374
375 template<int opc>
376 216 void interrupt(insn_context& ctx) {
377 using K = addr_kind;
378
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
216 auto parsed = parse_addr_kind<K::imm, K::imp>(ctx);
379
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
216 if(parsed.kind == K::imp) {
380
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 opcode1(ctx, opc, 0);
381 } else {
382
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
108 int64_t num = pass == 2 ? getnum(parsed.arg) : 0;
383 // this is kinda hacky
384
2/11
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
72 if(num < 0 || num > 255) asar_throw_error(2, error_type_block, error_id_bad_access_width, format_valid_widths(1, 1), num > 65535 ? 24 : 16);
385
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 opcode1(ctx, opc, num);
386 }
387 216 }
388
389 template<int opc, addr_kind k, int width>
390 684 void oneoff(insn_context& ctx) {
391
1/2
✓ Branch 0 taken 171 times.
✗ Branch 1 not taken.
684 auto parsed = parse_addr_kind<k>(ctx);
392
3/4
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
684 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
393 // only for error checking, we know the answer anyways
394
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
684 get_real_len(width, width, ctx, parsed);
395
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 if(width == 1) opcode1(ctx, opc, the_num);
396
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 else if(width == 2) opcode2(ctx, opc, the_num);
397
1/2
✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
540 else if(width == 3) opcode3(ctx, opc, the_num);
398 684 }
399
400 144 void stz(insn_context& ctx) {
401 using K = addr_kind;
402
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
144 auto parsed = parse_addr_kind<K::abs, K::x>(ctx);
403
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
144 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
404
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 int real_len = get_real_len(1, 2, ctx, parsed);
405
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
144 if(real_len == 1) {
406
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 if(parsed.kind == K::abs) opcode1(ctx, 0x64, the_num);
407
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 else if(parsed.kind == K::x) opcode1(ctx, 0x74, the_num);
408 } else {
409
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 if(parsed.kind == K::abs) opcode2(ctx, 0x9c, the_num);
410
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 else if(parsed.kind == K::x) opcode2(ctx, 0x9e, the_num);
411 }
412 144 }
413
414 template<char which>
415 768 void jmp_jsr_jml(insn_context& ctx) {
416 using K = addr_kind;
417
1/2
✓ Branch 0 taken 195 times.
✗ Branch 1 not taken.
768 auto parsed = which == 'R' ? parse_addr_kind<K::abs, K::xind>(ctx)
418 : which == 'P' ? parse_addr_kind<K::abs, K::xind, K::ind, K::lind>(ctx)
419 : /* 'L' */ parse_addr_kind<K::abs, K::lind>(ctx);
420
3/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
768 int64_t the_num = pass == 2 ? getnum(parsed.arg) : 0;
421 // set optimizeforbank to -1 (i.e. auto, assume DBR = current bank)
422 // because jmp and jsr's arguments are relative to the program bank anyways
423 768 int old_optimize = optimizeforbank;
424
4/4
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 159 times.
768 if(parsed.kind == K::lind || parsed.kind == K::ind) {
425 // these ones for Some Reason always read the pointer from bank 0 lol
426 144 optimizeforbank = 0;
427 } else {
428 // the rest use bank K
429 624 optimizeforbank = -1;
430 }
431 390 int the_width = 2;
432
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 18 times.
288 if(which == 'L' && parsed.kind == K::abs) the_width = 3;
433
1/2
✓ Branch 0 taken 384 times.
✗ Branch 1 not taken.
768 get_real_len(the_width, the_width, ctx, parsed);
434 768 optimizeforbank = old_optimize;
435 if(which == 'R') {
436
3/4
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
288 if(parsed.kind == K::abs) opcode2(ctx, 0x20, the_num);
437
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 else if(parsed.kind == K::xind) opcode2(ctx, 0xfc, the_num);
438 } else if(which == 'L') {
439
3/4
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
288 if(parsed.kind == K::abs) opcode3(ctx, 0x5c, the_num);
440
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 else if(parsed.kind == K::lind) opcode2(ctx, 0xdc, the_num);
441 } else {
442
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
192 if(parsed.kind == K::abs) opcode2(ctx, 0x4c, the_num);
443
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
144 else if(parsed.kind == K::ind) opcode2(ctx, 0x6c, the_num);
444
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
108 else if(parsed.kind == K::xind) opcode2(ctx, 0x7c, the_num);
445
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 else if(parsed.kind == K::lind) opcode2(ctx, 0xdc, the_num);
446 }
447 768 }
448
449 template<int opc>
450 72 void mvn_mvp(insn_context& ctx) {
451 int count;
452
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
72 autoptr<char**> parts = qpsplit(ctx.arg.raw(), ',', &count);
453
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if(count != 2) asar_throw_error(2, error_type_block, error_id_bad_addr_mode);
454 // todo length checks ???
455
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 opcode0(ctx, opc);
456
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 24 times.
72 if(pass == 2) {
457
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 write1(getnum(parts[0]));
458
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
24 write1(getnum(parts[1]));
459 } else {
460
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 write2(0);
461 }
462 72 }
463
464 assocarr<void(*)(insn_context&)> mnemonics = {
465 { "ora", the8<0x00> },
466 { "and", the8<0x20> },
467 { "eor", the8<0x40> },
468 { "adc", the8<0x60> },
469 { "sta", the8<0x80, false> },
470 { "lda", the8<0xa0> },
471 { "cmp", the8<0xc0> },
472 { "sbc", the8<0xe0> },
473 { "asl", thenext8<0x00, 0x0a> },
474 { "bit", thenext8<0x1e, 0x89, true> },
475 { "rol", thenext8<0x20, 0x2a> },
476 { "lsr", thenext8<0x40, 0x4a> },
477 { "ror", thenext8<0x60, 0x6a> },
478 { "dec", thenext8<0xc0, 0x3a> },
479 { "inc", thenext8<0xe0, 0x1a> },
480 { "bcc", branch<0x90> },
481 { "bcs", branch<0xb0> },
482 { "beq", branch<0xf0> },
483 { "bmi", branch<0x30> },
484 { "bne", branch<0xd0> },
485 { "bpl", branch<0x10> },
486 { "bra", branch<0x80> },
487 { "bvc", branch<0x50> },
488 { "bvs", branch<0x70> },
489 { "brl", branch<0x82, 2> },
490 { "clc", implied<0x18> },
491 { "cld", implied<0xd8> },
492 { "cli", implied<0x58> },
493 { "clv", implied<0xb8> },
494 { "dex", implied_rep<0xca> },
495 { "dey", implied_rep<0x88> },
496 { "inx", implied_rep<0xe8> },
497 { "iny", implied_rep<0xc8> },
498 { "nop", implied_rep<0xea> },
499 { "pha", implied<0x48> },
500 { "phb", implied<0x8b> },
501 { "phd", implied<0x0b> },
502 { "phk", implied<0x4b> },
503 { "php", implied<0x08> },
504 { "phx", implied<0xda> },
505 { "phy", implied<0x5a> },
506 { "pla", implied<0x68> },
507 { "plb", implied<0xab> },
508 { "pld", implied<0x2b> },
509 { "plp", implied<0x28> },
510 { "plx", implied<0xfa> },
511 { "ply", implied<0x7a> },
512 { "rti", implied<0x40> },
513 { "rtl", implied<0x6b> },
514 { "rts", implied<0x60> },
515 { "sec", implied<0x38> },
516 { "sed", implied<0xf8> },
517 { "sei", implied<0x78> },
518 { "stp", implied<0xdb> },
519 { "tax", implied<0xaa> },
520 { "tay", implied<0xa8> },
521 { "tcd", implied<0x5b> },
522 { "tcs", implied<0x1b> },
523 { "tdc", implied<0x7b> },
524 { "tsc", implied<0x3b> },
525 { "tsx", implied<0xba> },
526 { "txa", implied<0x8a> },
527 { "txs", implied<0x9a> },
528 { "txy", implied<0x9b> },
529 { "tya", implied<0x98> },
530 { "tyx", implied<0xbb> },
531 { "wai", implied<0xcb> },
532 { "xba", implied<0xeb> },
533 { "xce", implied<0xfb> },
534 { "ldy", xy_ops<0xa0, 'L', 'Y'> },
535 { "ldx", xy_ops<0xa2, 'L', 'X'> },
536 { "cpy", xy_ops<0xc0, 'C', 'Y'> },
537 { "cpx", xy_ops<0xe0, 'C', 'X'> },
538 { "stx", xy_ops<0x82, 'S', 'X'> },
539 { "sty", xy_ops<0x80, 'S', 'Y'> },
540 { "cop", interrupt<0x02> },
541 { "wdm", interrupt<0x42> },
542 { "brk", interrupt<0x00> },
543 { "tsb", tsb_trb<0x00> },
544 { "trb", tsb_trb<0x10> },
545 { "rep", oneoff<0xc2, addr_kind::imm, 1> },
546 { "sep", oneoff<0xe2, addr_kind::imm, 1> },
547 { "pei", oneoff<0xd4, addr_kind::ind, 1> },
548 { "pea", oneoff<0xf4, addr_kind::abs, 2> },
549 { "mvn", mvn_mvp<0x54> },
550 { "mvp", mvn_mvp<0x44> },
551 { "jsl", oneoff<0x22, addr_kind::abs, 3> },
552 { "per", branch<0x62, 2> },
553 { "stz", stz },
554 { "jmp", jmp_jsr_jml<'P'> },
555 { "jsr", jmp_jsr_jml<'R'> },
556 { "jml", jmp_jsr_jml<'L'> },
557 };
558
559
560 68010 bool asblock_65816(char** word, int numwords)
561 {
562
2/2
✓ Branch 0 taken 37143 times.
✓ Branch 1 taken 30867 times.
68010 if(word[0][0] == '\'') return false;
563 30264 int word_i = 0;
564 30264 bool autoclean = false;
565
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 66498 times.
66804 if(!stricmpwithlower(word[0], "autoclean")) {
566 153 word_i++;
567 153 autoclean = true;
568 }
569
1/2
✓ Branch 0 taken 30264 times.
✗ Branch 1 not taken.
66804 string opc = word[word_i++];
570 30264 string par;
571
2/2
✓ Branch 0 taken 61332 times.
✓ Branch 1 taken 66804 times.
128136 for(int i = word_i; i < numwords; i++){
572
3/4
✓ Branch 0 taken 1650 times.
✓ Branch 1 taken 59682 times.
✓ Branch 2 taken 825 times.
✗ Branch 3 not taken.
61332 if(i > word_i) par += " ";
573
1/2
✓ Branch 0 taken 27513 times.
✗ Branch 1 not taken.
61332 par += word[i];
574 }
575
4/4
✓ Branch 0 taken 370500 times.
✓ Branch 1 taken 36540 times.
✓ Branch 2 taken 151104 times.
✓ Branch 3 taken 30264 times.
407040 for(int i = 0; i < opc.length(); i++) opc.raw()[i] = to_lower(opc[i]);
576 30264 char mod = 0;
577
9/10
✓ Branch 0 taken 66660 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 31290 times.
✓ Branch 3 taken 35370 times.
✓ Branch 4 taken 30120 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1170 times.
✓ Branch 7 taken 28950 times.
✓ Branch 8 taken 1170 times.
✓ Branch 9 taken 29094 times.
66804 if(opc.length() >= 2 && opc[opc.length()-2] == '.') {
578
1/2
✓ Branch 0 taken 1170 times.
✗ Branch 1 not taken.
2340 mod = opc[opc.length()-1];
579
2/4
✓ Branch 0 taken 1170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1170 times.
✗ Branch 3 not taken.
2340 opc.truncate(opc.length()-2);
580 }
581
4/4
✓ Branch 0 taken 36177 times.
✓ Branch 1 taken 30627 times.
✓ Branch 2 taken 24342 times.
✓ Branch 3 taken 5922 times.
66804 if(!mnemonics.exists(opc.data())) return false;
582
2/6
✓ Branch 0 taken 5922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5922 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11835 insn_context ctx{par, {}, mod, 0};
583 11835 ctx.orig_insn[0] = opc[0];
584 11835 ctx.orig_insn[1] = opc[1];
585 11835 ctx.orig_insn[2] = opc[2];
586
4/4
✓ Branch 0 taken 11811 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 5898 times.
✓ Branch 3 taken 24 times.
11835 mnemonics.find(opc.data())(ctx);
587
4/4
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 11535 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 84 times.
11787 if(autoclean && pass > 0) {
588 // should be changed to "can't use autoclean on this instruction"?
589
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
168 if(ctx.written_len != 3) asar_throw_error(2, error_type_block, error_id_broken_autoclean);
590
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 handle_autoclean(ctx.parsed_arg, ctx.written_opcode, snespos - 4);
591 }
592 5898 return true;
593 66900 }
594