blob: bcc141504fc63c7138b82143fde07a0bab99c4d7 [file] [log] [blame]
swissChili97b5d8b2020-08-15 20:00:54 -07001#include "as.h"
2#include "../cpu.h"
3#include "../instructions.h"
4#include "../mnemonics.h"
swissChilica0d2e22020-08-16 15:09:25 -07005#include "map.h"
swissChili97b5d8b2020-08-15 20:00:54 -07006
swissChilidab15a62020-08-17 15:41:27 -07007#include <endian.h>
8#include <stdio.h>
swissChili97b5d8b2020-08-15 20:00:54 -07009#include <string.h>
10#include <ctype.h>
11#include <stdbool.h>
12
swissChiliabccdfc2021-01-08 21:39:12 -080013#ifdef VERBOSE_ASSEMBLER
14#define dbgf(fmt, ...) fprintf(fmt, __VA_ARGS__)
15#else
16#define dbgf(fmt, ...)
17#endif
18
swissChili97b5d8b2020-08-15 20:00:54 -070019enum
20{
21 ARG_16, /* Absolute 16 bit argument */
22 ARG_8, /* Absolute 8 bit argument */
23 ARG_8REL, /* Relative 8 bit argument */
24 ARG_REL, /* Relative label */
25 ARG_ABS, /* Absolute label */
26 ARG_IMP, /* Implied argument */
27};
28
swissChilidab15a62020-08-17 15:41:27 -070029#define MAX_LEN (0xFFFF - 0x600)
30#define MAX_INSTS (MAX_LEN / 2)
swissChili7acb4ce2020-08-16 20:16:10 -070031
swissChili97b5d8b2020-08-15 20:00:54 -070032typedef struct
33{
34 uint8_t opcode;
35 uint8_t arg_type;
swissChili7acb4ce2020-08-16 20:16:10 -070036 uint16_t line;
swissChili97b5d8b2020-08-15 20:00:54 -070037 union
38 {
39 char label[32];
40 uint16_t long_arg;
41 uint8_t byte_arg;
42 int8_t rel_arg;
43 };
44} inst_t;
45
swissChilidab15a62020-08-17 15:41:27 -070046typedef struct ll_node
47{
48 struct ll_node *last;
49 char name[32];
50 uint16_t addr;
51} ll_node_t;
52
swissChili7acb4ce2020-08-16 20:16:10 -070053// Normal strtok() counts 2 seperators as one, ie asdf\n\njlk is 2 lines.
54// This functions counts that as 3 lines, and will return an empty line in between.
55char *strtok_fix(char *string, const char *token)
56{
57 static char *pos;
58 if (string)
59 pos = string;
60 else
61 string = pos;
62
63 if (*pos == 0)
64 return NULL;
65
66 for (; *string; string++)
67 {
68 for (int i = 0; i < strlen(token); i++)
69 {
70 if (*string == token[i])
71 {
72 *string = 0;
73 char *old_pos = pos;
74 pos = string + 1;
75
76 return old_pos;
77 }
78 }
79 }
80 return pos;
81}
82
swissChilidab15a62020-08-17 15:41:27 -070083void putshort(uint16_t a, FILE *out)
84{
85 uint16_t le = htole16(a);
86 fwrite(&le, sizeof(uint16_t), 1, out);
87}
88
swissChili97b5d8b2020-08-15 20:00:54 -070089void print_inst(inst_t *arg)
90{
91 char *arg_types =
92 "16 8 8RELREL ABS IMP ";
93
swissChiliabccdfc2021-01-08 21:39:12 -080094 dbgf("\033[33mInst: %.4s $%x ", arg_types + arg->arg_type * 4, arg->opcode);
swissChili97b5d8b2020-08-15 20:00:54 -070095
96 switch (arg->arg_type)
97 {
98 case ARG_16:
swissChiliabccdfc2021-01-08 21:39:12 -080099 dbgf("%x", arg->long_arg);
swissChili97b5d8b2020-08-15 20:00:54 -0700100 break;
101 case ARG_8:
swissChiliabccdfc2021-01-08 21:39:12 -0800102 dbgf("%x", arg->byte_arg);
swissChili97b5d8b2020-08-15 20:00:54 -0700103 break;
104 case ARG_8REL:
swissChiliabccdfc2021-01-08 21:39:12 -0800105 dbgf("%d", arg->rel_arg);
swissChili97b5d8b2020-08-15 20:00:54 -0700106 break;
107 case ARG_REL:
108 case ARG_ABS:
swissChiliabccdfc2021-01-08 21:39:12 -0800109 dbgf("%s", arg->label);
swissChili97b5d8b2020-08-15 20:00:54 -0700110 break;
111 }
112
swissChiliabccdfc2021-01-08 21:39:12 -0800113 dbgf("\033[0m\n");
swissChili97b5d8b2020-08-15 20:00:54 -0700114}
115
116bool is_ident(char c)
117{
swissChilia4f49b52020-08-16 17:35:37 -0700118 return c && (isalpha(c) || isdigit(c)
119 || c == '_' || c == '-'
120 || c == '$' || c == '.');
swissChili97b5d8b2020-08-15 20:00:54 -0700121}
122
123uint32_t skip_ws(char **code)
124{
125 uint32_t len = 0;
126
swissChilia4f49b52020-08-16 17:35:37 -0700127 for (; **code == ' ' || **code == '\t'; (*code)++, len++)
swissChili97b5d8b2020-08-15 20:00:54 -0700128 {}
129
130 return len;
131}
132
133uint32_t skip_to_eol(char **code)
134{
135 uint32_t len = 0;
136
137 for (; **code && **code != '\n'; (*code)++, len++)
138 {}
139
140 if (**code)
141 (*code)++;
142
143 return len;
144}
145
146char *parse_label_name(char **code)
147{
148 char *start = *code;
149 for (; is_ident(**code); (*code)++)
150 {}
151
152 if (start == *code)
153 return false;
154
155 **code = 0;
156 return start;
157}
158
159char *parse_label(char **code)
160{
161 char *start = *code;
162
163 for (; is_ident(**code); (*code)++)
164 {}
165
166 skip_ws(code);
167
swissChilia4f49b52020-08-16 17:35:37 -0700168 if (*code != start && **code == ':')
swissChili97b5d8b2020-08-15 20:00:54 -0700169 {
170 **code = 0;
171 (*code)++;
172 return start;
173 }
swissChiliabccdfc2021-01-08 21:39:12 -0800174 dbgf(">> lkl: **code == %c %x\n", **code, **code);
swissChili97b5d8b2020-08-15 20:00:54 -0700175
176 *code = start;
177
178 return NULL;
179}
180
181char *parse_inst(char **code)
182{
183 char *start = *code;
184
185 for (; isalpha(**code); (*code)++)
186 {}
187
swissChili97b5d8b2020-08-15 20:00:54 -0700188 if (start == *code)
189 return NULL;
190
swissChilia4f49b52020-08-16 17:35:37 -0700191 // If code is incremented when it points to \0, it will wrap to the next line
192 // returned by strtok(), which causes a bug where instructions followed immediately
193 // by a newline and no arguments causes the next instruction to parse the entire
194 // program as its argument (not good)
195 if (**code)
196 {
197 **code = 0;
198 (*code)++;
199 }
200
swissChili97b5d8b2020-08-15 20:00:54 -0700201 return start;
202}
203
204bool is_eol(char c)
205{
206 return c == ';' ||
207 c == '\n' ||
swissChili97b5d8b2020-08-15 20:00:54 -0700208 c == '\0';
209}
210
211bool skip(char **code, const char *p)
212{
213 for (; *p && *p == **code; p++, (*code)++)
214 {}
215
216 if (!*p)
217 return true;
218 return false;
219}
220
221bool parse_num(char **code, uint64_t *num)
222{
223 char *start = *code;
224 int base = 10;
225 if (**code == '$')
226 {
227 base = 16;
228 (*code)++;
229 }
230
231 skip_ws(code);
232
233 char *endptr = *code;
234 int64_t val = strtol(*code, &endptr, base);
235
236 if (*code == endptr)
237 {
238 *code = start;
239 return false;
240 }
241 *num = val;
242 *code = endptr;
243 return true;
244}
245
246bool parse_num_max(char **code, uint64_t *num, uint64_t max)
247{
248 uint64_t n;
249 if (parse_num(code, &n))
250 {
251 if (n > max)
252 return false;
253
254 *num = n;
255 return true;
256 }
257 else return false;
258}
259
260bool parse_u8(char **code, uint8_t *num)
261{
262 uint64_t n;
263 if (!parse_num_max(code, &n, 0xFF))
264 return false;
265
266 *num = n & 0xFF;
267 return true;
268}
269
270bool parse_u16(char **code, uint16_t *num)
271{
272 uint64_t n;
273 if (!parse_num_max(code, &n, 0xFFFF))
274 return false;
275
276 *num = n & 0xFFFF;
277 return true;
278}
279
280bool ws_end(char **code)
281{
282 skip_ws(code);
283 return is_eol(**code);
284}
285
286bool parse_arg(char *code, int am, inst_t *inst)
287{
288 skip_ws(&code);
289
290 uint16_t num;
291 uint8_t num8;
292 char *lbl;
293
294 switch (am)
295 {
296 case AM_ACC:
297 case AM_IMP:
swissChiliabccdfc2021-01-08 21:39:12 -0800298 dbgf("Trying AM_IMP on '%.8s'\n", code);
swissChili97b5d8b2020-08-15 20:00:54 -0700299 skip_ws(&code);
300 if (is_eol(*code))
301 {
302 inst->arg_type = ARG_IMP;
303 return ws_end(&code);
304 }
305 break;
306
307 case AM_IMM:
swissChiliabccdfc2021-01-08 21:39:12 -0800308 dbgf("Trying AM_IMM on '%.8s'\n", code);
swissChili97b5d8b2020-08-15 20:00:54 -0700309 if (!skip(&code, "#"))
310 return false;
311 skip_ws(&code);
312 case AM_ZP:
313 if (parse_u8(&code, &num8))
314 {
315 inst->arg_type = ARG_8;
316 inst->byte_arg = num8;
317
318 return ws_end(&code);
319 }
320 break;
321
322 case AM_ABS:
323 if (parse_u16(&code, &num))
324 {
325 inst->arg_type = ARG_16;
326 inst->long_arg = num;
swissChilidab15a62020-08-17 15:41:27 -0700327 return ws_end(&code);
swissChili97b5d8b2020-08-15 20:00:54 -0700328 }
329 else if ((lbl = parse_label_name(&code)))
330 {
331 inst->arg_type = ARG_ABS;
332 strncpy(inst->label, lbl, 32);
swissChilidab15a62020-08-17 15:41:27 -0700333 return ws_end(&code);
swissChili97b5d8b2020-08-15 20:00:54 -0700334 }
335 break;
336
337 case AM_REL:
338 if (parse_u8(&code, &num8))
339 {
340 inst->arg_type = ARG_8REL;
341 inst->rel_arg = num;
342 return ws_end(&code);
343 }
344 else if ((lbl = parse_label_name(&code)))
345 {
346 inst->arg_type = ARG_REL;
347 strncpy(inst->label, lbl, 32);
348 return ws_end(&code);
349 }
350 break;
351
352 case AM_IND:
353 if (!skip(&code,"("))
354 return false;
355
356 if (!parse_u16(&code, &num))
357 return false;
358
359 if (!skip(&code, ")"))
360 return false;
361
362 inst->arg_type = ARG_16;
363 inst->long_arg = num;
swissChilidab15a62020-08-17 15:41:27 -0700364 return ws_end(&code);
swissChili97b5d8b2020-08-15 20:00:54 -0700365
366 case AM_AX:
367 case AM_ZPX:
368 case AM_AY:
369 case AM_ZPY:
370 if (am == AM_AX || am == AM_AY)
371 {
372 if (!parse_u16(&code, &num))
373 return false;
374 inst->arg_type = ARG_16;
375 inst->long_arg = num;
376 }
377 else
378 {
379 if (!parse_u8(&code, &num8))
380 return false;
381 inst->arg_type = ARG_8;
382 inst->byte_arg = num8;
383 }
swissChiliabccdfc2021-01-08 21:39:12 -0800384 dbgf("Parsing AM_* worked, now parsing ,\n");
swissChili97b5d8b2020-08-15 20:00:54 -0700385 if (!skip(&code, ","))
386 return false;
387
388 skip_ws(&code);
swissChiliabccdfc2021-01-08 21:39:12 -0800389 dbgf(", worked yup\n");
swissChilidab15a62020-08-17 15:41:27 -0700390 char reg = (am == AM_AY || am == AM_ZPY ? 'y' : 'x');
swissChiliabccdfc2021-01-08 21:39:12 -0800391 dbgf("reg is %c, *code is %c %x\n", reg, tolower(*code), tolower(*code));
swissChilidab15a62020-08-17 15:41:27 -0700392 if (tolower(*code) != reg)
swissChili97b5d8b2020-08-15 20:00:54 -0700393 return false;
swissChilidab15a62020-08-17 15:41:27 -0700394 (code)++;
swissChili97b5d8b2020-08-15 20:00:54 -0700395 return ws_end(&code);
396
397 case AM_ZIX:
398 if (!skip(&code, "("))
399 break;
400 skip_ws(&code);
401 if (!parse_u8(&code, &num8))
402 break;
403 skip_ws(&code);
404 if (!skip(&code, ","))
405 break;
406 skip_ws(&code);
407 if (tolower(*code) != 'x')
408 return false;
409 skip_ws(&code);
410
411 if (!skip(&code, ")"))
412 break;
413
414 inst->arg_type = ARG_8;
415 inst->byte_arg = num8;
416 return ws_end(&code);
417
418 case AM_ZIY:
419 if (!skip(&code, "("))
420 break;
421 skip_ws(&code);
422 if (!parse_u8(&code, &num8))
423 break;
424 skip_ws(&code);
425 if (!skip(&code, ")"))
426 break;
427 skip_ws(&code);
428 if (!skip(&code, ","))
429 break;
430 skip_ws(&code);
431 if (tolower(*code) != 'x')
432 break;
433
434 inst->arg_type = ARG_8;
435 inst->byte_arg = num8;
436 return ws_end(&code);
437 }
438 return false;
439}
440
swissChilidab15a62020-08-17 15:41:27 -0700441// Since program counter can never be < $600, return 0 on failure
442uint16_t ll_find(ll_node_t *head, char *name)
443{
444 ll_node_t *last = head;
445 while (last)
446 {
447 head = last;
448 if (!strcasecmp(head->name, name))
449 return head->addr;
450 last = head->last;
451 }
452 return 0;
453}
454
swissChili97b5d8b2020-08-15 20:00:54 -0700455uint32_t assemble(char *code, FILE *out)
456{
swissChilidab15a62020-08-17 15:41:27 -0700457 uint16_t num_insts = 0;
458 uint16_t pc = 0x600;
swissChili97b5d8b2020-08-15 20:00:54 -0700459 uint32_t line_no = 1;
swissChilidab15a62020-08-17 15:41:27 -0700460 ll_node_t *last_node = NULL;
swissChili7acb4ce2020-08-16 20:16:10 -0700461 char *line,
462 *orig_line,
463 *line_start;
swissChilidab15a62020-08-17 15:41:27 -0700464 inst_t **insts = calloc(sizeof(inst_t), MAX_INSTS);
swissChili97b5d8b2020-08-15 20:00:54 -0700465
swissChiliabccdfc2021-01-08 21:39:12 -0800466 dbgf("Assembling File\n");
467 dbgf("%s\n", code);
swissChili97b5d8b2020-08-15 20:00:54 -0700468
swissChili7acb4ce2020-08-16 20:16:10 -0700469 orig_line = strtok_fix(code, "\n");
470
471 while (orig_line)
swissChili97b5d8b2020-08-15 20:00:54 -0700472 {
swissChili7acb4ce2020-08-16 20:16:10 -0700473 line = strdup(orig_line);
474 line_start = line;
475
476 if (*line == 0)
477 goto end_of_line;
swissChili7acb4ce2020-08-16 20:16:10 -0700478
swissChili97b5d8b2020-08-15 20:00:54 -0700479 skip_ws(&line);
swissChilidab15a62020-08-17 15:41:27 -0700480
swissChiliabccdfc2021-01-08 21:39:12 -0800481 dbgf("line %d: \033[36m%.12s\033[0m\n", line_no, line);
swissChilidab15a62020-08-17 15:41:27 -0700482
swissChili7acb4ce2020-08-16 20:16:10 -0700483 if (is_eol(*line))
484 {
swissChiliabccdfc2021-01-08 21:39:12 -0800485 dbgf("skip_ws() brought us to EOL\n");
swissChili7acb4ce2020-08-16 20:16:10 -0700486 goto end_of_line;
487 }
swissChili97b5d8b2020-08-15 20:00:54 -0700488
swissChilia4f49b52020-08-16 17:35:37 -0700489 char *label = parse_label(&line);
swissChiliabccdfc2021-01-08 21:39:12 -0800490 dbgf(">> label == %.5s %p\n", label, label);
swissChili7acb4ce2020-08-16 20:16:10 -0700491 skip_ws(&code);
swissChilidab15a62020-08-17 15:41:27 -0700492 //if (is_eol(*line))
493 // goto end_of_line;
swissChilia4f49b52020-08-16 17:35:37 -0700494 char *mn = parse_inst(&line);
swissChilia4f49b52020-08-16 17:35:37 -0700495
496 bool no_argument = false;
swissChilia4f49b52020-08-16 17:35:37 -0700497 if (is_eol(*line))
498 {
499 no_argument = true;
swissChilia4f49b52020-08-16 17:35:37 -0700500 }
swissChili97b5d8b2020-08-15 20:00:54 -0700501 int32_t mnemonic = -1;
502
503 if (label)
504 {
swissChiliabccdfc2021-01-08 21:39:12 -0800505 dbgf("Storing label %s\n", label);
swissChilidab15a62020-08-17 15:41:27 -0700506 ll_node_t *head = malloc(sizeof(ll_node_t));
507 head->last = last_node;
508 strncpy(head->name, label, 32);
509 // strncpy won't zero the last byte if its over 32 bytes long
510 head->name[31] = 0;
511 head->addr = pc;
512 last_node = head;
swissChiliabccdfc2021-01-08 21:39:12 -0800513 dbgf("Set label %s at $%x\n", label, pc);
swissChili97b5d8b2020-08-15 20:00:54 -0700514 }
515
516 if (mn)
517 {
518#define MN(a) if (!strcasecmp(mn, #a)) \
swissChilica0d2e22020-08-16 15:09:25 -0700519 { \
swissChili97b5d8b2020-08-15 20:00:54 -0700520 mnemonic = a; \
swissChilica0d2e22020-08-16 15:09:25 -0700521 } \
swissChili97b5d8b2020-08-15 20:00:54 -0700522 else
523
swissChili7acb4ce2020-08-16 20:16:10 -0700524 MNEMONICS
525 {
swissChiliabccdfc2021-01-08 21:39:12 -0800526 dbgf(ERR "Could not parse instruction on line %d\n%s\n" RESET, line_no, orig_line);
swissChilidab15a62020-08-17 15:41:27 -0700527 free(line_start);
swissChili7acb4ce2020-08-16 20:16:10 -0700528 goto cleanup;
529 }
swissChili97b5d8b2020-08-15 20:00:54 -0700530#undef MN
531
swissChiliabccdfc2021-01-08 21:39:12 -0800532 dbgf("Got instruction %s %d\n", mn, mnemonic);
swissChili97b5d8b2020-08-15 20:00:54 -0700533
swissChilidab15a62020-08-17 15:41:27 -0700534 inst_t *arg = malloc(sizeof(inst_t));
535 arg->line = line_no;
swissChiliabccdfc2021-01-08 21:39:12 -0800536 // dbgf("Parsing '%s'\n", line);
swissChili97b5d8b2020-08-15 20:00:54 -0700537#define INST(_mn, am, op, len) \
swissChilia4f49b52020-08-16 17:35:37 -0700538 if ((no_argument && (_mn == AM_IMP || _mn == AM_ACC)) \
swissChilidab15a62020-08-17 15:41:27 -0700539 || (mnemonic == _mn && parse_arg(line, am, arg))) \
swissChilia4f49b52020-08-16 17:35:37 -0700540 { \
swissChiliabccdfc2021-01-08 21:39:12 -0800541 dbgf(GREEN "AM_ succeeded: %s at pc=$%x\n" RESET, \
swissChili6a923012020-08-18 17:47:27 -0700542 #am, pc); \
swissChilidab15a62020-08-17 15:41:27 -0700543 arg->opcode = op; \
swissChilia4f49b52020-08-16 17:35:37 -0700544 pc += len; \
swissChilidab15a62020-08-17 15:41:27 -0700545 print_inst(arg); \
swissChilia4f49b52020-08-16 17:35:37 -0700546 } \
swissChili97b5d8b2020-08-15 20:00:54 -0700547 else
548
549 INSTRUCTIONS
550 {
swissChiliabccdfc2021-01-08 21:39:12 -0800551 dbgf("\033[31mCould not be parsed: %s '%s'\033[0m\n", mn, line);
swissChilidab15a62020-08-17 15:41:27 -0700552 free(line_start);
553 goto cleanup;
swissChili97b5d8b2020-08-15 20:00:54 -0700554 }
555#undef INST
swissChilidab15a62020-08-17 15:41:27 -0700556
557 insts[num_insts++] = arg;
swissChili97b5d8b2020-08-15 20:00:54 -0700558 }
swissChili7acb4ce2020-08-16 20:16:10 -0700559 end_of_line:
560 line_no++;
swissChili7acb4ce2020-08-16 20:16:10 -0700561 orig_line = strtok_fix(NULL, "\n");
562 free(line_start);
swissChili97b5d8b2020-08-15 20:00:54 -0700563 }
564
swissChilidab15a62020-08-17 15:41:27 -0700565 // Generate machine code
566 for (int i = 0, curr_pc = 0x600; insts[i]; i++)
567 {
568 putc(insts[i]->opcode, out);
569
570 switch (insts[i]->arg_type)
571 {
572 case ARG_8:
573 putc(insts[i]->byte_arg, out);
574 curr_pc += 2;
575 break;
576 case ARG_16:
577 putshort(insts[i]->long_arg, out);
578 curr_pc += 3;
579 break;
580 case ARG_8REL:
581 putc(insts[i]->rel_arg, out);
582 curr_pc += 2;
583 break;
584 case ARG_ABS:
585 {
586 uint16_t lbl;
587 if (!(lbl = ll_find(last_node, insts[i]->label)))
588 {
swissChiliabccdfc2021-01-08 21:39:12 -0800589 dbgf(ERR "Error on line %d: label '%s' is not defined" RESET "\n",
swissChilic3829942020-09-06 19:36:04 -0700590 insts[i]->line, insts[i]->label);
swissChilidab15a62020-08-17 15:41:27 -0700591 goto cleanup;
592 }
593 curr_pc += 3;
594
595 putshort(lbl, out);
596 break;
597 }
598 case ARG_REL:
599 {
600 uint16_t lbl;
601 if (!(lbl = ll_find(last_node, insts[i]->label)))
602 {
swissChiliabccdfc2021-01-08 21:39:12 -0800603 dbgf(ERR "Error on line %d: label '%s' is not defined" RESET "\n",
swissChilic3829942020-09-06 19:36:04 -0700604 insts[i]->line, insts[i]->label);
swissChilidab15a62020-08-17 15:41:27 -0700605 goto cleanup;
606 }
607 curr_pc += 2;
608 int16_t diff = lbl - curr_pc;
swissChiliabccdfc2021-01-08 21:39:12 -0800609 dbgf("ARG_REL, pc (after) == %x, diff = %hx\n", curr_pc, (uint8_t) diff);
swissChilidab15a62020-08-17 15:41:27 -0700610 if ((diff < 0 ? -diff : diff) > 0xFF)
611 {
swissChiliabccdfc2021-01-08 21:39:12 -0800612 dbgf(ERR "Error on line %d: label '%s' is too far away for a relative jump" RESET "\n",
swissChilic3829942020-09-06 19:36:04 -0700613 insts[i]->line, insts[i]->label);
swissChiliabccdfc2021-01-08 21:39:12 -0800614 dbgf("pc == %hx, label is at %hx\n", curr_pc, lbl);
swissChilidab15a62020-08-17 15:41:27 -0700615 goto cleanup;
616 }
swissChili6a923012020-08-18 17:47:27 -0700617 putc((uint8_t) diff, out);
swissChilidab15a62020-08-17 15:41:27 -0700618 break;
619 }
620 default:
621 curr_pc++;
622 }
623 }
swissChili6a923012020-08-18 17:47:27 -0700624
swissChili7acb4ce2020-08-16 20:16:10 -0700625cleanup:
swissChiliabccdfc2021-01-08 21:39:12 -0800626 dbgf("-----\n");
627 dbgf("At end, there are %d instructions\n", num_insts);
swissChilidab15a62020-08-17 15:41:27 -0700628 while (last_node)
629 {
630 ll_node_t *curr_node = last_node;
631 last_node = curr_node->last;
632 free(curr_node);
633 }
634 for (int i = 0; insts[i]; i++)
635 free(insts[i]);
636 free(insts);
637 fflush(out);
swissChili97b5d8b2020-08-15 20:00:54 -0700638
639 return num_insts;
640}