asar coverage - build #131


src/asar/
File: src/asar/arch-65816.cpp
Date: 2024-01-22 23:17:50
Lines:
277/307
90.2%
Functions:
136/137
99.3%
Branches:
397/594
66.8%

Line Branch Exec Source
1 #include <string>
2 #include "asar.h"
3 #include "assembleblock.h"
4 #include "asar_math.h"
5
6 #define write1 write1_pick
7
8 2106 void asinit_65816()
9 {
10 2106 }
11
12 1968 void asend_65816()
13 {
14 1968 }
15
16 // like an address mode, but without a specific width
17 enum class addr_kind {
18 abs, // $00
19 x, // $00,x
20 y, // $00,y
21 ind, // ($00)
22 lind, // [$00]
23 xind, // ($00,x)
24 indy, // ($00),y
25 lindy, // [$00],y
26 s, // $00,s
27 sy, // ($00,s),y
28 imp, // implied (no argument)
29 a, // 'A' as argument
30 imm, // #$00
31 };
32
33 5787 struct insn_context {
34 string arg;
35 char orig_insn[3]; // oops i didn't end up using this... could be useful in some error messages maybe
36 char modifier;
37 };
38
39 // checks for matching characters at the start of haystack, ignoring spaces.
40 // returns index into haystack right after the match
41 template<char... chars>
42 58074 ssize_t startmatch(const string& haystack) {
43 static const char needle[] = {chars...};
44 29058 size_t haystack_i = 0;
45
2/2
✓ Branch 0 taken 29037 times.
✓ Branch 1 taken 2415 times.
62904 for(size_t i = 0; i < sizeof...(chars); i++) {
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29037 times.
58074 while(haystack[haystack_i] == ' ') haystack_i++;
47
2/2
✓ Branch 0 taken 14526 times.
✓ Branch 1 taken 14511 times.
58074 if(needle[i] != to_lower(haystack[haystack_i++])) return -1;
48 }
49 4830 return haystack_i;
50 }
51
52 // checks for matching characters at the end of haystack, ignoring spaces.
53 // returns index into haystack right before the match
54 template<char... chars>
55
1/2
✓ Branch 0 taken 12105 times.
✗ Branch 1 not taken.
48456 ssize_t endmatch(const string& haystack) {
56 static const char needle[] = {chars...};
57 48456 ssize_t haystack_i = haystack.length()-1;
58
2/2
✓ Branch 0 taken 28296 times.
✓ Branch 1 taken 2898 times.
62388 for(ssize_t i = sizeof...(chars)-1; i >= 0; i--) {
59
4/6
✓ Branch 0 taken 19458 times.
✓ Branch 1 taken 8838 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19458 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14157 times.
56592 while(haystack_i >= 0 && haystack[haystack_i] == ' ') haystack_i--;
60
6/6
✓ Branch 0 taken 19458 times.
✓ Branch 1 taken 8838 times.
✓ Branch 2 taken 9738 times.
✓ Branch 3 taken 9720 times.
✓ Branch 4 taken 10674 times.
✓ Branch 5 taken 3483 times.
56592 if(haystack_i < 0 || needle[i] != to_lower(haystack[haystack_i--])) return -1;
61 }
62 5796 return haystack_i+1;
63 }
64
65 /*
66 * Parses the address kind from an argument, given a list of allowed address kinds.
67 * Throws "invalid address mode" if the argument does not match any kinds.
68 */
69 // i still don't like this function...
70 template<addr_kind... allowed_kinds>
71
1/2
✓ Branch 0 taken 4824 times.
✗ Branch 1 not taken.
21690 std::pair<addr_kind, string> parse_addr_kind(insn_context& arg) {
72 10854 ssize_t start_i = 0, end_i = arg.arg.length();
73 // If this addressing kind is allowed, return it, along with a trimmed version of the string.
74 #define RETURN_IF_ALLOWED(kind) \
75 if constexpr(((allowed_kinds == addr_kind::kind) || ...)) { \
76 string out(arg.arg.data() + start_i, end_i - start_i); \
77 return std::make_pair(addr_kind::kind, out); \
78 }
79
2/2
✓ Branch 0 taken 1425 times.
✓ Branch 1 taken 9420 times.
21690 if((start_i = startmatch<'#'>(arg.arg)) >= 0) {
80
2/4
✓ Branch 0 taken 714 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 714 times.
✗ Branch 3 not taken.
5736 RETURN_IF_ALLOWED(imm);
81 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
82 }
83
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 8772 times.
18840 if((start_i = startmatch<'('>(arg.arg)) >= 0) {
84
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 504 times.
1296 if((end_i = endmatch<',', 's', ')', ',', 'y'>(arg.arg)) >= 0) {
85
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);
86 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
87 }
88
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 360 times.
1008 if((end_i = endmatch<')', ',', 'y'>(arg.arg)) >= 0) {
89
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);
90 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
91 }
92
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 180 times.
720 if((end_i = endmatch<',', 'x', ')'>(arg.arg)) >= 0) {
93
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);
94 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
95 }
96
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
360 if((end_i = endmatch<')'>(arg.arg)) >= 0) {
97
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
738 RETURN_IF_ALLOWED(ind);
98 asar_throw_warning(1, warning_id_assuming_address_mode, "($00)", "$00", " (if this was intentional, add a +0 after the parentheses.)");
99 }
100 }
101
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 8430 times.
17544 if((start_i = startmatch<'['>(arg.arg)) >= 0) {
102
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 198 times.
684 if((end_i = endmatch<']', ',', 'y'>(arg.arg)) >= 0) {
103
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);
104 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
105 }
106
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
396 if((end_i = endmatch<']'>(arg.arg)) >= 0) {
107
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);
108 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
109 }
110 }
111 8436 start_i = 0;
112
2/2
✓ Branch 0 taken 1530 times.
✓ Branch 1 taken 6900 times.
16860 if((end_i = endmatch<',', 'x'>(arg.arg)) >= 0) {
113
2/4
✓ Branch 0 taken 765 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 765 times.
✗ Branch 3 not taken.
6120 RETURN_IF_ALLOWED(x);
114 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
115 }
116
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 6666 times.
13800 if((end_i = endmatch<',', 'y'>(arg.arg)) >= 0) {
117
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);
118 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
119 }
120
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 6522 times.
13332 if((end_i = endmatch<',', 's'>(arg.arg)) >= 0) {
121
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);
122 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
123 }
124 // hoping that by now, something would have stripped whitespace lol
125
2/2
✓ Branch 0 taken 2934 times.
✓ Branch 1 taken 3588 times.
13044 if(arg.arg.length() == 0) {
126
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);
127 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
128 }
129
6/6
✓ Branch 0 taken 3570 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 3462 times.
✓ Branch 4 taken 63 times.
✓ Branch 5 taken 1734 times.
7176 if(arg.arg == "a" || arg.arg == "A") {
130
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);
131 // todo: some hint for "don't name your label "a" "?
132 36 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
133 }
134 if constexpr(((allowed_kinds == addr_kind::abs) || ...)) {
135
1/2
✓ Branch 0 taken 1734 times.
✗ Branch 1 not taken.
7476 return std::make_pair(addr_kind::abs, arg.arg);
136 }
137 asar_throw_error(1, error_type_block, error_id_bad_addr_mode);
138 #undef RETURN_IF_ALLOWED
139 // clang doesn't know that asar_throw_error is noreturn in this case... :(
140 // we don't really have anything good to return either tho
141 __builtin_unreachable();
142 }
143
144 const char* format_valid_widths(int min, int max) {
145 if(min == 1) {
146 if(max == 1) return "only 8-bit";
147 if(max == 2) return "only 8-bit or 16-bit";
148 if(max == 3) return "any width"; // shouldn't actually happen lol
149 } else if(min == 2) {
150 if(max == 2) return "only 16-bit";
151 if(max == 3) return "only 16-bit or 24-bit";
152 } else if(min == 3) {
153 return "only 24-bit";
154 }
155 return "???";
156 }
157
158 7305 int get_real_len(int min_len, int max_len, char modifier, int arg_min_len) {
159
2/2
✓ Branch 0 taken 2340 times.
✓ Branch 1 taken 4965 times.
7305 if(modifier != 0) {
160 2340 int given_len = getlenfromchar(modifier);
161
2/4
✓ Branch 0 taken 2322 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2322 times.
2322 if(given_len < min_len || given_len > max_len)
162 asar_throw_error(2, error_type_block, error_id_bad_access_width, format_valid_widths(min_len, max_len), given_len*8);
163 2322 return given_len;
164 } else {
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4965 times.
4965 if(arg_min_len > max_len) {
166 asar_throw_error(2, error_type_block, error_id_bad_access_width, format_valid_widths(min_len, max_len), arg_min_len*8);
167 }
168 // todo warn about widening when dpbase != 0
169 4965 return std::max(arg_min_len, min_len);
170 }
171 }
172
173 1113 void check_implicit_immediate(char modifier, const string& target) {
174
2/2
✓ Branch 0 taken 555 times.
✓ Branch 1 taken 558 times.
1113 if(modifier != 0) return;
175
2/2
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 288 times.
573 if(is_hex_constant(target.data())) return;
176 87 asar_throw_warning(2, warning_id_implicitly_sized_immediate);
177 }
178
179 template<int base, bool allow_imm = true>
180 9006 void the8(insn_context& arg) {
181 using K = addr_kind;
182
1/2
✓ Branch 0 taken 2253 times.
✗ Branch 1 not taken.
9006 auto parse_result = 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>(arg);
183 9006 addr_kind kind = parse_result.first;
184 4506 int min_len = 0, max_len = 4;
185
4/4
✓ Branch 0 taken 1501 times.
✓ Branch 1 taken 3002 times.
✓ Branch 2 taken 1489 times.
✓ Branch 3 taken 12 times.
9006 int64_t the_num = pass == 2 ? getnum(parse_result.second) : 0;
186
1/2
✓ Branch 0 taken 4491 times.
✗ Branch 1 not taken.
8982 int arg_min_len = getlen(parse_result.second, kind == K::imm);
187
14/14
✓ Branch 0 taken 2175 times.
✓ Branch 1 taken 2316 times.
✓ Branch 2 taken 2103 times.
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 2031 times.
✓ Branch 5 taken 72 times.
✓ Branch 6 taken 1959 times.
✓ Branch 7 taken 72 times.
✓ Branch 8 taken 1887 times.
✓ Branch 9 taken 72 times.
✓ Branch 10 taken 1815 times.
✓ Branch 11 taken 72 times.
✓ Branch 12 taken 72 times.
✓ Branch 13 taken 1743 times.
8982 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;
188
2/2
✓ Branch 0 taken 861 times.
✓ Branch 1 taken 882 times.
3486 else if(kind == K::abs) min_len = 1, max_len = 3;
189
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 450 times.
1764 else if(kind == K::x) min_len = 1, max_len = 3;
190
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 378 times.
900 else if(kind == K::y) min_len = max_len = 2;
191
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
756 else if(kind == K::imm) min_len = 1, max_len = 2;
192
3/4
✓ Branch 0 taken 753 times.
✓ Branch 1 taken 3738 times.
✓ Branch 2 taken 753 times.
✗ Branch 3 not taken.
8982 if(kind == K::imm) check_implicit_immediate(arg.modifier, parse_result.second);
193
2/2
✓ Branch 0 taken 4473 times.
✓ Branch 1 taken 18 times.
8982 int real_len = get_real_len(min_len, max_len, arg.modifier, arg_min_len);
194 4476 int opcode_offset = 0;
195
2/2
✓ Branch 0 taken 1965 times.
✓ Branch 1 taken 2508 times.
8946 if(real_len == 1) {
196
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 984 times.
3930 if(kind == K::xind) opcode_offset = 0x1;
197
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::s) opcode_offset = 0x3;
198
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::abs) opcode_offset = 0x5;
199
2/2
✓ Branch 0 taken 801 times.
✓ Branch 1 taken 984 times.
3570 if(kind == K::lind) opcode_offset = 0x7;
200
2/2
✓ Branch 0 taken 912 times.
✓ Branch 1 taken 981 times.
3786 if(kind == K::imm) opcode_offset = 0x9;
201
2/2
✓ Branch 0 taken 828 times.
✓ Branch 1 taken 984 times.
3624 if(kind == K::indy) opcode_offset = 0x11;
202
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::ind) opcode_offset = 0x12;
203
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::sy) opcode_offset = 0x13;
204
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 984 times.
3786 if(kind == K::x) opcode_offset = 0x15;
205
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 1677 times.
3642 if(kind == K::lindy) opcode_offset = 0x17;
206
2/2
✓ Branch 0 taken 1602 times.
✓ Branch 1 taken 906 times.
5016 } else if(real_len == 2) {
207
2/2
✓ Branch 0 taken 801 times.
✓ Branch 1 taken 801 times.
3204 if(kind == K::imm) opcode_offset = 0x9;
208
2/2
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 801 times.
2778 if(kind == K::abs) opcode_offset = 0xd;
209
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 801 times.
2460 if(kind == K::y) opcode_offset = 0x19;
210
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 1242 times.
3060 if(kind == K::x) opcode_offset = 0x1d;
211
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 453 times.
1812 } else if(real_len == 3) {
212
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 453 times.
1812 if(kind == K::abs) opcode_offset = 0xf;
213
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 453 times.
1194 if(kind == K::x) opcode_offset = 0x1f;
214 }
215
1/2
✓ Branch 0 taken 4473 times.
✗ Branch 1 not taken.
8946 write1(opcode_offset + base);
216
3/4
✓ Branch 0 taken 1965 times.
✓ Branch 1 taken 2508 times.
✓ Branch 2 taken 1965 times.
✗ Branch 3 not taken.
8946 if(real_len == 1) write1(the_num);
217
3/4
✓ Branch 0 taken 1602 times.
✓ Branch 1 taken 906 times.
✓ Branch 2 taken 1602 times.
✗ Branch 3 not taken.
5016 else if(real_len == 2) write2(the_num);
218
2/4
✓ Branch 0 taken 906 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 906 times.
✗ Branch 3 not taken.
1812 else if(real_len == 3) write3(the_num);
219 8976 }
220
221 template<int base, int accum_opc, bool is_bit = false>
222 2448 void thenext8(insn_context& arg) {
223 using K = addr_kind;
224 addr_kind kind;
225 1224 string parsed_str;
226 if constexpr(is_bit) {
227
1/2
✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
432 auto parse_result = parse_addr_kind<K::x, K::abs, K::imm>(arg);
228 432 kind = parse_result.first;
229
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
216 parsed_str = parse_result.second;
230 216 } else {
231
1/2
✓ Branch 0 taken 1008 times.
✗ Branch 1 not taken.
2016 auto parse_result = parse_addr_kind<K::x, K::abs, K::imm, K::a, K::imp>(arg);
232 2016 kind = parse_result.first;
233
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
1008 parsed_str = parse_result.second;
234 // todo: some checks on arg.modifier here
235
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 972 times.
2016 if(kind == K::imm) {
236 // implied rep
237
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 int64_t rep_count = getnum(parsed_str);
238
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if(foundlabel) asar_throw_error(0, error_type_block, error_id_no_labels_here);
239
3/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 36 times.
252 for (int64_t i=0;i<rep_count;i++) { write1(accum_opc); }
240 36 return;
241 }
242
3/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 486 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 432 times.
1944 if(kind == K::a || kind == K::imp) {
243
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
216 write1(accum_opc);
244 108 return;
245 }
246
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 72 times.
1008 }
247
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_str) : 0;
248
1/2
✓ Branch 0 taken 1080 times.
✗ Branch 1 not taken.
2160 int arg_min_len = getlen(parsed_str, kind == K::imm);
249
1/2
✓ Branch 0 taken 1080 times.
✗ Branch 1 not taken.
2160 int real_len = get_real_len(1, 2, arg.modifier, arg_min_len);
250 1080 int opcode = 0;
251
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 576 times.
1296 if(kind == K::imm) {
252
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
144 check_implicit_immediate(arg.modifier, parsed_str);
253 72 opcode = accum_opc;
254
2/2
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 504 times.
2016 } else if(real_len == 1) {
255
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 252 times.
1008 if(kind == K::abs) opcode = base+0x6;
256
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 252 times.
756 if(kind == K::x) opcode = base+0x16;
257
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 252 times.
1008 } else if(real_len == 2) {
258
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 252 times.
1008 if(kind == K::abs) opcode = base+0xe;
259
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 252 times.
756 if(kind == K::x) opcode = base+0x1e;
260 }
261
1/2
✓ Branch 0 taken 1080 times.
✗ Branch 1 not taken.
2160 write1(opcode);
262
3/4
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 540 times.
✓ Branch 2 taken 540 times.
✗ Branch 3 not taken.
2160 if(real_len == 1) write1(the_num);
263
2/4
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 540 times.
✗ Branch 3 not taken.
1080 else if(real_len == 2) write2(the_num);
264
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 72 times.
2448 }
265
266 template<int base>
267 288 void tsb_trb(insn_context& arg) {
268 using K = addr_kind;
269
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
288 auto parse_result = parse_addr_kind<K::abs>(arg);
270
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(parse_result.second) : 0;
271
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
288 int arg_min_len = getlen(parse_result.second, false);
272
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
288 int real_len = get_real_len(1, 2, arg.modifier, arg_min_len);
273
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
288 int opcode_offset = real_len == 1 ? 0x04 : 0x0c;
274
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
288 write1(opcode_offset + base);
275
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) write1(the_num);
276
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
144 else if(real_len == 2) write2(the_num);
277 288 }
278
279 template<int opc, int width = 1>
280 432 void branch(insn_context& arg) {
281 using K = addr_kind;
282
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 9 times.
432 auto parse_result = parse_addr_kind<K::abs>(arg);
283 198 int64_t num = 0;
284
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 132 times.
396 if(pass == 2) {
285
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
132 num = getnum(parse_result.second);
286
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 6 times.
132 if(foundlabel) {
287 120 int64_t delta = num - (snespos + width + 1);
288
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 57 times.
120 if((num & ~0xffff) != (snespos & ~0xffff)) {
289 // todo: should throw error "can't branch to different bank"
290 asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(delta).data());
291 }
292
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)) {
293 asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(delta).data());
294 }
295 60 num = delta;
296 } else {
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 if(num & ~(width==2 ? 0xffff : 0xff)) {
298 asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(num).data());
299 }
300 12 num = (int16_t)(width==2 ? num : (int8_t)num);
301 }
302 }
303
304
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
396 write1(opc);
305
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
324 if(width == 1) write1(num);
306
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 else if(width == 2) write2(num);
307 396 }
308
309 template<int opc>
310 1404 void implied(insn_context& arg) {
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 702 times.
1404 if(arg.arg != "") {
312 // todo: some kind of "this instruction doesn't take an argument" message?
313 asar_throw_error(0, error_type_block, error_id_bad_addr_mode);
314 }
315 1404 write1(opc);
316 1404 }
317
318 template<int opc>
319 6120 void implied_rep(insn_context& arg) {
320 using K = addr_kind;
321
1/2
✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
6120 auto parse_result = parse_addr_kind<K::imm, K::imp>(arg);
322
2/2
✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 180 times.
6120 if(parse_result.first == K::imp) {
323
1/2
✓ Branch 0 taken 2880 times.
✗ Branch 1 not taken.
5760 write1(opc);
324 } else {
325
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
360 int64_t rep_count = getnum(parse_result.second);
326
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
360 if(foundlabel) asar_throw_error(0, error_type_block, error_id_no_labels_here);
327
3/4
✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 414 times.
✓ Branch 3 taken 180 times.
1188 for (int64_t i=0;i<rep_count;i++) { write1(opc); }
328 }
329 6120 }
330
331 template<int base, char op, char xy>
332 1800 void xy_ops(insn_context& arg) {
333 using K = addr_kind;
334 900 std::pair<addr_kind, string> parse_result;
335 if(op == 'S') { // stx
336
2/4
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
360 parse_result = parse_addr_kind<K::abs, (xy == 'X' ? K::y : K::x)>(arg);
337 } else if(op == 'L') { // ldx
338
2/4
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
✗ Branch 3 not taken.
864 parse_result = parse_addr_kind<K::abs, K::imm, (xy == 'X' ? K::y : K::x)>(arg);
339 } else { // cpx
340
2/4
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
576 parse_result = parse_addr_kind<K::abs, K::imm>(arg);
341 }
342
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(parse_result.second) : 0;
343
1/2
✓ Branch 0 taken 900 times.
✗ Branch 1 not taken.
1800 int arg_min_len = getlen(parse_result.second, false);
344
1/2
✓ Branch 0 taken 900 times.
✗ Branch 1 not taken.
1800 int real_len = get_real_len(1, 2, arg.modifier, arg_min_len);
345 900 int opcode = 0;
346
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 612 times.
1800 if(parse_result.first == K::imm) {
347
1/2
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
576 check_implicit_immediate(arg.modifier, parse_result.second);
348 288 opcode = base;
349
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 180 times.
1224 } else if(parse_result.first == K::abs) {
350
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 216 times.
864 if(real_len == 1) opcode = base + 0x4;
351 216 else opcode = base + 0xc;
352 } else { // ,x or ,y
353
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 90 times.
360 if(real_len == 1) opcode = base + 0x14;
354 72 else opcode = base + 0x1c;
355 }
356
1/2
✓ Branch 0 taken 900 times.
✗ Branch 1 not taken.
1800 write1(opcode);
357
3/4
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 432 times.
✓ Branch 2 taken 468 times.
✗ Branch 3 not taken.
1800 if(real_len == 1) write1(the_num);
358
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) write2(the_num);
359 1800 }
360
361 template<int opc>
362 216 void interrupt(insn_context& arg) {
363 using K = addr_kind;
364
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
216 auto parse_result = parse_addr_kind<K::imm, K::imp>(arg);
365
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
216 if(parse_result.first == K::imp) {
366
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 write1(opc);
367
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 write1(0);
368 } else {
369
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(parse_result.second) : 0;
370 // this is kinda hacky
371
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);
372
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 write1(opc);
373
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 write1(num);
374 }
375 216 }
376
377 template<int opc, addr_kind k, int width>
378 504 void oneoff(insn_context& arg) {
379
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
504 auto parse_result = parse_addr_kind<k>(arg);
380
3/4
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
504 int64_t the_num = pass == 2 ? getnum(parse_result.second) : 0;
381
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
504 int arg_min_len = getlen(parse_result.second, false);
382 // only for error checking, we know the answer anyways
383
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
504 get_real_len(width, width, arg.modifier, arg_min_len);
384
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
504 write1(opc);
385
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
108 if(width == 1) write1(the_num);
386
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 else if(width == 2) write2(the_num);
387
1/2
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
360 else if(width == 3) write3(the_num);
388 504 }
389
390 144 void stz(insn_context& arg) {
391 using K = addr_kind;
392
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
144 auto parse_result = parse_addr_kind<K::abs, K::x>(arg);
393
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(parse_result.second) : 0;
394
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 int arg_min_len = getlen(parse_result.second, false);
395
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 int real_len = get_real_len(1, 2, arg.modifier, arg_min_len);
396
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
144 if(real_len == 1) {
397
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 if(parse_result.first == K::abs) write1(0x64);
398
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 else if(parse_result.first == K::x) write1(0x74);
399
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 write1(the_num);
400 } else {
401
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 if(parse_result.first == K::abs) write1(0x9c);
402
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 else if(parse_result.first == K::x) write1(0x9e);
403
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 write2(the_num);
404 }
405 144 }
406
407 template<char which>
408 588 void jmp_jsr_jml(insn_context& arg) {
409 using K = addr_kind;
410
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
588 auto parse_result = which == 'R' ? parse_addr_kind<K::abs, K::xind>(arg)
411 : which == 'P' ? parse_addr_kind<K::abs, K::xind, K::ind, K::lind>(arg)
412 : /* 'L' */ parse_addr_kind<K::abs, K::lind>(arg);
413
3/4
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 196 times.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
588 int64_t the_num = pass == 2 ? getnum(parse_result.second) : 0;
414 // set optimizeforbank to -1 (i.e. auto, assume DBR = current bank)
415 // because jmp and jsr's arguments are relative to the program bank anyways
416 588 int old_optimize = optimizeforbank;
417
4/4
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 114 times.
588 if(parse_result.first == K::lind || parse_result.first == K::ind) {
418 // these ones for Some Reason always read the pointer from bank 0 lol
419 144 optimizeforbank = 0;
420 } else {
421 // the rest use bank K
422 444 optimizeforbank = -1;
423 }
424
1/2
✓ Branch 0 taken 294 times.
✗ Branch 1 not taken.
588 int arg_min_len = getlen(parse_result.second, false);
425 588 optimizeforbank = old_optimize;
426
3/5
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
606 get_real_len(2, (which == 'L' && parse_result.first == K::abs) ? 3 : 2, arg.modifier, arg_min_len);
427 if(which == 'R') {
428
3/4
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
288 if(parse_result.first == K::abs) write1(0x20);
429
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 else if(parse_result.first == K::xind) write1(0xfc);
430 } else if(which == 'L') {
431
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
108 if(parse_result.first == K::abs) {
432
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 write1(0x5c);
433
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 write3(the_num);
434 36 return;
435
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 } else if(parse_result.first == K::lind) {
436
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 write1(0xdc);
437 }
438 } else {
439
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
192 if(parse_result.first == K::abs) write1(0x4c);
440
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
144 else if(parse_result.first == K::ind) write1(0x6c);
441
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
108 else if(parse_result.first == K::xind) write1(0x7c);
442
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
72 else if(parse_result.first == K::lind) write1(0xdc);
443 }
444
1/2
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
516 write2(the_num);
445
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 18 times.
300 }
446
447 template<int opc>
448 72 void mvn_mvp(insn_context& arg) {
449 int count;
450
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
72 autoptr<char**> parts = qpsplit(arg.arg.raw(), ',', &count);
451
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);
452 // todo length checks ???
453
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 write1(opc);
454
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 24 times.
72 if(pass == 2) {
455
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]));
456
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]));
457 } else {
458
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 write2(0);
459 }
460 72 }
461
462 assocarr<void(*)(insn_context&)> mnemonics = {
463 { "ora", the8<0x00> },
464 { "and", the8<0x20> },
465 { "eor", the8<0x40> },
466 { "adc", the8<0x60> },
467 { "sta", the8<0x80, false> },
468 { "lda", the8<0xa0> },
469 { "cmp", the8<0xc0> },
470 { "sbc", the8<0xe0> },
471 { "asl", thenext8<0x00, 0x0a> },
472 { "bit", thenext8<0x1e, 0x89, true> },
473 { "rol", thenext8<0x20, 0x2a> },
474 { "lsr", thenext8<0x40, 0x4a> },
475 { "ror", thenext8<0x60, 0x6a> },
476 { "dec", thenext8<0xc0, 0x3a> },
477 { "inc", thenext8<0xe0, 0x1a> },
478 { "bcc", branch<0x90> },
479 { "bcs", branch<0xb0> },
480 { "beq", branch<0xf0> },
481 { "bmi", branch<0x30> },
482 { "bne", branch<0xd0> },
483 { "bpl", branch<0x10> },
484 { "bra", branch<0x80> },
485 { "bvc", branch<0x50> },
486 { "bvs", branch<0x70> },
487 { "brl", branch<0x82, 2> },
488 { "clc", implied<0x18> },
489 { "cld", implied<0xd8> },
490 { "cli", implied<0x58> },
491 { "clv", implied<0xb8> },
492 { "dex", implied_rep<0xca> },
493 { "dey", implied_rep<0x88> },
494 { "inx", implied_rep<0xe8> },
495 { "iny", implied_rep<0xc8> },
496 { "nop", implied_rep<0xea> },
497 { "pha", implied<0x48> },
498 { "phb", implied<0x8b> },
499 { "phd", implied<0x0b> },
500 { "phk", implied<0x4b> },
501 { "php", implied<0x08> },
502 { "phx", implied<0xda> },
503 { "phy", implied<0x5a> },
504 { "pla", implied<0x68> },
505 { "plb", implied<0xab> },
506 { "pld", implied<0x2b> },
507 { "plp", implied<0x28> },
508 { "plx", implied<0xfa> },
509 { "ply", implied<0x7a> },
510 { "rti", implied<0x40> },
511 { "rtl", implied<0x6b> },
512 { "rts", implied<0x60> },
513 { "sec", implied<0x38> },
514 { "sed", implied<0xf8> },
515 { "sei", implied<0x78> },
516 { "stp", implied<0xdb> },
517 { "tax", implied<0xaa> },
518 { "tay", implied<0xa8> },
519 { "tcd", implied<0x5b> },
520 { "tcs", implied<0x1b> },
521 { "tdc", implied<0x7b> },
522 { "tsc", implied<0x3b> },
523 { "tsx", implied<0xba> },
524 { "txa", implied<0x8a> },
525 { "txs", implied<0x9a> },
526 { "txy", implied<0x9b> },
527 { "tya", implied<0x98> },
528 { "tyx", implied<0xbb> },
529 { "wai", implied<0xcb> },
530 { "xba", implied<0xeb> },
531 { "xce", implied<0xfb> },
532 { "ldy", xy_ops<0xa0, 'L', 'Y'> },
533 { "ldx", xy_ops<0xa2, 'L', 'X'> },
534 { "cpy", xy_ops<0xc0, 'C', 'Y'> },
535 { "cpx", xy_ops<0xe0, 'C', 'X'> },
536 { "stx", xy_ops<0x82, 'S', 'X'> },
537 { "sty", xy_ops<0x80, 'S', 'Y'> },
538 { "cop", interrupt<0x02> },
539 { "wdm", interrupt<0x42> },
540 { "brk", interrupt<0x00> },
541 { "tsb", tsb_trb<0x00> },
542 { "trb", tsb_trb<0x10> },
543 { "rep", oneoff<0xc2, addr_kind::imm, 1> },
544 { "sep", oneoff<0xe2, addr_kind::imm, 1> },
545 { "pei", oneoff<0xd4, addr_kind::ind, 1> },
546 { "pea", oneoff<0xf4, addr_kind::abs, 2> },
547 { "mvn", mvn_mvp<0x54> },
548 { "mvp", mvn_mvp<0x44> },
549 { "jsl", oneoff<0x22, addr_kind::abs, 3> },
550 { "per", branch<0x62, 2> },
551 { "stz", stz },
552 { "jmp", jmp_jsr_jml<'P'> },
553 { "jsr", jmp_jsr_jml<'R'> },
554 { "jml", jmp_jsr_jml<'L'> },
555 };
556
557
558 67332 bool asblock_65816(char** word, int numwords)
559 {
560 #define is(test) (!stricmpwithupper(word[0], test))
561
2/2
✓ Branch 0 taken 36846 times.
✓ Branch 1 taken 30486 times.
67332 if(word[0][0] == '\'') return false;
562 29883 string par;
563
2/2
✓ Branch 0 taken 60963 times.
✓ Branch 1 taken 66126 times.
127089 for(int i = 1; i < numwords; i++){
564
3/4
✓ Branch 0 taken 1848 times.
✓ Branch 1 taken 59115 times.
✓ Branch 2 taken 924 times.
✗ Branch 3 not taken.
60963 if(i > 1) par += " ";
565
1/2
✓ Branch 0 taken 27288 times.
✗ Branch 1 not taken.
60963 par += word[i];
566 }
567 // todo handle code like `nop = $1234`
568
1/2
✓ Branch 0 taken 29883 times.
✗ Branch 1 not taken.
66126 string opc = word[0];
569
4/4
✓ Branch 0 taken 368832 times.
✓ Branch 1 taken 36243 times.
✓ Branch 2 taken 150231 times.
✓ Branch 3 taken 29883 times.
441318 for(int i = 0; i < opc.length(); i++) opc.raw()[i] = to_lower(opc[i]);
570 29883 char mod = 0;
571
9/10
✓ Branch 0 taken 65982 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 30909 times.
✓ Branch 3 taken 35073 times.
✓ Branch 4 taken 29739 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1170 times.
✓ Branch 7 taken 28569 times.
✓ Branch 8 taken 1170 times.
✓ Branch 9 taken 28713 times.
66126 if(opc.length() >= 2 && opc[opc.length()-2] == '.') {
572
1/2
✓ Branch 0 taken 1170 times.
✗ Branch 1 not taken.
2340 mod = opc[opc.length()-1];
573
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);
574 }
575
4/4
✓ Branch 0 taken 35670 times.
✓ Branch 1 taken 30456 times.
✓ Branch 2 taken 24087 times.
✓ Branch 3 taken 5796 times.
66126 if(!mnemonics.exists(opc.data())) return false;
576
2/2
✓ Branch 0 taken 11559 times.
✓ Branch 1 taken 24 times.
11583 insn_context ctx{par, {}, mod};
577 11583 ctx.orig_insn[0] = opc[0];
578 11583 ctx.orig_insn[1] = opc[1];
579 11583 ctx.orig_insn[2] = opc[2];
580
4/4
✓ Branch 0 taken 11559 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 5772 times.
✓ Branch 3 taken 24 times.
11583 mnemonics.find(opc.data())(ctx);
581 5772 return true;
582 66198 }
583