qapi: Improve specificity of type/member descriptions
[qemu/armbru.git] / target / hexagon / idef-parser / idef-parser.y
blob5444fd4749c23a9df31d5f3df16849e3815c15f7
1 %{
2 /*
3 * Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved.
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.
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/>.
14 #include "idef-parser.h"
15 #include "parser-helpers.h"
16 #include "idef-parser.tab.h"
17 #include "idef-parser.yy.h"
19 /* Uncomment this to disable yyasserts */
20 /* #define NDEBUG */
22 #define ERR_LINE_CONTEXT 40
26 %lex-param {void *scanner}
27 %parse-param {void *scanner}
28 %parse-param {Context *c}
30 %define parse.error verbose
31 %define parse.lac full
32 %define api.pure full
34 %locations
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;
47 /* Tokens */
48 %start input
50 %expect 1
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
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
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
96 /* Bison Grammar */
99 /* Input file containing the description of each hexagon instruction */
100 input : instructions
102 /* Suppress warning about unused yynerrs */
103 (void) yynerrs;
104 YYACCEPT;
108 instructions : instruction instructions
109 | %empty
112 instruction : INAME
114 gen_inst(c, $1);
116 arguments
118 EMIT_SIG(c, ")");
119 EMIT_HEAD(c, "{\n");
121 code
123 gen_inst_code(c, &@1);
125 | error /* Recover gracefully after instruction compilation error */
127 free_instruction(c);
131 arguments : '(' ')'
132 | '(' argument_list ')';
134 argument_list : argument_decl ',' argument_list
135 | argument_decl
138 var : VAR
140 track_string(c, $1.var.name);
141 $$ = $1;
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.
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;
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.
167 var_type : TYPE_SIZE_T
169 yyassert(c, &@1, $1.bit_width <= 64,
170 "Variables with size > 64-bit are not supported!");
171 $$ = $1;
173 | type_int
175 $$.signedness = SIGNED;
176 $$.bit_width = 32;
178 | type_uint
180 $$.signedness = UNSIGNED;
181 $$.bit_width = 32;
183 | type_ulonglong
185 $$.signedness = UNSIGNED;
186 $$.bit_width = 64;
190 /* Rule to capture declarations of VARs */
191 var_decl : var_type IMM
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.
198 * Therefore we want to NOP these declarations.
200 yyassert(c, &@2, $2.imm.type == I,
201 "Variable declaration with immedaties only allowed"
202 " for the loop induction variable \"i\"");
203 $$ = $2;
205 | var_type var
208 * Allocate new variable, this checks that it hasn't already
209 * been declared.
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;
220 /* Return the modified registers list */
221 code : '{' statements '}'
223 c->inst.code_begin = c->input_buffer + @2.first_column - 1;
224 c->inst.code_end = c->input_buffer + @2.last_column - 1;
226 | '{'
228 /* Nop */
233 argument_decl : REG
235 emit_arg(c, &@1, &$1);
236 /* Enqueue register into initialization list */
237 g_array_append_val(c->inst.init_list, $1);
239 | PRED
241 emit_arg(c, &@1, &$1);
242 /* Enqueue predicate into initialization list */
243 g_array_append_val(c->inst.init_list, $1);
245 | IN REG
247 emit_arg(c, &@2, &$2);
249 | IN PRED
251 emit_arg(c, &@2, &$2);
253 | IMM
255 EMIT_SIG(c, ", int %ciV", $1.imm.id);
259 code_block : '{' statements '}'
260 | '{' '}'
263 /* A list of one or more statements */
264 statements : statements statement
265 | statement
268 /* Statements can be assignment (rvalue ';'), control or memory statements */
269 statement : control_statement
270 | var_decl ';'
271 | rvalue ';'
272 | code_block
273 | ';'
276 assign_statement : lvalue '=' rvalue
278 @1.last_column = @3.last_column;
279 gen_assign(c, &@1, &$1, &$3);
280 $$ = $1;
282 | var_decl '=' rvalue
284 @1.last_column = @3.last_column;
285 gen_assign(c, &@1, &$1, &$3);
286 $$ = $1;
288 | lvalue INC rvalue
290 @1.last_column = @3.last_column;
291 HexValue tmp = gen_bin_op(c, &@1, ADD_OP, &$1, &$3);
292 gen_assign(c, &@1, &$1, &tmp);
293 $$ = $1;
295 | lvalue DEC rvalue
297 @1.last_column = @3.last_column;
298 HexValue tmp = gen_bin_op(c, &@1, SUB_OP, &$1, &$3);
299 gen_assign(c, &@1, &$1, &tmp);
300 $$ = $1;
302 | lvalue ANDA rvalue
304 @1.last_column = @3.last_column;
305 HexValue tmp = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3);
306 gen_assign(c, &@1, &$1, &tmp);
307 $$ = $1;
309 | lvalue ORA rvalue
311 @1.last_column = @3.last_column;
312 HexValue tmp = gen_bin_op(c, &@1, ORB_OP, &$1, &$3);
313 gen_assign(c, &@1, &$1, &tmp);
314 $$ = $1;
316 | lvalue XORA rvalue
318 @1.last_column = @3.last_column;
319 HexValue tmp = gen_bin_op(c, &@1, XORB_OP, &$1, &$3);
320 gen_assign(c, &@1, &$1, &tmp);
321 $$ = $1;
323 | PRED '=' rvalue
325 @1.last_column = @3.last_column;
326 gen_pred_assign(c, &@1, &$1, &$3);
328 | IMM '=' rvalue
330 @1.last_column = @3.last_column;
331 yyassert(c, &@1, $3.type == IMMEDIATE,
332 "Cannot assign non-immediate to immediate!");
333 yyassert(c, &@1, $1.imm.type == VARIABLE,
334 "Cannot assign to non-variable!");
335 /* Assign to the function argument */
336 OUT(c, &@1, &$1, " = ", &$3, ";\n");
337 $$ = $1;
339 | LOAD '(' IMM ',' IMM ',' SIGN ',' var ',' lvalue ')'
341 @1.last_column = @12.last_column;
342 yyassert(c, &@1, !is_inside_ternary(c),
343 "Assignment side-effect not modeled!");
344 yyassert(c, &@1, $3.imm.value == 1,
345 "LOAD of arrays not supported!");
346 gen_load(c, &@1, &$5, $7, &$9, &$11);
348 | STORE '(' IMM ',' IMM ',' var ',' rvalue ')'
349 /* Store primitive */
351 @1.last_column = @10.last_column;
352 yyassert(c, &@1, !is_inside_ternary(c),
353 "Assignment side-effect not modeled!");
354 yyassert(c, &@1, $3.imm.value == 1,
355 "STORE of arrays not supported!");
356 gen_store(c, &@1, &$5, &$7, &$9);
358 | LPCFG '=' rvalue
360 @1.last_column = @3.last_column;
361 yyassert(c, &@1, !is_inside_ternary(c),
362 "Assignment side-effect not modeled!");
363 $3 = gen_rvalue_truncate(c, &@1, &$3);
364 $3 = rvalue_materialize(c, &@1, &$3);
365 OUT(c, &@1, "gen_set_usr_field(ctx, USR_LPCFG, ", &$3, ");\n");
367 | DEPOSIT '(' rvalue ',' rvalue ',' rvalue ')'
369 @1.last_column = @8.last_column;
370 yyassert(c, &@1, !is_inside_ternary(c),
371 "Assignment side-effect not modeled!");
372 gen_deposit_op(c, &@1, &$5, &$7, &$3, &$1);
374 | SETHALF '(' rvalue ',' lvalue ',' rvalue ')'
376 @1.last_column = @8.last_column;
377 yyassert(c, &@1, !is_inside_ternary(c),
378 "Assignment side-effect not modeled!");
379 gen_sethalf(c, &@1, &$1, &$3, &$5, &$7);
381 | SETBITS '(' rvalue ',' rvalue ',' rvalue ',' rvalue ')'
383 @1.last_column = @10.last_column;
384 yyassert(c, &@1, !is_inside_ternary(c),
385 "Assignment side-effect not modeled!");
386 gen_setbits(c, &@1, &$3, &$5, &$7, &$9);
388 | INSBITS '(' lvalue ',' rvalue ',' rvalue ',' rvalue ')'
390 @1.last_column = @10.last_column;
391 yyassert(c, &@1, !is_inside_ternary(c),
392 "Assignment side-effect not modeled!");
393 gen_rdeposit_op(c, &@1, &$3, &$9, &$7, &$5);
395 | IDENTITY '(' rvalue ')'
397 @1.last_column = @4.last_column;
398 $$ = $3;
402 control_statement : frame_check
403 | cancel_statement
404 | if_statement
405 | for_statement
408 frame_check : FCHK '(' rvalue ',' rvalue ')' ';'
411 cancel_statement : LOAD_CANCEL
413 gen_load_cancel(c, &@1);
415 | STORE_CANCEL
417 gen_cancel(c, &@1);
419 | CANCEL
422 if_statement : if_stmt
424 /* Fix else label */
425 OUT(c, &@1, "gen_set_label(if_label_", &$1, ");\n");
427 | if_stmt ELSE
429 @1.last_column = @2.last_column;
430 $2 = gen_if_else(c, &@1, $1);
432 statement
434 OUT(c, &@1, "gen_set_label(if_label_", &$2, ");\n");
438 for_statement : FOR '(' IMM '=' IMM ';' IMM '<' IMM ';' IMM PLUSPLUS ')'
440 yyassert(c, &@3,
441 $3.imm.type == I &&
442 $7.imm.type == I &&
443 $11.imm.type == I,
444 "Loop induction variable must be \"i\"");
445 @1.last_column = @13.last_column;
446 OUT(c, &@1, "for (int ", &$3, " = ", &$5, "; ",
447 &$7, " < ", &$9);
448 OUT(c, &@1, "; ", &$11, "++) {\n");
450 code_block
452 OUT(c, &@1, "}\n");
456 if_stmt : IF '(' rvalue ')'
458 @1.last_column = @3.last_column;
459 $1 = gen_if_cond(c, &@1, &$3);
461 statement
463 $$ = $1;
467 rvalue : FAIL
469 yyassert(c, &@1, false, "Encountered a FAIL token as rvalue.\n");
471 | assign_statement
472 | REG
474 $$ = $1;
476 | IMM
478 $$ = $1;
480 | PRED
482 $$ = gen_rvalue_pred(c, &@1, &$1);
484 | PC
486 /* Read PC from the CR */
487 HexValue rvalue;
488 memset(&rvalue, 0, sizeof(HexValue));
489 rvalue.type = IMMEDIATE;
490 rvalue.imm.type = IMM_PC;
491 rvalue.bit_width = 32;
492 rvalue.signedness = UNSIGNED;
493 $$ = rvalue;
495 | CONSTEXT
497 HexValue rvalue;
498 memset(&rvalue, 0, sizeof(HexValue));
499 rvalue.type = IMMEDIATE;
500 rvalue.imm.type = IMM_CONSTEXT;
501 rvalue.signedness = UNSIGNED;
502 rvalue.is_dotnew = false;
503 $$ = rvalue;
505 | var
507 $$ = gen_rvalue_var(c, &@1, &$1);
509 | MPY '(' rvalue ',' rvalue ')'
511 @1.last_column = @6.last_column;
512 $$ = gen_rvalue_mpy(c, &@1, &$1, &$3, &$5);
514 | rvalue '+' rvalue
516 @1.last_column = @3.last_column;
517 $$ = gen_bin_op(c, &@1, ADD_OP, &$1, &$3);
519 | rvalue '-' rvalue
521 @1.last_column = @3.last_column;
522 $$ = gen_bin_op(c, &@1, SUB_OP, &$1, &$3);
524 | rvalue '*' rvalue
526 @1.last_column = @3.last_column;
527 $$ = gen_bin_op(c, &@1, MUL_OP, &$1, &$3);
529 | rvalue ASL rvalue
531 @1.last_column = @3.last_column;
532 $$ = gen_bin_op(c, &@1, ASL_OP, &$1, &$3);
534 | rvalue ASR rvalue
536 @1.last_column = @3.last_column;
537 assert_signedness(c, &@1, $1.signedness);
538 if ($1.signedness == UNSIGNED) {
539 $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
540 } else if ($1.signedness == SIGNED) {
541 $$ = gen_bin_op(c, &@1, ASR_OP, &$1, &$3);
544 | rvalue LSR rvalue
546 @1.last_column = @3.last_column;
547 $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
549 | rvalue '&' rvalue
551 @1.last_column = @3.last_column;
552 $$ = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3);
554 | rvalue '|' rvalue
556 @1.last_column = @3.last_column;
557 $$ = gen_bin_op(c, &@1, ORB_OP, &$1, &$3);
559 | rvalue '^' rvalue
561 @1.last_column = @3.last_column;
562 $$ = gen_bin_op(c, &@1, XORB_OP, &$1, &$3);
564 | rvalue ANDL rvalue
566 @1.last_column = @3.last_column;
567 $$ = gen_bin_op(c, &@1, ANDL_OP, &$1, &$3);
569 | MIN '(' rvalue ',' rvalue ')'
571 @1.last_column = @3.last_column;
572 $$ = gen_bin_op(c, &@1, MINI_OP, &$3, &$5);
574 | MAX '(' rvalue ',' rvalue ')'
576 @1.last_column = @3.last_column;
577 $$ = gen_bin_op(c, &@1, MAXI_OP, &$3, &$5);
579 | '~' rvalue
581 @1.last_column = @2.last_column;
582 $$ = gen_rvalue_not(c, &@1, &$2);
584 | '!' rvalue
586 @1.last_column = @2.last_column;
587 $$ = gen_rvalue_notl(c, &@1, &$2);
589 | SAT '(' IMM ',' rvalue ')'
591 @1.last_column = @6.last_column;
592 $$ = gen_rvalue_sat(c, &@1, &$1, &$3, &$5);
594 | CAST rvalue
596 @1.last_column = @2.last_column;
597 /* Assign target signedness */
598 $2.signedness = $1.signedness;
599 $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness);
601 | rvalue EQ rvalue
603 @1.last_column = @3.last_column;
604 $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3);
606 | rvalue NEQ rvalue
608 @1.last_column = @3.last_column;
609 $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3);
611 | rvalue '<' rvalue
613 @1.last_column = @3.last_column;
615 assert_signedness(c, &@1, $1.signedness);
616 assert_signedness(c, &@1, $3.signedness);
617 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
618 $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3);
619 } else {
620 $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3);
623 | rvalue '>' rvalue
625 @1.last_column = @3.last_column;
627 assert_signedness(c, &@1, $1.signedness);
628 assert_signedness(c, &@1, $3.signedness);
629 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
630 $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3);
631 } else {
632 $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3);
635 | rvalue LTE rvalue
637 @1.last_column = @3.last_column;
639 assert_signedness(c, &@1, $1.signedness);
640 assert_signedness(c, &@1, $3.signedness);
641 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
642 $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3);
643 } else {
644 $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3);
647 | rvalue GTE rvalue
649 @1.last_column = @3.last_column;
651 assert_signedness(c, &@1, $1.signedness);
652 assert_signedness(c, &@1, $3.signedness);
653 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
654 $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3);
655 } else {
656 $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3);
659 | rvalue '?'
661 Ternary t = { 0 };
662 t.state = IN_LEFT;
663 t.cond = $1;
664 g_array_append_val(c->ternary, t);
666 rvalue ':'
668 Ternary *t = &g_array_index(c->ternary, Ternary,
669 c->ternary->len - 1);
670 t->state = IN_RIGHT;
672 rvalue
674 @1.last_column = @5.last_column;
675 $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7);
677 | FSCR '(' rvalue ')'
679 @1.last_column = @4.last_column;
680 $$ = gen_rvalue_fscr(c, &@1, &$3);
682 | SXT '(' rvalue ',' IMM ',' rvalue ')'
684 @1.last_column = @8.last_column;
685 yyassert(c, &@1, $5.type == IMMEDIATE &&
686 $5.imm.type == VALUE,
687 "SXT expects immediate values\n");
688 $$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, SIGNED);
690 | ZXT '(' rvalue ',' IMM ',' rvalue ')'
692 @1.last_column = @8.last_column;
693 yyassert(c, &@1, $5.type == IMMEDIATE &&
694 $5.imm.type == VALUE,
695 "ZXT expects immediate values\n");
696 $$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, UNSIGNED);
698 | '(' rvalue ')'
700 $$ = $2;
702 | ABS rvalue
704 @1.last_column = @2.last_column;
705 $$ = gen_rvalue_abs(c, &@1, &$2);
707 | CROUND '(' rvalue ',' rvalue ')'
709 @1.last_column = @6.last_column;
710 $$ = gen_convround_n(c, &@1, &$3, &$5);
712 | CROUND '(' rvalue ')'
714 @1.last_column = @4.last_column;
715 $$ = gen_convround(c, &@1, &$3);
717 | ROUND '(' rvalue ',' rvalue ')'
719 @1.last_column = @6.last_column;
720 $$ = gen_round(c, &@1, &$3, &$5);
722 | '-' rvalue
724 @1.last_column = @2.last_column;
725 $$ = gen_rvalue_neg(c, &@1, &$2);
727 | ICIRC '(' rvalue ')' ASL IMM
729 @1.last_column = @6.last_column;
730 $$ = gen_tmp(c, &@1, 32, UNSIGNED);
731 OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n");
733 | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')'
735 @1.last_column = @8.last_column;
736 gen_circ_op(c, &@1, &$3, &$5, &$7);
738 | LOCNT '(' rvalue ')'
740 @1.last_column = @4.last_column;
741 /* Leading ones count */
742 $$ = gen_locnt_op(c, &@1, &$3);
744 | COUNTONES '(' rvalue ')'
746 @1.last_column = @4.last_column;
747 /* Ones count */
748 $$ = gen_ctpop_op(c, &@1, &$3);
750 | EXTRACT '(' rvalue ',' rvalue ')'
752 @1.last_column = @6.last_column;
753 $$ = gen_extract_op(c, &@1, &$5, &$3, &$1);
755 | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')'
757 @1.last_column = @8.last_column;
758 yyassert(c, &@1, $5.type == IMMEDIATE &&
759 $5.imm.type == VALUE &&
760 $7.type == IMMEDIATE &&
761 $7.imm.type == VALUE,
762 "Range extract needs immediate values!\n");
763 $$ = gen_rextract_op(c,
764 &@1,
765 &$3,
766 $7.imm.value,
767 $5.imm.value - $7.imm.value + 1);
769 | CAST4_8U '(' rvalue ')'
771 @1.last_column = @4.last_column;
772 $$ = gen_rvalue_truncate(c, &@1, &$3);
773 $$.signedness = UNSIGNED;
774 $$ = rvalue_materialize(c, &@1, &$$);
775 $$ = gen_rvalue_extend(c, &@1, &$$);
777 | BREV '(' rvalue ')'
779 @1.last_column = @4.last_column;
780 $$ = gen_rvalue_brev(c, &@1, &$3);
782 | ROTL '(' rvalue ',' rvalue ')'
784 @1.last_column = @6.last_column;
785 $$ = gen_rotl(c, &@1, &$3, &$5);
787 | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')'
789 @1.last_column = @8.last_column;
790 gen_addsat64(c, &@1, &$3, &$5, &$7);
792 | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')'
794 @1.last_column = @8.last_column;
795 $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7);
797 | LSBNEW '(' rvalue ')'
799 @1.last_column = @4.last_column;
800 HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED);
801 $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one);
805 lvalue : FAIL
807 @1.last_column = @1.last_column;
808 yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\n");
810 | REG
812 $$ = $1;
814 | var
816 $$ = $1;
822 int main(int argc, char **argv)
824 if (argc != 5) {
825 fprintf(stderr,
826 "Semantics: Hexagon ISA to tinycode generator compiler\n\n");
827 fprintf(stderr,
828 "Usage: ./semantics IDEFS EMITTER_C EMITTER_H "
829 "ENABLED_INSTRUCTIONS_LIST\n");
830 return 1;
833 enum {
834 ARG_INDEX_ARGV0 = 0,
835 ARG_INDEX_IDEFS,
836 ARG_INDEX_EMITTER_C,
837 ARG_INDEX_EMITTER_H,
838 ARG_INDEX_ENABLED_INSTRUCTIONS_LIST
841 FILE *enabled_file = fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST], "w");
843 FILE *output_file = fopen(argv[ARG_INDEX_EMITTER_C], "w");
844 fputs("#include \"qemu/osdep.h\"\n", output_file);
845 fputs("#include \"qemu/log.h\"\n", output_file);
846 fputs("#include \"cpu.h\"\n", output_file);
847 fputs("#include \"internal.h\"\n", output_file);
848 fputs("#include \"tcg/tcg-op.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 \"tcg/tcg.h\"\n", output_file);
855 fputs("#include \"macros.h\"\n", output_file);
856 fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]);
858 FILE *defines_file = fopen(argv[ARG_INDEX_EMITTER_H], "w");
859 assert(defines_file != NULL);
860 fputs("#ifndef HEX_EMITTER_H\n", defines_file);
861 fputs("#define HEX_EMITTER_H\n", defines_file);
862 fputs("\n", defines_file);
863 fputs("#include \"insn.h\"\n\n", defines_file);
865 /* Parser input file */
866 Context context = { 0 };
867 context.defines_file = defines_file;
868 context.output_file = output_file;
869 context.enabled_file = enabled_file;
870 /* Initialize buffers */
871 context.out_str = g_string_new(NULL);
872 context.signature_str = g_string_new(NULL);
873 context.header_str = g_string_new(NULL);
874 context.ternary = g_array_new(FALSE, TRUE, sizeof(Ternary));
875 /* Read input file */
876 FILE *input_file = fopen(argv[ARG_INDEX_IDEFS], "r");
877 fseek(input_file, 0L, SEEK_END);
878 long input_size = ftell(input_file);
879 context.input_buffer = (char *) calloc(input_size + 1, sizeof(char));
880 fseek(input_file, 0L, SEEK_SET);
881 size_t read_chars = fread(context.input_buffer,
882 sizeof(char),
883 input_size,
884 input_file);
885 if (read_chars != (size_t) input_size) {
886 fprintf(stderr, "Error: an error occurred while reading input file!\n");
887 return -1;
889 yylex_init(&context.scanner);
890 YY_BUFFER_STATE buffer;
891 buffer = yy_scan_string(context.input_buffer, context.scanner);
892 /* Start the parsing procedure */
893 yyparse(context.scanner, &context);
894 if (context.implemented_insn != context.total_insn) {
895 fprintf(stderr,
896 "Warning: %d/%d meta instructions have been implemented!\n",
897 context.implemented_insn,
898 context.total_insn);
900 fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n",
901 defines_file);
902 /* Cleanup */
903 yy_delete_buffer(buffer, context.scanner);
904 yylex_destroy(context.scanner);
905 free(context.input_buffer);
906 g_string_free(context.out_str, TRUE);
907 g_string_free(context.signature_str, TRUE);
908 g_string_free(context.header_str, TRUE);
909 g_array_free(context.ternary, TRUE);
910 fclose(output_file);
911 fclose(input_file);
912 fclose(defines_file);
913 fclose(enabled_file);
915 return 0;