Kestrel Interface
Loading...
Searching...
No Matches
kest_asm_parser.c
Go to the documentation of this file.
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4
5#include "kest_int.h"
6
7#ifndef PRINTLINES_ALLOWED
8#define PRINTLINES_ALLOWED 0
9#endif
10
11static const char *FNAME = "kest_asm_parser.c";
12
13#define CH_DELIMITER 'c'
14#define KEST_EXPR_DELIMITER "["
15#define RS_DELIMITER "$"
16#define DQ_CODELIMITER "]"
17
19
20static const char *instrs [] = {
21 "nop", "mov", "add", "sub", "mul",
22 "madd", "arsh", "lsh", "rsh", "abs",
23 "min", "max", "clamp", "mov_acc",
24 "macz", "umacz", "mac", "umac",
25 "delay_read", "delay_write", "delay_mwrite",
26 "mem_read", "mem_write", "filter",
27 "tanh4", "sin2pi"
28};
29
30static const int n_instrs = sizeof(instrs) / sizeof(instrs[0]);
31
32static const kest_arg_format arg_format_std_0 = {
33 .n_args = 0,
34
35 .arg_a_pos = KEST_ARG_POS_NONE,
36 .arg_b_pos = KEST_ARG_POS_NONE,
37 .arg_c_pos = KEST_ARG_POS_NONE,
38 .dest_pos = KEST_ARG_POS_NONE,
39 .shift_pos = KEST_ARG_POS_NONE
40};
41
42static const kest_arg_format arg_format_std_1 = {
43 .n_args = 2,
44
45 .arg_a_pos = 0,
46 .arg_b_pos = KEST_ARG_POS_NONE,
47 .arg_c_pos = KEST_ARG_POS_NONE,
48 .res_pos = KEST_ARG_POS_NONE,
49 .dest_pos = 1,
50 .shift_pos = KEST_ARG_POS_NONE
51};
52
53static const kest_arg_format arg_format_std_2 = {
54 .n_args = 3,
55
56 .arg_a_pos = 0,
57 .arg_b_pos = 1,
58 .arg_c_pos = KEST_ARG_POS_NONE,
59 .res_pos = KEST_ARG_POS_NONE,
60 .dest_pos = 2,
61 .shift_pos = KEST_ARG_POS_NONE
62};
63
64static const kest_arg_format arg_format_mac = {
65 .n_args = 2,
66
67 .arg_a_pos = 0,
68 .arg_b_pos = 1,
69 .arg_c_pos = KEST_ARG_POS_NONE,
70 .res_pos = KEST_ARG_POS_NONE,
71 .dest_pos = KEST_ARG_POS_NONE,
72 .shift_pos = KEST_ARG_POS_NONE
73};
74
75static const kest_arg_format arg_format_add = {
76 .n_args = 3,
77
78 .arg_a_pos = 0,
79 .arg_b_pos = KEST_ARG_POS_NONE,
80 .arg_c_pos = 1,
81 .res_pos = KEST_ARG_POS_NONE,
82 .dest_pos = 2,
83 .shift_pos = KEST_ARG_POS_NONE
84};
85
86static const kest_arg_format arg_format_std_3 = {
87 .n_args = 4,
88
89 .arg_a_pos = 0,
90 .arg_b_pos = 1,
91 .arg_c_pos = 2,
92 .res_pos = KEST_ARG_POS_NONE,
93 .dest_pos = 3,
94 .shift_pos = KEST_ARG_POS_NONE
95};
96
97static const kest_arg_format arg_format_shift = {
98 .n_args = 3,
99
100 .arg_a_pos = 0,
101 .arg_b_pos = 1,
102 .arg_c_pos = KEST_ARG_POS_NONE,
103 .res_pos = KEST_ARG_POS_NONE,
104 .dest_pos = 3,
105 .shift_pos = 2
106};
107
108static const kest_arg_format arg_format_read = {
109 .n_args = 1,
110
111 .arg_a_pos = KEST_ARG_POS_NONE,
112 .arg_b_pos = KEST_ARG_POS_NONE,
113 .arg_c_pos = KEST_ARG_POS_NONE,
114 .res_pos = KEST_ARG_POS_NONE,
115 .dest_pos = 0,
116 .shift_pos = KEST_ARG_POS_NONE
117};
118/*
119static const kest_arg_format arg_format_write = {
120 .n_args = 1,
121
122 .arg_a_pos = 0,
123 .arg_b_pos = KEST_ARG_POS_NONE,
124 .arg_c_pos = KEST_ARG_POS_NONE,
125 .res_pos = KEST_ARG_POS_NONE,
126 .dest_pos = KEST_ARG_POS_NONE,
127 .shift_pos = KEST_ARG_POS_NONE
128};
129*/
130static const kest_arg_format arg_format_res_read = {
131 .n_args = 2,
132
133 .arg_a_pos = KEST_ARG_POS_NONE,
134 .arg_b_pos = KEST_ARG_POS_NONE,
135 .arg_c_pos = KEST_ARG_POS_NONE,
136 .res_pos = 0,
137 .dest_pos = 1,
138 .shift_pos = KEST_ARG_POS_NONE
139};
140
141static const kest_arg_format arg_format_res_write = {
142 .n_args = 2,
143
144 .arg_a_pos = 0,
145 .arg_b_pos = KEST_ARG_POS_NONE,
146 .arg_c_pos = KEST_ARG_POS_NONE,
147 .res_pos = 1,
148 .dest_pos = KEST_ARG_POS_NONE,
149 .shift_pos = KEST_ARG_POS_NONE
150};
151
152static const kest_arg_format arg_format_res_write_2 = {
153 .n_args = 3,
154
155 .arg_a_pos = 0,
156 .arg_b_pos = 1,
157 .arg_c_pos = KEST_ARG_POS_NONE,
158 .res_pos = 2,
159 .dest_pos = KEST_ARG_POS_NONE,
160 .shift_pos = KEST_ARG_POS_NONE
161};
162
163static const kest_arg_format arg_format_res_rw = {
164 .n_args = 3,
165
166 .arg_a_pos = 0,
167 .arg_b_pos = KEST_ARG_POS_NONE,
168 .arg_c_pos = KEST_ARG_POS_NONE,
169 .res_pos = 1,
170 .dest_pos = 2,
171 .shift_pos = KEST_ARG_POS_NONE
172};
173
174const kest_arg_format *kest_instr_arg_format(const char *instr)
175{
176 if (!instr) return NULL;
177
178 if (strcmp(instr, "nop" ) == 0) return &arg_format_std_0;
179 if (strcmp(instr, "mov" ) == 0) return &arg_format_std_1;
180 if (strcmp(instr, "add" ) == 0) return &arg_format_add;
181 if (strcmp(instr, "sub" ) == 0) return &arg_format_std_2;
182 if (strcmp(instr, "mul" ) == 0) return &arg_format_std_2;
183 if (strcmp(instr, "madd" ) == 0) return &arg_format_std_3;
184 if (strcmp(instr, "arsh" ) == 0) return &arg_format_shift;
185 if (strcmp(instr, "lsh" ) == 0) return &arg_format_shift;
186 if (strcmp(instr, "rsh" ) == 0) return &arg_format_shift;
187 if (strcmp(instr, "abs" ) == 0) return &arg_format_std_1;
188 if (strcmp(instr, "min" ) == 0) return &arg_format_std_2;
189 if (strcmp(instr, "max" ) == 0) return &arg_format_std_2;
190 if (strcmp(instr, "clamp" ) == 0) return &arg_format_std_3;
191 if (strcmp(instr, "mov_acc" ) == 0) return &arg_format_read;
192 if (strcmp(instr, "macz" ) == 0) return &arg_format_mac;
193 if (strcmp(instr, "umacz" ) == 0) return &arg_format_mac;
194 if (strcmp(instr, "mac" ) == 0) return &arg_format_mac;
195 if (strcmp(instr, "umac" ) == 0) return &arg_format_mac;
196 if (strcmp(instr, "delay_read" ) == 0) return &arg_format_res_read;
197 if (strcmp(instr, "delay_write" ) == 0) return &arg_format_res_write;
198 if (strcmp(instr, "delay_mwrite") == 0) return &arg_format_res_write_2;
199 if (strcmp(instr, "mem_read" ) == 0) return &arg_format_res_read;
200 if (strcmp(instr, "mem_write" ) == 0) return &arg_format_res_write;
201 if (strcmp(instr, "filter" ) == 0) return &arg_format_res_rw;
202 if (strcmp(instr, "tanh4" ) == 0) return &arg_format_std_1;
203 if (strcmp(instr, "sin2pi" ) == 0) return &arg_format_std_1;
204
205 return NULL;
206}
207
208int kest_instr_opcode(const char *instr)
209{
210 if (!instr) return BLOCK_INSTR_NOP;
211
212 if (strcmp(instr, "nop" ) == 0) return BLOCK_INSTR_NOP;
213 if (strcmp(instr, "mov" ) == 0) return BLOCK_INSTR_MADD;
214 if (strcmp(instr, "add" ) == 0) return BLOCK_INSTR_MADD;
215 if (strcmp(instr, "sub" ) == 0) return BLOCK_INSTR_MADD;
216 if (strcmp(instr, "mul" ) == 0) return BLOCK_INSTR_MADD;
217 if (strcmp(instr, "madd" ) == 0) return BLOCK_INSTR_MADD;
218 if (strcmp(instr, "arsh" ) == 0) return BLOCK_INSTR_ARSH;
219 if (strcmp(instr, "lsh" ) == 0) return BLOCK_INSTR_LSH;
220 if (strcmp(instr, "rsh" ) == 0) return BLOCK_INSTR_RSH;
221 if (strcmp(instr, "abs" ) == 0) return BLOCK_INSTR_ABS;
222 if (strcmp(instr, "min" ) == 0) return BLOCK_INSTR_MIN;
223 if (strcmp(instr, "max" ) == 0) return BLOCK_INSTR_MAX;
224 if (strcmp(instr, "clamp" ) == 0) return BLOCK_INSTR_CLAMP;
225 if (strcmp(instr, "mov_acc" ) == 0) return BLOCK_INSTR_MOV_ACC;
226 if (strcmp(instr, "macz" ) == 0) return BLOCK_INSTR_MACZ;
227 if (strcmp(instr, "umacz" ) == 0) return BLOCK_INSTR_UMACZ;
228 if (strcmp(instr, "mac" ) == 0) return BLOCK_INSTR_MAC;
229 if (strcmp(instr, "umac" ) == 0) return BLOCK_INSTR_UMAC;
230 if (strcmp(instr, "delay_read" ) == 0) return BLOCK_INSTR_DELAY_READ;
231 if (strcmp(instr, "delay_write" ) == 0) return BLOCK_INSTR_DELAY_WRITE;
232 if (strcmp(instr, "delay_mwrite") == 0) return BLOCK_INSTR_DELAY_WRITE;
233 if (strcmp(instr, "mem_read" ) == 0) return BLOCK_INSTR_MEM_READ;
234 if (strcmp(instr, "mem_write" ) == 0) return BLOCK_INSTR_MEM_WRITE;
235 if (strcmp(instr, "filter" ) == 0) return BLOCK_INSTR_FILTER;
236 if (strcmp(instr, "tanh4" ) == 0) return BLOCK_INSTR_LUT_READ;
237 if (strcmp(instr, "sin2pi" ) == 0) return BLOCK_INSTR_LUT_READ;
238
239 return BLOCK_INSTR_NOP;
240}
241
243{
244 if (!ps)
245 return ERR_NULL_PTR;
246
247 kest_token_ll *current = ps->current_token;
248 kest_token_ll *tok;
249
250 kest_dsp_resource_pll *current_res;
251 int resource_found;
252
253 int ret_val = NO_ERROR;
254
255 int n;
256 int valid;
257
258 if (!current || !current->data)
259 {
260 ret_val = ERR_BAD_ARGS;
261 goto asm_parse_arg_fin;
262 }
263
264 if (current->data[0] == CH_DELIMITER)
265 {
266 if (arg) arg->type = KEST_ASM_ARG_CHANNEL;
267
268 valid = 1;
269 n = 0;
270 for (int i = 1; current->data[i] != 0; i++)
271 {
272 if (i > 2)
273 valid = 0;
274
275 if ('0' <= current->data[i] && current->data[i] <= '9')
276 {
277 n = 10 * n + current->data[i] - '0';
278 }
279 else if ('a' <= current->data[i] && current->data[i] <= 'f')
280 {
281 n = 16 * n + current->data[i] - 'a' + 10;
282 }
283 else if ('A' <= current->data[i] && current->data[i] <= 'F')
284 {
285 n = 16 * n + current->data[i] - 'A' + 10;
286 }
287 else
288 {
289 valid = 0;
290 }
291
292 if (!valid)
293 {
294 kest_parser_error_at(ps, current, "Invalid argument \"%s\"");
295 ret_val = ERR_BAD_ARGS;
296 goto asm_parse_arg_fin;
297 }
298 }
299
300 if (arg) arg->addr = n;
301 }
302 else if (strcmp(current->data, KEST_EXPR_DELIMITER) == 0)
303 {
304 if (arg) arg->type = KEST_ASM_ARG_EXPR;
305
306 tok = current;
307
308 do
309 {
310 tok = tok->next;
311
312 if (!tok || strcmp(tok->data, "\n") == 0)
313 {
314 kest_parser_error_at(ps, current, "Missing \"%s\"", DQ_CODELIMITER);
315 ret_val = ERR_BAD_ARGS;
316 goto asm_parse_arg_fin;
317 }
318
319 } while (strcmp(tok->data, DQ_CODELIMITER) != 0);
320
321 if (arg)
322 {
323 arg->expr = kest_parse_expression(ps, current->next, tok);
324 if (!arg->expr)
325 {
326 ret_val = ERR_BAD_ARGS;
327 goto asm_parse_arg_fin;
328 }
329 }
330
331 if (tok)
332 current = tok;
333 else
334 current = NULL;
335 }
336 else if (strcmp(current->data, RS_DELIMITER) == 0)
337 {
338 if (arg) arg->type = KEST_ASM_ARG_RES;
339
340 current = current->next;
341
342 if (!current || !current->data || strcmp(current->data, "\n") == 0)
343 {
344 kest_parser_error_at(ps, current, "Missing resource identifier");
345 ret_val = ERR_BAD_ARGS;
346 goto asm_parse_arg_fin;
347 }
348
349 current_res = ps->resources;
350
351 resource_found = 0;
352 while (current_res && !resource_found)
353 {
354 if (current_res->data && current_res->data->name)
355 {
356 if (strcmp(current->data, current_res->data->name) == 0)
357 {
358 resource_found = 1;
359 if (arg) arg->res = current_res->data;
360 }
361 }
362
363 current_res = current_res->next;
364 }
365
366 if (resource_found && arg)
367 {
368
369 }
370 else
371 {
372 kest_parser_error_at(ps, current, "Resource \"%s\" not found", current->data);
373 ret_val = ERR_BAD_ARGS;
374 goto asm_parse_arg_fin;
375 }
376 }
377 else if (token_is_int(current->data))
378 {
379 if (arg)
380 {
381 arg->type = KEST_ASM_ARG_INT;
382 arg->val = strtol(current->data, NULL, 10);
383 }
384 }
385 else
386 {
387 KEST_PRINTF("Syntax error: \"%s\"\n", current->data);
388 ret_val = ERR_BAD_ARGS;
389 goto asm_parse_arg_fin;
390 }
391
392asm_parse_arg_fin:
393
394 if (current)
395 current = current->next;
396
397 ps->current_token = current;
398
399 return ret_val;
400}
401
403{
404 if (!ps)
405 return ERR_NULL_PTR;
406
407 kest_token_ll *current = ps->current_token;
408 kest_token_ll *tok;
409
410 kest_expression *expr;
411
412 kest_dsp_resource_pll *current_res;
413 int resource_found;
414 int line;
415
416 int ret_val = NO_ERROR;
417
418 int n;
419 int valid;
420
421 if (!current || !current->data)
422 {
423 ret_val = ERR_BAD_ARGS;
424 goto asm_parse_arg_fin;
425 }
426
427 if (current->data[0] == CH_DELIMITER)
428 {
429 if (arg) arg->type = KEST_ASM_ARG_CHANNEL;
430
431 valid = 1;
432 n = 0;
433 for (int i = 1; current->data[i] != 0; i++)
434 {
435 if (i > 2)
436 valid = 0;
437
438 if ('0' <= current->data[i] && current->data[i] <= '9')
439 {
440 n = 10 * n + current->data[i] - '0';
441 }
442 else if ('a' <= current->data[i] && current->data[i] <= 'f')
443 {
444 n = 16 * n + current->data[i] - 'a' + 10;
445 }
446 else if ('A' <= current->data[i] && current->data[i] <= 'F')
447 {
448 n = 16 * n + current->data[i] - 'A' + 10;
449 }
450 else
451 {
452 valid = 0;
453 }
454
455 if (!valid)
456 {
457 kest_parser_error_at(ps, current, "Invalid argument \"%s\"");
458 ret_val = ERR_BAD_ARGS;
459 goto asm_parse_arg_fin;
460 }
461 }
462
463 if (arg)
464 {
466 }
467 }
468 else if (strcmp(current->data, KEST_EXPR_DELIMITER) == 0)
469 {
470 if (arg) arg->type = KEST_ASM_ARG_EXPR;
471
472 tok = current;
473
474 do
475 {
476 tok = tok->next;
477
478 if (!tok || strcmp(tok->data, "\n") == 0)
479 {
480 kest_parser_error_at(ps, current, "Missing \"%s\"", DQ_CODELIMITER);
481 ret_val = ERR_BAD_ARGS;
482 goto asm_parse_arg_fin;
483 }
484
485 } while (strcmp(tok->data, DQ_CODELIMITER) != 0);
486
487 if (arg)
488 {
489 arg->expr = kest_parse_expression(ps, current->next, tok);
490 if (!arg->expr)
491 {
492 ret_val = ERR_BAD_ARGS;
493 goto asm_parse_arg_fin;
494 }
495 }
496
497 if (tok)
498 current = tok;
499 else
500 current = NULL;
501 }
502 else if (strcmp(current->data, RS_DELIMITER) == 0)
503 {
504 if (arg) arg->type = KEST_ASM_ARG_RES;
505
506 current = current->next;
507
508 if (!current || !current->data || strcmp(current->data, "\n") == 0)
509 {
510 kest_parser_error_at(ps, current, "Missing resource identifier");
511 ret_val = ERR_BAD_ARGS;
512 goto asm_parse_arg_fin;
513 }
514
515 expr = new_m_expression_reference(current->data);
516 if (arg)
517 {
518 arg->expr = expr;
519 }
520 }
521 else if (token_is_int(current->data))
522 {
523 if (arg)
524 {
525 arg->type = KEST_ASM_ARG_INT;
527 }
528 }
529 else
530 {
531 KEST_PRINTF("Syntax error: \"%s\"\n", current->data);
532 ret_val = ERR_BAD_ARGS;
533 goto asm_parse_arg_fin;
534 }
535
536asm_parse_arg_fin:
537
538 if (current)
539 current = current->next;
540
541 ps->current_token = current;
542
543 return ret_val;
544}
545
546int is_valid_instr(const char *instr)
547{
548 if (!instr)
549 return 0;
550
551 for (int i = 0; i < n_instrs; i++)
552 if (strcmp(instrs[i], instr) == 0) return 1;
553
554 return 0;
555}
556
558{
559 if (!ps)
560 return ERR_NULL_PTR;
561
562 kest_token_ll *current = ps->current_token;
563
564 if (!current)
565 return ERR_BAD_ARGS;
566
567 if (!current->data)
568 return ERR_BAD_ARGS;
569
570 kest_block *block = kest_alloc(sizeof(kest_block));
571
572 if (!block)
573 return ERR_ALLOC_FAIL;
574
575 memset(block, 0, sizeof(kest_block));
576
577 int line_number = current->line;
578
579 KEST_PRINTF("Parsing asm line, line %d: \"%s\"\n", line_number, ps->lines[line_number - 1]);
580
581 int ret_val = NO_ERROR;
582
583 const char *instr_char = current->data;
584
585 kest_asm_line *line = NULL;
587
588 int args_cont = 1;
589 int line_fin = 0;
590 int n_args_read = 0;
591 int arg_ret_val;
592
593 if (!is_valid_instr(current->data))
594 {
595 kest_parser_error_at(ps, current, "Unknown instruction \"%s\"", current->data);
596 ret_val = ERR_BAD_ARGS;
597 goto asm_line_parse_fin;
598 }
599
600 line = kest_parser_alloc(sizeof(kest_asm_line));
601
602 if (!line)
603 {
604 kest_parser_error_at(ps, current, "Allocation failed", current->data);
605 ret_val = ERR_ALLOC_FAIL;
606 goto asm_line_parse_fin;
607 }
608
609 line->line_number = line_number;
610 line->n_args = 0;
611 line->instr = kest_parser_strndup(current->data, 12);
612
613 if (!line->instr)
614 {
615 kest_parser_error_at(ps, current, "Allocation failed", current->data);
616 ret_val = ERR_ALLOC_FAIL;
617 goto asm_line_parse_fin;
618 }
619
620 current = current->next;
621 ps->current_token = current;
622
623 for (int i = 0; ; i++)
624 {
625 if (!current || !current->data || current->data[0] == '\n' || current->line != line_number)
626 {
627 KEST_PRINTF("Breaking argument loop; reason:\n");
628 if (!current)
629 KEST_PRINTF("current = NULL");
630 if (!current->data)
631 KEST_PRINTF("current->data = NULL");
632 if (current->data[0] == '\n')
633 KEST_PRINTF("current token is newline token\n");
634 if (current->line != line_number)
635 KEST_PRINTF("current token is on line %d, instead of %d\n", current->line, line_number);
636 break;
637 }
638
639 if ((arg_ret_val = kest_parse_asm_arg_2(ps, (i < INSTR_MAX_ARGS) ? &line->args[i] : NULL)) != NO_ERROR)
640 {
641 current = ps->current_token;
642 ret_val = arg_ret_val;
643 goto asm_line_parse_fin;
644 }
645
646 if (i < INSTR_MAX_ARGS)
647 {
648 KEST_PRINTF("Parsed an argument: ");
649 switch (line->args[i].type)
650 {
652 KEST_PRINTF("channel c%s\n", kest_expression_to_string(line->args[i].expr));
653 break;
654
656 KEST_PRINTF("expression [%s]\n", kest_expression_to_string(line->args[i].expr));
657 break;
658
659 case KEST_ASM_ARG_RES:
660 KEST_PRINTF("resource $%s\n", kest_expression_to_string(line->args[i].expr));
661 break;
662
663 case KEST_ASM_ARG_INT:
664 KEST_PRINTF("integer: %s\n", kest_expression_to_string(line->args[i].expr));
665 break;
666 }
667 }
668
669 line->n_args++;
670 n_args_read++;
671
672 current = ps->current_token;
673 }
674
675 KEST_PRINTF("Line has %d args\n", line->n_args);
676
677 kest_asm_line_pll_safe_append(&ps->asm_lines, line);
678
679#if 0
680 if (strcmp(current->data, "nop") == 0)
681 {
682 block->instr = BLOCK_INSTR_NOP;
683
684 dest_pos = -1;
685 arg_a_pos = -1;
686 arg_b_pos = -1;
687
688 n_args_expected = 0;
689 }
690 else if (strcmp(current->data, "mov") == 0)
691 {
692 block->instr = BLOCK_INSTR_MADD;
693 block->arg_b = operand_const_one();
694 block->arg_c = operand_const_zero();
695 block->shift = 1;
696
697 arg_b_pos = -1;
698
699 n_args_expected = 2;
700 }
701 else if (strcmp(current->data, "add") == 0)
702 {
703 block->instr = BLOCK_INSTR_MADD;
704 block->arg_b = operand_const_one();
705 block->shift = 1;
706
707 arg_b_pos = -1;
708 arg_c_pos = 2;
709 }
710 else if (strcmp(current->data, "sub") == 0)
711 {
712 block->instr = BLOCK_INSTR_MADD;
714
715 arg_b_pos = -1;
716 arg_c_pos = 2;
717 }
718 else if (strcmp(current->data, "mul") == 0)
719 {
720 block->instr = BLOCK_INSTR_MADD;
721
722 block->arg_c = operand_const_zero();
723 block->shift = 0;
724
725 arg_b_pos = 2;
726 }
727 else if (strcmp(current->data, "madd") == 0)
728 {
729 block->instr = BLOCK_INSTR_MADD;
730
731 arg_c_pos = 3;
732
733 n_args_expected = 4;
734 }
735 else if (strcmp(current->data, "arsh") == 0)
736 {
737 block->instr = BLOCK_INSTR_MADD;
738 block->arg_b = operand_const_one();
739 block->shift = 1;
740 shift_mode = 0;
741
742 arg_b_pos = -1;
743 shift_pos = 2;
744 }
745 else if (strcmp(current->data, "lsh") == 0)
746 {
747 block->instr = BLOCK_INSTR_LSH;
748 shift_mode = 0;
749
750 arg_b_pos = -1;
751 shift_pos = 2;
752 }
753 else if (strcmp(current->data, "rsh") == 0)
754 {
755 block->instr = BLOCK_INSTR_RSH;
756 shift_mode = 0;
757
758 arg_b_pos = -1;
759 shift_pos = 2;
760 }
761 else if (strcmp(current->data, "abs") == 0)
762 {
763 block->instr = BLOCK_INSTR_RSH;
764
765 arg_b_pos = -1;
766 n_args_expected = 2;
767 }
768 else if (strcmp(current->data, "min") == 0)
769 {
770 block->instr = BLOCK_INSTR_MIN;
771 }
772 else if (strcmp(current->data, "max") == 0)
773 {
774 block->instr = BLOCK_INSTR_MAX;
775 }
776 else if (strcmp(current->data, "clamp") == 0)
777 {
778 block->instr = BLOCK_INSTR_CLAMP;
779
780 arg_c_pos = 3;
781
782 n_args_expected = 4;
783 }
784 else if (strcmp(current->data, "mov_acc") == 0)
785 {
786 block->instr = BLOCK_INSTR_MOV_ACC;
787
788 arg_a_pos = -1;
789 arg_b_pos = -1;
790
791 n_args_expected = 1;
792 }
793 else if (strcmp(current->data, "mov_lacc") == 0)
794 {
796
797 arg_a_pos = -1;
798 arg_b_pos = -1;
799
800 n_args_expected = 1;
801 }
802 else if (strcmp(current->data, "mov_uacc") == 0)
803 {
805
806 arg_a_pos = -1;
807 arg_b_pos = -1;
808
809 n_args_expected = 1;
810 }
811 else if (strcmp(current->data, "macz") == 0)
812 {
813 block->instr = BLOCK_INSTR_MACZ;
814 n_args_expected = 2;
815
816 arg_a_pos = 0;
817 arg_b_pos = 1;
818 dest_pos = -1;
819 }
820 else if (strcmp(current->data, "macz_noshift") == 0)
821 {
822 block->instr = BLOCK_INSTR_MACZ;
823
824 block->shift = 15;
825 n_args_expected = 2;
826 dest_pos = -1;
827 }
828 else if (strcmp(current->data, "umacz") == 0)
829 {
830 block->instr = BLOCK_INSTR_UMACZ;
831
832 arg_a_pos = 0;
833 arg_b_pos = 1;
834 dest_pos = -1;
835
836 n_args_expected = 2;
837 }
838 else if (strcmp(current->data, "umacz_noshift") == 0)
839 {
840 block->instr = BLOCK_INSTR_UMACZ;
841
842 block->shift = 15;
843 n_args_expected = 2;
844
845 arg_a_pos = 0;
846 arg_b_pos = 1;
847 dest_pos = -1;
848 }
849 else if (strcmp(current->data, "macz_unsat") == 0)
850 {
851 block->instr = BLOCK_INSTR_MACZ;
852 block->saturate_disable = 1;
853 n_args_expected = 2;
854
855 arg_a_pos = 0;
856 arg_b_pos = 1;
857 dest_pos = -1;
858 }
859 else if (strcmp(current->data, "macz_unsat_noshift") == 0)
860 {
861 block->instr = BLOCK_INSTR_MACZ;
862 block->saturate_disable = 1;
863 n_args_expected = 2;
864
865 block->shift = 15;
866
867 arg_a_pos = 0;
868 arg_b_pos = 1;
869 dest_pos = -1;
870 }
871 else if (strcmp(current->data, "umacz_unsat") == 0)
872 {
873 block->instr = BLOCK_INSTR_UMACZ;
874 block->saturate_disable = 1;
875 n_args_expected = 2;
876
877 arg_a_pos = 0;
878 arg_b_pos = 1;
879 dest_pos = -1;
880 }
881 else if (strcmp(current->data, "umacz_unsat_noshift") == 0)
882 {
883 block->instr = BLOCK_INSTR_UMACZ;
884 block->saturate_disable = 1;
885 n_args_expected = 2;
886
887 block->shift = 15;
888
889 arg_a_pos = 0;
890 arg_b_pos = 1;
891 dest_pos = -1;
892 }
893 else if (strcmp(current->data, "mac") == 0)
894 {
895 block->instr = BLOCK_INSTR_MAC;
896 n_args_expected = 2;
897
898 arg_a_pos = 0;
899 arg_b_pos = 1;
900 dest_pos = -1;
901 }
902 else if (strcmp(current->data, "mac_noshift") == 0)
903 {
904 block->instr = BLOCK_INSTR_MAC;
905
906 n_args_expected = 2;
907 block->shift = 15;
908
909 arg_a_pos = 0;
910 arg_b_pos = 1;
911 dest_pos = -1;
912 }
913 else if (strcmp(current->data, "umac") == 0)
914 {
915 block->instr = BLOCK_INSTR_UMAC;
916 n_args_expected = 2;
917
918 arg_a_pos = 0;
919 arg_b_pos = 1;
920 dest_pos = -1;
921 }
922 else if (strcmp(current->data, "umac_noshift") == 0)
923 {
924 block->instr = BLOCK_INSTR_UMAC;
925 n_args_expected = 2;
926
927 block->shift = 15;
928
929 arg_a_pos = 0;
930 arg_b_pos = 1;
931 dest_pos = -1;
932 }
933 else if (strcmp(current->data, "mac_unsat") == 0)
934 {
935 block->instr = BLOCK_INSTR_MAC;
936 n_args_expected = 2;
937 block->saturate_disable = 1;
938
939 arg_a_pos = 0;
940 arg_b_pos = 1;
941 dest_pos = -1;
942 }
943 else if (strcmp(current->data, "mac_unsat_noshift") == 0)
944 {
945 block->instr = BLOCK_INSTR_MAC;
946 n_args_expected = 2;
947 block->saturate_disable = 1;
948
949 block->shift = 15;
950
951 arg_a_pos = 0;
952 arg_b_pos = 1;
953 dest_pos = -1;
954 }
955 else if (strcmp(current->data, "umac_unsat") == 0)
956 {
957 block->instr = BLOCK_INSTR_UMAC;
958 block->saturate_disable = 1;
959 n_args_expected = 2;
960
961 arg_a_pos = 0;
962 arg_b_pos = 1;
963 dest_pos = -1;
964 }
965 else if (strcmp(current->data, "umac_unsat_noshift") == 0)
966 {
967 block->instr = BLOCK_INSTR_UMAC;
968 block->saturate_disable = 1;
969 n_args_expected = 2;
970
971 block->shift = 15;
972
973 arg_a_pos = 0;
974 arg_b_pos = 1;
975 dest_pos = -1;
976 }
977 else if (strcmp(current->data, "delay_read") == 0)
978 {
980
981 arg_a_pos = -1;
982 arg_b_pos = -1;
983 res_pos = 1;
984
985 n_args_expected = 2;
986 }
987 else if (strcmp(current->data, "delay_write") == 0)
988 {
990
991 arg_a_pos = 1;
992 arg_b_pos = -1;
993 dest_pos = -1;
994 res_pos = 0;
995
998
999 n_args_expected = 2;
1000 }
1001 else if (strcmp(current->data, "delay_mwrite") == 0)
1002 {
1004
1005 res_pos = 0;
1006 dest_pos = -1;
1007
1008 n_args_expected = 3;
1009 }
1010 else if (strcmp(current->data, "mem_read") == 0)
1011 {
1012 block->instr = BLOCK_INSTR_MEM_READ;
1013
1014 arg_a_pos = -1;
1015 arg_b_pos = -1;
1016 res_pos = 1;
1017
1018 n_args_expected = 2;
1019 }
1020 else if (strcmp(current->data, "mem_write") == 0)
1021 {
1023
1024 dest_pos = -1;
1025 arg_b_pos = -1;
1026 res_pos = 0;
1027
1028 n_args_expected = 2;
1029 }
1030 else
1031 {
1032 KEST_PRINTF("Error: unknown instruction \"%s\"\n", current->data);
1033 ret_val = ERR_BAD_ARGS;
1034 goto asm_line_parse_fin;
1035 }
1036
1037 if (shift_mode)
1038 {
1039 n_args_expected++;
1040 shift_pos = dest_pos;
1041
1042 if (arg_a_pos > shift_pos)
1043 shift_pos = arg_a_pos;
1044 if (arg_b_pos > shift_pos)
1045 shift_pos = arg_b_pos;
1046 if (arg_c_pos > shift_pos)
1047 shift_pos = arg_c_pos;
1048 if (arg_c_pos > res_pos)
1049 shift_pos = arg_c_pos;
1050
1051 shift_pos++;
1052 }
1053
1054 current = current->next;
1055
1056 ps->current_token = current;
1057
1058 for (int i = 0; ; i++)
1059 {
1060 if (!current || !current->data || current->data[0] == '\n')
1061 break;
1062
1063 if ((arg_ret_val = kest_parse_asm_arg(ps, (i < INSTR_MAX_ARGS) ? &args[i] : NULL)) != NO_ERROR)
1064 {
1065 current = ps->current_token;
1066 ret_val = arg_ret_val;
1067 goto asm_line_parse_fin;
1068 }
1069
1070 n_args_read++;
1071
1072 current = ps->current_token;
1073 }
1074
1075 if (n_args_read < n_args_expected)
1076 {
1077 KEST_PRINTF("Error: too few arguments for instruction \"%s\" (expected %d, given %d)\n", instr_char, n_args_expected, n_args_read);
1078 ret_val = ERR_BAD_ARGS;
1079 goto asm_line_parse_fin;
1080 }
1081 else if (n_args_read > n_args_expected)
1082 {
1083 KEST_PRINTF("Error: too many arguments for instruction \"%s\" (expected %d, given %d)\n", instr_char, n_args_expected, n_args_read);
1084 ret_val = ERR_BAD_ARGS;
1085 goto asm_line_parse_fin;
1086 }
1087
1088 if (dest_pos != -1)
1089 {
1090 if (args[dest_pos].type != KEST_ASM_ARG_CHANNEL)
1091 {
1092 KEST_PRINTF("Error: destination must be a channel\n");
1093 ret_val = ERR_BAD_ARGS;
1094 goto asm_line_parse_fin;
1095 }
1096 else
1097 {
1098 block->dest = args[dest_pos].addr;
1099 }
1100 }
1101
1102 if (shift_pos != -1)
1103 {
1104 if (args[shift_pos].type != KEST_ASM_ARG_INT || args[shift_pos].val < 0 || args[shift_pos].val > 15)
1105 {
1106 KEST_PRINTF("Error: shift value must be an integer between 0 and 15\n");
1107 ret_val = ERR_BAD_ARGS;
1108 goto asm_line_parse_fin;
1109 }
1110 else
1111 {
1112 block->shift = args[shift_pos].val;
1113 }
1114 }
1115
1116 if (arg_a_pos != -1)
1117 {
1118 switch (args[arg_a_pos].type)
1119 {
1122 block->arg_a.addr = args[arg_a_pos].addr;
1123 break;
1124
1125 case KEST_ASM_ARG_EXPR:
1127 block->arg_a.addr = 0;
1128 reg_0_taken = 1;
1129
1130 block->reg_0.expr = args[arg_a_pos].expr;
1131 block->reg_0.active = 1;
1132 break;
1133
1134 default:
1135 KEST_PRINTF("Error: wrong type given for arg a\n");
1136 break;
1137 }
1138 }
1139
1140 if (arg_b_pos != -1)
1141 {
1142 switch (args[arg_b_pos].type)
1143 {
1146 block->arg_b.addr = args[arg_b_pos].addr;
1147 break;
1148
1149 case KEST_ASM_ARG_EXPR:
1151
1152 if (!reg_0_taken)
1153 {
1154 block->arg_b.addr = 0;
1155 reg_0_taken = 1;
1156
1157 block->reg_0.expr = args[arg_b_pos].expr;
1158 block->reg_0.active = 1;
1159 }
1160 else
1161 {
1162 block->arg_b.addr = 1;
1163 reg_1_taken = 1;
1164
1165 block->reg_1.expr = args[arg_b_pos].expr;
1166 block->reg_1.active = 1;
1167 }
1168 break;
1169
1170 default:
1171 KEST_PRINTF("Error: wrong type given for arg b\n");
1172 ret_val = ERR_BAD_ARGS;
1173 goto asm_line_parse_fin;
1174 break;
1175 }
1176 }
1177
1178 if (arg_c_pos != -1)
1179 {
1180 switch (args[arg_c_pos].type)
1181 {
1184 block->arg_c.addr = args[arg_c_pos].addr;
1185 break;
1186
1187 case KEST_ASM_ARG_EXPR:
1189 if (!reg_0_taken)
1190 {
1191 block->arg_c.addr = 0;
1192 reg_0_taken = 1;
1193
1194 block->reg_0.expr = args[arg_c_pos].expr;
1195 block->reg_0.active = 1;
1196 }
1197 else if (!reg_1_taken)
1198 {
1199 block->arg_c.addr = 1;
1200 reg_1_taken = 1;
1201
1202 block->reg_1.expr = args[arg_c_pos].expr;
1203 block->reg_1.active = 1;
1204 }
1205 else
1206 {
1207 KEST_PRINTF("Error: too many constants\n");
1208 ret_val = ERR_BAD_ARGS;
1209 goto asm_line_parse_fin;
1210 }
1211 break;
1212
1213 default:
1214 KEST_PRINTF("Error: wrong type given for arg c\n");
1215 ret_val = ERR_BAD_ARGS;
1216 goto asm_line_parse_fin;
1217 break;
1218 }
1219 }
1220
1221 if (res_pos != -1)
1222 {
1223 if (args[res_pos].type != KEST_ASM_ARG_RES)
1224 {
1225 KEST_PRINTF("Error: resource must be a resource\n");
1226 ret_val = ERR_BAD_ARGS;
1227 goto asm_line_parse_fin;
1228 }
1229 else
1230 {
1231 block->res = args[res_pos].res;
1232 }
1233 }
1234
1235 block->shift_set = shift_mode;
1236
1237 kest_block_pll_safe_append(&ps->blocks, block);
1238
1239#endif
1240
1241asm_line_parse_fin:
1242
1243 ps->current_token = current;
1244
1245 return ret_val;
1246}
1247
1249{
1250 if (!ps)
1251 return ERR_NULL_PTR;
1252
1253 kest_token_ll *current = ps->current_token;
1254
1255 int line_start;
1256 int comment;
1257 int ret_val = NO_ERROR;
1258
1259 kest_token_ll_skip_ws(&current);
1260 while (current)
1261 {
1262 // Advance to the next non-whitespace token
1263 ps->current_token = current;
1264 ret_val = kest_parse_asm_line(ps);
1265
1266 if (ret_val != NO_ERROR)
1267 {
1268 KEST_PRINTF("ASM parsing failed: %s\n", kest_error_code_to_string(ret_val));
1269 return ret_val;
1270 }
1271
1272 current = ps->current_token;
1273 kest_token_ll_skip_ws(&current);
1274 }
1275
1276 return NO_ERROR;
1277}
1278
1279kest_dsp_resource *kest_resource_get_by_name(kest_dsp_resource_pll *resources, const char *name)
1280{
1281 if (!resources || !name)
1282 return NULL;
1283
1284 kest_dsp_resource_pll *current = resources;
1285
1286 while (current)
1287 {
1288 if (current->data && current->data->name && strcmp(current->data->name, name) == 0)
1289 return current->data;
1290
1291 current = current->next;
1292 }
1293
1294 return NULL;
1295}
1296
1298{
1299 if (!ps || !line)
1300 return ERR_NULL_PTR;
1301
1302 int ret_val = NO_ERROR;
1303 int line_number = line->line_number;
1304
1305 kest_block *block = NULL;
1306 const kest_arg_format *arg_format = kest_instr_arg_format(line->instr);
1307
1308 kest_dsp_resource *resource;
1309
1310 if (!arg_format)
1311 return ERR_BAD_ARGS;
1312
1313 if (line->n_args != arg_format->n_args)
1314 {
1315 kest_parser_error_at_line(ps, line_number,
1316 "Instruction \"%s\" expects %d arguments, but %d were given.", line->instr, arg_format->n_args, line->n_args);
1317 return ERR_BAD_ARGS;
1318 }
1319
1320 block = kest_alloc(sizeof(kest_block));
1321
1322 if (!block)
1323 return ERR_ALLOC_FAIL;
1324
1325 memset(block, 0, sizeof(kest_block));
1326
1327 block->instr = kest_instr_opcode(line->instr);
1328
1329 kest_asm_arg arg;
1330 kest_block_operand *op = NULL;
1331
1332 int reg_0_taken = 0;
1333
1334 for (int i = 0; i < line->n_args; i++)
1335 {
1336 arg = line->args[i];
1337
1338 if (i == arg_format->dest_pos)
1339 {
1340 if (arg.type != KEST_ASM_ARG_CHANNEL)
1341 {
1342 kest_parser_error_at_line(ps, line_number, "Destination must be a channel");
1343 return ERR_BAD_ARGS;
1344 }
1345
1346 block->dest = (int)roundf(kest_expression_evaluate(line->args[i].expr, NULL));
1347 }
1348 else if (i == arg_format->res_pos)
1349 {
1350 if (arg.type != KEST_ASM_ARG_RES)
1351 {
1352 kest_parser_error_at_line(ps, line_number, "Argument %d of instruction \"%s\" must be a resource", i + 1, line->instr);
1353 return ERR_BAD_ARGS;
1354 }
1355
1356 if (!arg.expr)
1357 {
1358 return ERR_UNKNOWN_ERR;
1359 }
1360
1361 if (arg.expr->type != KEST_EXPR_REF)
1362 {
1363 // tbh....
1364 return ERR_UNKNOWN_ERR;
1365 }
1366
1367 if (!arg.expr->val.ref_name)
1368 {
1369 kest_parser_error_at_line(ps, line_number, "Resource has no name!");
1370 return ERR_UNKNOWN_ERR;
1371 }
1372
1373 resource = kest_resource_get_by_name(ps->resources, arg.expr->val.ref_name);
1374
1375 if (!resource)
1376 {
1377 kest_parser_error_at_line(ps, line_number, "Could not find resource \"%s\"", arg.expr->val.ref_name);
1378 return ERR_BAD_ARGS;
1379 }
1380
1381 block->res = resource;
1382 }
1383 else if (i == arg_format->shift_pos)
1384 {
1385 if (arg.type != KEST_ASM_ARG_INT)
1386 {
1387 kest_parser_error_at_line(ps, line_number, "Argument %d of instruction \"%s\" must be an integer", i + 1, line->instr);
1388 return ERR_BAD_ARGS;
1389 }
1390
1391 if (!arg.expr)
1392 {
1393 return ERR_UNKNOWN_ERR;
1394 }
1395
1396 if (arg.expr->type != KEST_EXPR_CONST)
1397 {
1398 // tbh....
1399 return ERR_UNKNOWN_ERR;
1400 }
1401
1402 block->shift = (int)roundf(kest_expression_evaluate(arg.expr, NULL));
1403 }
1404 else
1405 {
1406 if (i == arg_format->arg_a_pos)
1407 op = &block->arg_a;
1408 else if (i == arg_format->arg_b_pos)
1409 op = &block->arg_b;
1410 else if (i == arg_format->arg_c_pos)
1411 op = &block->arg_c;
1412
1413 if (!op)
1414 {
1415 kest_parser_error_at_line(ps, line_number, "Argument %d of instruction \"%s\" does not correspond to anything (this is a bug!!)", i + 1, line->instr);
1416 return ERR_UNKNOWN_ERR;
1417 }
1418
1419 switch (arg.type)
1420 {
1423 op->addr = (int)roundf(kest_expression_evaluate(arg.expr, NULL));
1424 break;
1425
1426 case KEST_ASM_ARG_EXPR:
1428
1429 if (!reg_0_taken)
1430 {
1431 block->reg_0.active = 1;
1432 block->reg_0.expr = arg.expr;
1433 reg_0_taken = 1;
1434
1435 op->addr = 0;
1436 }
1437 else
1438 {
1439 block->reg_1.active = 1;
1440 block->reg_1.expr = arg.expr;
1441
1442 op->addr = 1;
1443 }
1444
1445 break;
1446
1447 default:
1448 kest_parser_error_at_line(ps, line_number, "Argument %d of instruction \"%s\" must be either a channel or an expression", i + 1, line->instr);
1449 return ERR_BAD_ARGS;
1450 }
1451 }
1452 }
1453
1454 /* ... and some special considerations for unusual instructions */
1455
1456 if (strcmp(line->instr, "mov") == 0)
1457 {
1458 block->arg_b = operand_const_one();
1459 block->arg_c = operand_const_zero();
1460 }
1461 else if (strcmp(line->instr, "add") == 0)
1462 {
1463 block->arg_b = operand_const_one();
1464 }
1465 else if (strcmp(line->instr, "sub") == 0)
1466 {
1467 block->arg_b = operand_const_minus_one();
1468 }
1469 else if (strcmp(line->instr, "mul") == 0)
1470 {
1471 block->arg_c = operand_const_zero();
1472 }
1473 else if (strcmp(line->instr, "delay_write") == 0)
1474 {
1475 block->arg_c = operand_const_zero();
1476 }
1477 else if (strcmp(line->instr, "sin2pi") == 0)
1478 {
1479 block->res = &sin_lut;
1480 }
1481 else if (strcmp(line->instr, "tanh4") == 0)
1482 {
1483 block->res = &tanh_lut;
1484 }
1485
1486 kest_block_pll_safe_append(&ps->blocks, block);
1487
1488 return ret_val;
1489}
1490
1492{
1493 KEST_PRINTF("kest_process_asm_lines\n");
1494 if (!ps)
1495 return ERR_NULL_PTR;
1496
1497 int ret_val = NO_ERROR;
1498
1499 kest_asm_line_pll *current = ps->asm_lines;
1500
1501 int i = 0;
1502 while (current)
1503 {
1504 KEST_PRINTF("kest_process_asm_lines, line %d\n", i);
1505 kest_process_asm_line(ps, current->data);
1506 current = current->next; i++;
1507 }
1508
1509 return ret_val;
1510}
void * kest_alloc(size_t size)
Definition kest_alloc.c:11
kest_dsp_resource * kest_resource_get_by_name(kest_dsp_resource_pll *resources, const char *name)
int kest_parse_asm(kest_eff_parsing_state *ps)
int kest_process_asm_line(kest_eff_parsing_state *ps, kest_asm_line *line)
const kest_arg_format * kest_instr_arg_format(const char *instr)
#define RS_DELIMITER
int kest_instr_opcode(const char *instr)
#define CH_DELIMITER
#define KEST_EXPR_DELIMITER
int kest_parse_asm_line(kest_eff_parsing_state *ps)
int kest_parse_asm_arg_2(kest_eff_parsing_state *ps, kest_asm_arg *arg)
int kest_parse_asm_arg(kest_eff_parsing_state *ps, kest_asm_operand *arg)
#define DQ_CODELIMITER
int is_valid_instr(const char *instr)
int kest_process_asm_lines(kest_eff_parsing_state *ps)
#define INSTR_MAX_ARGS
#define KEST_ASM_ARG_INT
#define KEST_ASM_ARG_RES
#define KEST_ASM_ARG_EXPR
#define KEST_ASM_ARG_CHANNEL
#define KEST_ARG_POS_NONE
kest_block_operand operand_const_one()
Definition kest_block.c:21
kest_block_operand operand_const_minus_one()
Definition kest_block.c:29
kest_block_operand operand_const_zero()
Definition kest_block.c:13
#define BLOCK_INSTR_MEM_WRITE
Definition kest_block.h:24
#define BLOCK_INSTR_MAC
Definition kest_block.h:18
#define BLOCK_INSTR_DELAY_WRITE
Definition kest_block.h:22
#define BLOCK_OPERAND_TYPE_C
Definition kest_block.h:29
#define BLOCK_INSTR_UMACZ
Definition kest_block.h:17
#define BLOCK_OPERAND_TYPE_R
Definition kest_block.h:30
#define BLOCK_INSTR_DELAY_READ
Definition kest_block.h:21
#define BLOCK_INSTR_MOV_ACC
Definition kest_block.h:13
#define BLOCK_INSTR_UMAC
Definition kest_block.h:19
#define BLOCK_INSTR_CLAMP
Definition kest_block.h:12
#define BLOCK_INSTR_MOV_UACC
Definition kest_block.h:15
#define BLOCK_INSTR_RSH
Definition kest_block.h:8
#define BLOCK_INSTR_FILTER
Definition kest_block.h:25
#define BLOCK_INSTR_MACZ
Definition kest_block.h:16
#define BLOCK_INSTR_MEM_READ
Definition kest_block.h:23
#define BLOCK_INSTR_MADD
Definition kest_block.h:5
#define BLOCK_INSTR_ABS
Definition kest_block.h:9
#define ZERO_REGISTER_ADDR
Definition kest_block.h:37
#define BLOCK_INSTR_MOV_LACC
Definition kest_block.h:14
#define BLOCK_INSTR_LSH
Definition kest_block.h:7
#define BLOCK_INSTR_MAX
Definition kest_block.h:11
#define BLOCK_INSTR_MIN
Definition kest_block.h:10
#define BLOCK_INSTR_LUT_READ
Definition kest_block.h:20
#define BLOCK_INSTR_ARSH
Definition kest_block.h:6
#define BLOCK_INSTR_NOP
Definition kest_block.h:4
char * kest_parser_strndup(const char *str, int n)
void * kest_parser_alloc(size_t size)
void kest_parser_error_at_line(kest_eff_parsing_state *ps, int line, const char *msg,...)
void kest_parser_error_at(kest_eff_parsing_state *ps, kest_token_ll *token, const char *msg,...)
const char * kest_error_code_to_string(int error_code)
#define ERR_ALLOC_FAIL
#define ERR_BAD_ARGS
#define NO_ERROR
#define ERR_UNKNOWN_ERR
#define ERR_NULL_PTR
kest_expression * kest_parse_expression(kest_eff_parsing_state *ps, kest_token_ll *tokens, kest_token_ll *tokens_end)
kest_expression * new_m_expression_reference(char *ref_name)
kest_expression * new_m_expression_const(float v)
const char * kest_expression_to_string(kest_expression *expr)
float kest_expression_evaluate(kest_expression *expr, kest_expr_scope *scope)
#define KEST_EXPR_CONST
#define KEST_EXPR_REF
#define IMPLEMENT_LINKED_PTR_LIST(X)
#define KEST_PRINTF(...)
Definition kest_printf.h:10
kest_dsp_resource sin_lut
kest_dsp_resource tanh_lut
int token_is_int(char *token)
float token_to_float(char *token)
int kest_token_ll_skip_ws(kest_token_ll **list)
struct kest_expression * expr
const char * instr
kest_asm_arg args[INSTR_MAX_ARGS]
struct kest_expression * expr
kest_dsp_resource * res
kest_expression * expr
Definition kest_block.h:49
kest_block_operand arg_b
Definition kest_block.h:56
kest_block_operand arg_c
Definition kest_block.h:57
kest_block_reg_val reg_0
Definition kest_block.h:61
kest_block_reg_val reg_1
Definition kest_block.h:62
kest_block_operand arg_a
Definition kest_block.h:55
int shift_set
Definition kest_block.h:65
int saturate_disable
Definition kest_block.h:66
kest_dsp_resource * res
Definition kest_block.h:68
kest_token_ll * current_token
kest_dsp_resource_pll * resources
kest_block_pll * blocks
struct kest_asm_line_pll * asm_lines
union kest_expression::@166010055114121035173062362142367362353107353142 val
struct kest_token_ll * next