master
y 915 lines 29 KB
Raw
1 %{
2 /*
3 * Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved.
4 *
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
9 *
10 * You should have received a copy of the GNU General Public License
11 * along with this program; if not, see <http://www.gnu.org/licenses/>.
12 */
13
14 #include "idef-parser.h"
15 #include "parser-helpers.h"
16 #include "idef-parser.tab.h"
17 #include "idef-parser.yy.h"
18
19 /* Uncomment this to disable yyasserts */
20 /* #define NDEBUG */
21
22 #define ERR_LINE_CONTEXT 40
23
24 %}
25
26 %lex-param {void *scanner}
27 %parse-param {void *scanner}
28 %parse-param {Context *c}
29
30 %define parse.error verbose
31 %define parse.lac full
32 %define api.pure full
33
34 %locations
35
36 %union {
37 GString *string;
38 HexValue rvalue;
39 HexSat sat;
40 HexCast cast;
41 HexExtract extract;
42 HexMpy mpy;
43 HexSignedness signedness;
44 int index;
45 }
46
47 /* Tokens */
48 %start input
49
50 %expect 1
51
52 %token IN INAME VAR
53 %token ABS CROUND ROUND CIRCADD COUNTONES INC DEC ANDA ORA XORA PLUSPLUS ASL
54 %token ASR LSR EQ NEQ LTE GTE MIN MAX ANDL FOR ICIRC IF MUN FSCR FCHK SXT
55 %token ZXT CONSTEXT LOCNT BREV SIGN LOAD STORE PC LPCFG
56 %token LOAD_CANCEL STORE_CANCEL CANCEL IDENTITY ROTL INSBITS SETBITS EXTRANGE
57 %token CAST4_8U FAIL CARRY_FROM_ADD ADDSAT64 LSBNEW
58 %token TYPE_SIZE_T TYPE_INT TYPE_SIGNED TYPE_UNSIGNED TYPE_LONG
59
60 %token <rvalue> REG IMM PRED
61 %token <index> ELSE
62 %token <mpy> MPY
63 %token <sat> SAT
64 %token <cast> CAST DEPOSIT SETHALF
65 %token <extract> EXTRACT
66 %type <string> INAME
67 %type <rvalue> rvalue lvalue VAR assign_statement var var_decl var_type
68 %type <rvalue> FAIL
69 %type <rvalue> TYPE_SIGNED TYPE_UNSIGNED TYPE_INT TYPE_LONG TYPE_SIZE_T
70 %type <index> if_stmt IF
71 %type <signedness> SIGN
72
73 /* Operator Precedences */
74 %left MIN MAX
75 %left '('
76 %left ','
77 %left '='
78 %right CIRCADD
79 %right INC DEC ANDA ORA XORA
80 %left '?' ':'
81 %left ANDL
82 %left '|'
83 %left '^' ANDOR
84 %left '&'
85 %left EQ NEQ
86 %left '<' '>' LTE GTE
87 %left ASL ASR LSR
88 %right ABS
89 %left '-' '+'
90 %left '*' '/' '%' MPY
91 %right '~' '!'
92 %left '['
93 %right CAST
94 %right LOCNT BREV
95
96 /* Bison Grammar */
97 %%
98
99 /* Input file containing the description of each hexagon instruction */
100 input : instructions
101 {
102 /* Suppress warning about unused yynerrs */
103 (void) yynerrs;
104 YYACCEPT;
105 }
106 ;
107
108 instructions : instruction instructions
109 | %empty
110 ;
111
112 instruction : INAME
113 {
114 gen_inst(c, $1);
115 }
116 arguments
117 {
118 EMIT_SIG(c, ")");
119 EMIT_HEAD(c, "{\n");
120 }
121 code
122 {
123 gen_inst_code(c, &@1);
124 }
125 | error /* Recover gracefully after instruction compilation error */
126 {
127 free_instruction(c);
128 }
129 ;
130
131 arguments : '(' ')'
132 | '(' argument_list ')';
133
134 argument_list : argument_decl ',' argument_list
135 | argument_decl
136 ;
137
138 var : VAR
139 {
140 track_string(c, $1.var.name);
141 $$ = $1;
142 }
143 ;
144
145 /*
146 * Here the integer types are defined from valid combinations of
147 * `signed`, `unsigned`, `int`, and `long` tokens. The `signed`
148 * and `unsigned` tokens are here assumed to always be placed
149 * first in the type declaration, which is not the case in
150 * normal C. Similarly, `int` is assumed to always be placed
151 * last in the type.
152 */
153 type_int : TYPE_INT
154 | TYPE_SIGNED
155 | TYPE_SIGNED TYPE_INT;
156 type_uint : TYPE_UNSIGNED
157 | TYPE_UNSIGNED TYPE_INT;
158 type_ulonglong : TYPE_UNSIGNED TYPE_LONG TYPE_LONG
159 | TYPE_UNSIGNED TYPE_LONG TYPE_LONG TYPE_INT;
160
161 /*
162 * Here the various valid int types defined above specify
163 * their `signedness` and `bit_width`. The LP64 convention
164 * is assumed where longs are 64-bit, long longs are then
165 * assumed to also be 64-bit.
166 */
167 var_type : TYPE_SIZE_T
168 {
169 yyassert(c, &@1, $1.bit_width <= 64,
170 "Variables with size > 64-bit are not supported!");
171 $$ = $1;
172 }
173 | type_int
174 {
175 $$.signedness = SIGNED;
176 $$.bit_width = 32;
177 }
178 | type_uint
179 {
180 $$.signedness = UNSIGNED;
181 $$.bit_width = 32;
182 }
183 | type_ulonglong
184 {
185 $$.signedness = UNSIGNED;
186 $$.bit_width = 64;
187 }
188 ;
189
190 /* Rule to capture declarations of VARs */
191 var_decl : var_type IMM
192 {
193 /*
194 * Rule to capture "int i;" declarations since "i" is special
195 * and assumed to be always be IMM. Moreover, "i" is only
196 * assumed to be used in for-loops.
197 *
198 * Therefore we want to NOP these declarations.
199 */
200 yyassert(c, &@2, $2.imm.type == I,
201 "Variable declaration with immedaties only allowed"
202 " for the loop induction variable \"i\"");
203 $$ = $2;
204 }
205 | var_type var
206 {
207 /*
208 * Allocate new variable, this checks that it hasn't already
209 * been declared.
210 */
211 gen_varid_allocate(c, &@1, &$2, $1.bit_width, $1.signedness);
212 /* Copy var for variable name */
213 $$ = $2;
214 /* Copy type info from var_type */
215 $$.signedness = $1.signedness;
216 $$.bit_width = $1.bit_width;
217 }
218 ;
219
220 /* Return the modified registers list */
221 code : '{' statements '}'
222 {
223 c->inst.code_begin = c->input_buffer + @2.first_column - 1;
224 c->inst.code_end = c->input_buffer + @2.last_column - 1;
225 }
226 | '{'
227 {
228 /* Nop */
229 }
230 '}'
231 ;
232
233 argument_decl : REG
234 {
235 emit_arg(c, &@1, &$1);
236 }
237 | PRED
238 {
239 emit_arg(c, &@1, &$1);
240 /* Enqueue predicate into initialization list */
241 g_array_append_val(c->inst.init_list, $1);
242 }
243 | IN REG
244 {
245 emit_arg(c, &@2, &$2);
246 }
247 | IN PRED
248 {
249 emit_arg(c, &@2, &$2);
250 }
251 | IMM
252 {
253 EMIT_SIG(c, ", int %ciV", $1.imm.id);
254 }
255 ;
256
257 code_block : '{' statements '}'
258 | '{' '}'
259 ;
260
261 /* A list of one or more statements */
262 statements : statements statement
263 | statement
264 ;
265
266 /* Statements can be assignment (rvalue ';'), control or memory statements */
267 statement : control_statement
268 | var_decl ';'
269 | rvalue ';'
270 | code_block
271 | ';'
272 ;
273
274 assign_statement : lvalue '=' rvalue
275 {
276 @1.last_column = @3.last_column;
277 gen_assign(c, &@1, &$1, &$3);
278 $$ = $1;
279 }
280 | var_decl '=' rvalue
281 {
282 @1.last_column = @3.last_column;
283 gen_assign(c, &@1, &$1, &$3);
284 $$ = $1;
285 }
286 | lvalue INC rvalue
287 {
288 @1.last_column = @3.last_column;
289 HexValue tmp = gen_bin_op(c, &@1, ADD_OP, &$1, &$3);
290 gen_assign(c, &@1, &$1, &tmp);
291 $$ = $1;
292 }
293 | lvalue DEC rvalue
294 {
295 @1.last_column = @3.last_column;
296 HexValue tmp = gen_bin_op(c, &@1, SUB_OP, &$1, &$3);
297 gen_assign(c, &@1, &$1, &tmp);
298 $$ = $1;
299 }
300 | lvalue ANDA rvalue
301 {
302 @1.last_column = @3.last_column;
303 HexValue tmp = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3);
304 gen_assign(c, &@1, &$1, &tmp);
305 $$ = $1;
306 }
307 | lvalue ORA rvalue
308 {
309 @1.last_column = @3.last_column;
310 HexValue tmp = gen_bin_op(c, &@1, ORB_OP, &$1, &$3);
311 gen_assign(c, &@1, &$1, &tmp);
312 $$ = $1;
313 }
314 | lvalue XORA rvalue
315 {
316 @1.last_column = @3.last_column;
317 HexValue tmp = gen_bin_op(c, &@1, XORB_OP, &$1, &$3);
318 gen_assign(c, &@1, &$1, &tmp);
319 $$ = $1;
320 }
321 | PRED '=' rvalue
322 {
323 @1.last_column = @3.last_column;
324 gen_pred_assign(c, &@1, &$1, &$3);
325 }
326 | IMM '=' rvalue
327 {
328 @1.last_column = @3.last_column;
329 yyassert(c, &@1, $3.type == IMMEDIATE,
330 "Cannot assign non-immediate to immediate!");
331 yyassert(c, &@1, $1.imm.type == VARIABLE,
332 "Cannot assign to non-variable!");
333 /* Assign to the function argument */
334 OUT(c, &@1, &$1, " = ", &$3, ";\n");
335 $$ = $1;
336 }
337 | LOAD '(' IMM ',' IMM ',' SIGN ',' var ',' lvalue ')'
338 {
339 @1.last_column = @12.last_column;
340 yyassert(c, &@1, !is_inside_ternary(c),
341 "Assignment side-effect not modeled!");
342 yyassert(c, &@1, $3.imm.value == 1,
343 "LOAD of arrays not supported!");
344 gen_load(c, &@1, &$5, $7, &$9, &$11);
345 }
346 | STORE '(' IMM ',' IMM ',' var ',' rvalue ')'
347 /* Store primitive */
348 {
349 @1.last_column = @10.last_column;
350 yyassert(c, &@1, !is_inside_ternary(c),
351 "Assignment side-effect not modeled!");
352 yyassert(c, &@1, $3.imm.value == 1,
353 "STORE of arrays not supported!");
354 gen_store(c, &@1, &$5, &$7, &$9);
355 }
356 | LPCFG '=' rvalue
357 {
358 @1.last_column = @3.last_column;
359 yyassert(c, &@1, !is_inside_ternary(c),
360 "Assignment side-effect not modeled!");
361 $3 = gen_rvalue_truncate(c, &@1, &$3);
362 $3 = rvalue_materialize(c, &@1, &$3);
363 OUT(c, &@1, "gen_set_usr_field(ctx, USR_LPCFG, ", &$3, ");\n");
364 }
365 | DEPOSIT '(' rvalue ',' rvalue ',' rvalue ')'
366 {
367 @1.last_column = @8.last_column;
368 yyassert(c, &@1, !is_inside_ternary(c),
369 "Assignment side-effect not modeled!");
370 gen_deposit_op(c, &@1, &$5, &$7, &$3, &$1);
371 }
372 | SETHALF '(' rvalue ',' lvalue ',' rvalue ')'
373 {
374 @1.last_column = @8.last_column;
375 yyassert(c, &@1, !is_inside_ternary(c),
376 "Assignment side-effect not modeled!");
377 gen_sethalf(c, &@1, &$1, &$3, &$5, &$7);
378 }
379 | SETBITS '(' rvalue ',' rvalue ',' rvalue ',' rvalue ')'
380 {
381 @1.last_column = @10.last_column;
382 yyassert(c, &@1, !is_inside_ternary(c),
383 "Assignment side-effect not modeled!");
384 gen_setbits(c, &@1, &$3, &$5, &$7, &$9);
385 }
386 | INSBITS '(' lvalue ',' rvalue ',' rvalue ',' rvalue ')'
387 {
388 @1.last_column = @10.last_column;
389 yyassert(c, &@1, !is_inside_ternary(c),
390 "Assignment side-effect not modeled!");
391 gen_rdeposit_op(c, &@1, &$3, &$9, &$7, &$5);
392 }
393 | IDENTITY '(' rvalue ')'
394 {
395 @1.last_column = @4.last_column;
396 $$ = $3;
397 }
398 ;
399
400 control_statement : frame_check
401 | cancel_statement
402 | if_statement
403 | for_statement
404 ;
405
406 frame_check : FCHK '(' rvalue ',' rvalue ')' ';'
407 {
408 gen_framecheck(c, &@1, &$3, &$5);
409 }
410 ;
411
412 cancel_statement : LOAD_CANCEL
413 {
414 gen_load_cancel(c, &@1);
415 }
416 | STORE_CANCEL
417 {
418 gen_cancel(c, &@1);
419 }
420 | CANCEL
421 ;
422
423 if_statement : if_stmt
424 {
425 /* Fix else label */
426 OUT(c, &@1, "gen_set_label(if_label_", &$1, ");\n");
427 }
428 | if_stmt ELSE
429 {
430 @1.last_column = @2.last_column;
431 $2 = gen_if_else(c, &@1, $1);
432 }
433 statement
434 {
435 OUT(c, &@1, "gen_set_label(if_label_", &$2, ");\n");
436 }
437 ;
438
439 for_statement : FOR '(' IMM '=' IMM ';' IMM '<' IMM ';' IMM PLUSPLUS ')'
440 {
441 yyassert(c, &@3,
442 $3.imm.type == I &&
443 $7.imm.type == I &&
444 $11.imm.type == I,
445 "Loop induction variable must be \"i\"");
446 @1.last_column = @13.last_column;
447 OUT(c, &@1, "for (int ", &$3, " = ", &$5, "; ",
448 &$7, " < ", &$9);
449 OUT(c, &@1, "; ", &$11, "++) {\n");
450 }
451 code_block
452 {
453 OUT(c, &@1, "}\n");
454 }
455 ;
456
457 if_stmt : IF '(' rvalue ')'
458 {
459 @1.last_column = @3.last_column;
460 $1 = gen_if_cond(c, &@1, &$3);
461 }
462 statement
463 {
464 $$ = $1;
465 }
466 ;
467
468 rvalue : FAIL
469 {
470 yyassert(c, &@1, false, "Encountered a FAIL token as rvalue.\n");
471 }
472 | assign_statement
473 | REG
474 {
475 $$ = $1;
476 }
477 | IMM
478 {
479 $$ = $1;
480 }
481 | PRED
482 {
483 $$ = gen_rvalue_pred(c, &@1, &$1);
484 }
485 | PC
486 {
487 /* Read PC from the CR */
488 HexValue rvalue;
489 memset(&rvalue, 0, sizeof(HexValue));
490 rvalue.type = IMMEDIATE;
491 rvalue.imm.type = IMM_PC;
492 rvalue.bit_width = 32;
493 rvalue.signedness = UNSIGNED;
494 $$ = rvalue;
495 }
496 | CONSTEXT
497 {
498 HexValue rvalue;
499 memset(&rvalue, 0, sizeof(HexValue));
500 rvalue.type = IMMEDIATE;
501 rvalue.imm.type = IMM_CONSTEXT;
502 rvalue.signedness = UNSIGNED;
503 rvalue.is_dotnew = false;
504 $$ = rvalue;
505 }
506 | var
507 {
508 $$ = gen_rvalue_var(c, &@1, &$1);
509 }
510 | MPY '(' rvalue ',' rvalue ')'
511 {
512 @1.last_column = @6.last_column;
513 $$ = gen_rvalue_mpy(c, &@1, &$1, &$3, &$5);
514 }
515 | rvalue '+' rvalue
516 {
517 @1.last_column = @3.last_column;
518 $$ = gen_bin_op(c, &@1, ADD_OP, &$1, &$3);
519 }
520 | rvalue '-' rvalue
521 {
522 @1.last_column = @3.last_column;
523 $$ = gen_bin_op(c, &@1, SUB_OP, &$1, &$3);
524 }
525 | rvalue '*' rvalue
526 {
527 @1.last_column = @3.last_column;
528 $$ = gen_bin_op(c, &@1, MUL_OP, &$1, &$3);
529 }
530 | rvalue ASL rvalue
531 {
532 @1.last_column = @3.last_column;
533 $$ = gen_bin_op(c, &@1, ASL_OP, &$1, &$3);
534 }
535 | rvalue ASR rvalue
536 {
537 @1.last_column = @3.last_column;
538 assert_signedness(c, &@1, $1.signedness);
539 if ($1.signedness == UNSIGNED) {
540 $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
541 } else if ($1.signedness == SIGNED) {
542 $$ = gen_bin_op(c, &@1, ASR_OP, &$1, &$3);
543 }
544 }
545 | rvalue LSR rvalue
546 {
547 @1.last_column = @3.last_column;
548 $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
549 }
550 | rvalue '&' rvalue
551 {
552 @1.last_column = @3.last_column;
553 $$ = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3);
554 }
555 | rvalue '|' rvalue
556 {
557 @1.last_column = @3.last_column;
558 $$ = gen_bin_op(c, &@1, ORB_OP, &$1, &$3);
559 }
560 | rvalue '^' rvalue
561 {
562 @1.last_column = @3.last_column;
563 $$ = gen_bin_op(c, &@1, XORB_OP, &$1, &$3);
564 }
565 | rvalue ANDL rvalue
566 {
567 @1.last_column = @3.last_column;
568 $$ = gen_bin_op(c, &@1, ANDL_OP, &$1, &$3);
569 }
570 | MIN '(' rvalue ',' rvalue ')'
571 {
572 @1.last_column = @3.last_column;
573 $$ = gen_bin_op(c, &@1, MINI_OP, &$3, &$5);
574 }
575 | MAX '(' rvalue ',' rvalue ')'
576 {
577 @1.last_column = @3.last_column;
578 $$ = gen_bin_op(c, &@1, MAXI_OP, &$3, &$5);
579 }
580 | '~' rvalue
581 {
582 @1.last_column = @2.last_column;
583 $$ = gen_rvalue_not(c, &@1, &$2);
584 }
585 | '!' rvalue
586 {
587 @1.last_column = @2.last_column;
588 $$ = gen_rvalue_notl(c, &@1, &$2);
589 }
590 | SAT '(' IMM ',' rvalue ')'
591 {
592 @1.last_column = @6.last_column;
593 $$ = gen_rvalue_sat(c, &@1, &$1, &$3, &$5);
594 }
595 | CAST rvalue
596 {
597 @1.last_column = @2.last_column;
598 $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness);
599 }
600 | rvalue EQ rvalue
601 {
602 @1.last_column = @3.last_column;
603 $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3);
604 }
605 | rvalue NEQ rvalue
606 {
607 @1.last_column = @3.last_column;
608 $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3);
609 }
610 | rvalue '<' rvalue
611 {
612 @1.last_column = @3.last_column;
613
614 assert_signedness(c, &@1, $1.signedness);
615 assert_signedness(c, &@1, $3.signedness);
616 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
617 $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3);
618 } else {
619 $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3);
620 }
621 }
622 | rvalue '>' rvalue
623 {
624 @1.last_column = @3.last_column;
625
626 assert_signedness(c, &@1, $1.signedness);
627 assert_signedness(c, &@1, $3.signedness);
628 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
629 $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3);
630 } else {
631 $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3);
632 }
633 }
634 | rvalue LTE rvalue
635 {
636 @1.last_column = @3.last_column;
637
638 assert_signedness(c, &@1, $1.signedness);
639 assert_signedness(c, &@1, $3.signedness);
640 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
641 $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3);
642 } else {
643 $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3);
644 }
645 }
646 | rvalue GTE rvalue
647 {
648 @1.last_column = @3.last_column;
649
650 assert_signedness(c, &@1, $1.signedness);
651 assert_signedness(c, &@1, $3.signedness);
652 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
653 $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3);
654 } else {
655 $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3);
656 }
657 }
658 | rvalue '?'
659 {
660 Ternary t = { 0 };
661 t.state = IN_LEFT;
662 t.cond = $1;
663 g_array_append_val(c->ternary, t);
664 }
665 rvalue ':'
666 {
667 Ternary *t = &g_array_index(c->ternary, Ternary,
668 c->ternary->len - 1);
669 t->state = IN_RIGHT;
670 }
671 rvalue
672 {
673 @1.last_column = @5.last_column;
674 $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7);
675 }
676 | FSCR '(' rvalue ')'
677 {
678 @1.last_column = @4.last_column;
679 $$ = gen_rvalue_fscr(c, &@1, &$3);
680 }
681 | SXT '(' rvalue ',' IMM ',' rvalue ')'
682 {
683 @1.last_column = @8.last_column;
684 yyassert(c, &@1, $5.type == IMMEDIATE &&
685 $5.imm.type == VALUE,
686 "SXT expects immediate values\n");
687 $$ = gen_extend_op(c, &@1, &$3, 64, &$7, SIGNED);
688 }
689 | ZXT '(' rvalue ',' IMM ',' rvalue ')'
690 {
691 @1.last_column = @8.last_column;
692 yyassert(c, &@1, $5.type == IMMEDIATE &&
693 $5.imm.type == VALUE,
694 "ZXT expects immediate values\n");
695 $$ = gen_extend_op(c, &@1, &$3, 64, &$7, UNSIGNED);
696 }
697 | '(' rvalue ')'
698 {
699 $$ = $2;
700 }
701 | ABS rvalue
702 {
703 @1.last_column = @2.last_column;
704 $$ = gen_rvalue_abs(c, &@1, &$2);
705 }
706 | CROUND '(' rvalue ',' rvalue ')'
707 {
708 @1.last_column = @6.last_column;
709 $$ = gen_convround_n(c, &@1, &$3, &$5);
710 }
711 | CROUND '(' rvalue ')'
712 {
713 @1.last_column = @4.last_column;
714 $$ = gen_convround(c, &@1, &$3);
715 }
716 | ROUND '(' rvalue ',' rvalue ')'
717 {
718 @1.last_column = @6.last_column;
719 $$ = gen_round(c, &@1, &$3, &$5);
720 }
721 | '-' rvalue
722 {
723 @1.last_column = @2.last_column;
724 $$ = gen_rvalue_neg(c, &@1, &$2);
725 }
726 | ICIRC '(' rvalue ')' ASL IMM
727 {
728 @1.last_column = @6.last_column;
729 $$ = gen_tmp(c, &@1, 32, UNSIGNED);
730 OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n");
731 }
732 | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')'
733 {
734 @1.last_column = @8.last_column;
735 gen_circ_op(c, &@1, &$3, &$5, &$7);
736 }
737 | LOCNT '(' rvalue ')'
738 {
739 @1.last_column = @4.last_column;
740 /* Leading ones count */
741 $$ = gen_locnt_op(c, &@1, &$3);
742 }
743 | COUNTONES '(' rvalue ')'
744 {
745 @1.last_column = @4.last_column;
746 /* Ones count */
747 $$ = gen_ctpop_op(c, &@1, &$3);
748 }
749 | EXTRACT '(' rvalue ',' rvalue ')'
750 {
751 @1.last_column = @6.last_column;
752 $$ = gen_extract_op(c, &@1, &$5, &$3, &$1);
753 }
754 | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')'
755 {
756 @1.last_column = @8.last_column;
757 yyassert(c, &@1, $5.type == IMMEDIATE &&
758 $5.imm.type == VALUE &&
759 $7.type == IMMEDIATE &&
760 $7.imm.type == VALUE,
761 "Range extract needs immediate values!\n");
762 $$ = gen_rextract_op(c,
763 &@1,
764 &$3,
765 $7.imm.value,
766 $5.imm.value - $7.imm.value + 1);
767 }
768 | CAST4_8U '(' rvalue ')'
769 {
770 @1.last_column = @4.last_column;
771 $$ = gen_rvalue_truncate(c, &@1, &$3);
772 $$.signedness = UNSIGNED;
773 $$ = rvalue_materialize(c, &@1, &$$);
774 $$ = gen_rvalue_extend(c, &@1, &$$);
775 }
776 | BREV '(' rvalue ')'
777 {
778 @1.last_column = @4.last_column;
779 $$ = gen_rvalue_brev(c, &@1, &$3);
780 }
781 | ROTL '(' rvalue ',' rvalue ')'
782 {
783 @1.last_column = @6.last_column;
784 $$ = gen_rotl(c, &@1, &$3, &$5);
785 }
786 | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')'
787 {
788 @1.last_column = @8.last_column;
789 gen_addsat64(c, &@1, &$3, &$5, &$7);
790 }
791 | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')'
792 {
793 @1.last_column = @8.last_column;
794 $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7);
795 }
796 | LSBNEW '(' rvalue ')'
797 {
798 @1.last_column = @4.last_column;
799 HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED);
800 $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one);
801 }
802 ;
803
804 lvalue : FAIL
805 {
806 yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\n");
807 }
808 | REG
809 {
810 $$ = $1;
811 }
812 | var
813 {
814 $$ = $1;
815 }
816 ;
817
818 %%
819
820 int main(int argc, char **argv)
821 {
822 if (argc != 5) {
823 fprintf(stderr,
824 "Semantics: Hexagon ISA to tinycode generator compiler\n\n");
825 fprintf(stderr,
826 "Usage: ./semantics IDEFS EMITTER_C EMITTER_H "
827 "ENABLED_INSTRUCTIONS_LIST\n");
828 return 1;
829 }
830
831 enum {
832 ARG_INDEX_ARGV0 = 0,
833 ARG_INDEX_IDEFS,
834 ARG_INDEX_EMITTER_C,
835 ARG_INDEX_EMITTER_H,
836 ARG_INDEX_ENABLED_INSTRUCTIONS_LIST
837 };
838
839 FILE *enabled_file = fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST], "w");
840
841 FILE *output_file = fopen(argv[ARG_INDEX_EMITTER_C], "w");
842 fputs("#include \"qemu/osdep.h\"\n", output_file);
843 fputs("#include \"qemu/log.h\"\n", output_file);
844 fputs("#include \"cpu.h\"\n", output_file);
845 fputs("#include \"internal.h\"\n", output_file);
846 fputs("#include \"tcg/tcg.h\"\n", output_file);
847 fputs("#include \"tcg/tcg-op.h\"\n", output_file);
848 fputs("#include \"exec/helper-gen.h\"\n", output_file);
849 fputs("#include \"insn.h\"\n", output_file);
850 fputs("#include \"opcodes.h\"\n", output_file);
851 fputs("#include \"translate.h\"\n", output_file);
852 fputs("#define QEMU_GENERATE\n", output_file);
853 fputs("#include \"genptr.h\"\n", output_file);
854 fputs("#include \"macros.h\"\n", output_file);
855 fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]);
856
857 FILE *defines_file = fopen(argv[ARG_INDEX_EMITTER_H], "w");
858 assert(defines_file != NULL);
859 fputs("#ifndef HEX_EMITTER_H\n", defines_file);
860 fputs("#define HEX_EMITTER_H\n", defines_file);
861 fputs("\n", defines_file);
862 fputs("#include \"insn.h\"\n\n", defines_file);
863
864 /* Parser input file */
865 Context context = { 0 };
866 context.defines_file = defines_file;
867 context.output_file = output_file;
868 context.enabled_file = enabled_file;
869 /* Initialize buffers */
870 context.out_str = g_string_new(NULL);
871 context.signature_str = g_string_new(NULL);
872 context.header_str = g_string_new(NULL);
873 context.ternary = g_array_new(FALSE, TRUE, sizeof(Ternary));
874 /* Read input file */
875 FILE *input_file = fopen(argv[ARG_INDEX_IDEFS], "rb");
876 fseek(input_file, 0L, SEEK_END);
877 long input_size = ftell(input_file);
878 context.input_buffer = (char *) calloc(input_size + 1, sizeof(char));
879 fseek(input_file, 0L, SEEK_SET);
880 size_t read_chars = fread(context.input_buffer,
881 sizeof(char),
882 input_size,
883 input_file);
884 if (read_chars != (size_t) input_size) {
885 fprintf(stderr, "Error: an error occurred while reading input file!\n");
886 return -1;
887 }
888 yylex_init(&context.scanner);
889 YY_BUFFER_STATE buffer;
890 buffer = yy_scan_string(context.input_buffer, context.scanner);
891 /* Start the parsing procedure */
892 yyparse(context.scanner, &context);
893 if (context.implemented_insn != context.total_insn) {
894 fprintf(stderr,
895 "Warning: %d/%d meta instructions have been implemented!\n",
896 context.implemented_insn,
897 context.total_insn);
898 }
899 fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n",
900 defines_file);
901 /* Cleanup */
902 yy_delete_buffer(buffer, context.scanner);
903 yylex_destroy(context.scanner);
904 free(context.input_buffer);
905 g_string_free(context.out_str, TRUE);
906 g_string_free(context.signature_str, TRUE);
907 g_string_free(context.header_str, TRUE);
908 g_array_free(context.ternary, TRUE);
909 fclose(output_file);
910 fclose(input_file);
911 fclose(defines_file);
912 fclose(enabled_file);
913
914 return 0;
915 }