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 
409 cancel_statement : LOAD_CANCEL
410                    {
411                        gen_load_cancel(c, &@1);
412                    }
413                  | STORE_CANCEL
414                    {
415                        gen_cancel(c, &@1);
416                    }
417                  | CANCEL
418                  ;
419 
420 if_statement : if_stmt
421                {
422                    /* Fix else label */
423                    OUT(c, &@1, "gen_set_label(if_label_", &$1, ");\n");
424                }
425              | if_stmt ELSE
426                {
427                    @1.last_column = @2.last_column;
428                    $2 = gen_if_else(c, &@1, $1);
429                }
430                statement
431                {
432                    OUT(c, &@1, "gen_set_label(if_label_", &$2, ");\n");
433                }
434              ;
435 
436 for_statement : FOR '(' IMM '=' IMM ';' IMM '<' IMM ';' IMM PLUSPLUS ')'
437                 {
438                     yyassert(c, &@3,
439                              $3.imm.type == I &&
440                              $7.imm.type == I &&
441                              $11.imm.type == I,
442                              "Loop induction variable must be \"i\"");
443                     @1.last_column = @13.last_column;
444                     OUT(c, &@1, "for (int ", &$3, " = ", &$5, "; ",
445                         &$7, " < ", &$9);
446                     OUT(c, &@1, "; ", &$11, "++) {\n");
447                 }
448                 code_block
449                 {
450                     OUT(c, &@1, "}\n");
451                 }
452               ;
453 
454 if_stmt : IF '(' rvalue ')'
455           {
456               @1.last_column = @3.last_column;
457               $1 = gen_if_cond(c, &@1, &$3);
458           }
459           statement
460           {
461               $$ = $1;
462           }
463         ;
464 
465 rvalue : FAIL
466          {
467              yyassert(c, &@1, false, "Encountered a FAIL token as rvalue.\n");
468          }
469        | assign_statement
470        | REG
471          {
472              $$ = $1;
473          }
474        | IMM
475          {
476              $$ = $1;
477          }
478        | PRED
479          {
480              $$ = gen_rvalue_pred(c, &@1, &$1);
481          }
482        | PC
483          {
484              /* Read PC from the CR */
485              HexValue rvalue;
486              memset(&rvalue, 0, sizeof(HexValue));
487              rvalue.type = IMMEDIATE;
488              rvalue.imm.type = IMM_PC;
489              rvalue.bit_width = 32;
490              rvalue.signedness = UNSIGNED;
491              $$ = rvalue;
492          }
493        | CONSTEXT
494          {
495              HexValue rvalue;
496              memset(&rvalue, 0, sizeof(HexValue));
497              rvalue.type = IMMEDIATE;
498              rvalue.imm.type = IMM_CONSTEXT;
499              rvalue.signedness = UNSIGNED;
500              rvalue.is_dotnew = false;
501              $$ = rvalue;
502          }
503        | var
504          {
505              $$ = gen_rvalue_var(c, &@1, &$1);
506          }
507        | MPY '(' rvalue ',' rvalue ')'
508          {
509              @1.last_column = @6.last_column;
510              $$ = gen_rvalue_mpy(c, &@1, &$1, &$3, &$5);
511          }
512        | rvalue '+' rvalue
513          {
514              @1.last_column = @3.last_column;
515              $$ = gen_bin_op(c, &@1, ADD_OP, &$1, &$3);
516          }
517        | rvalue '-' rvalue
518          {
519              @1.last_column = @3.last_column;
520              $$ = gen_bin_op(c, &@1, SUB_OP, &$1, &$3);
521          }
522        | rvalue '*' rvalue
523          {
524              @1.last_column = @3.last_column;
525              $$ = gen_bin_op(c, &@1, MUL_OP, &$1, &$3);
526          }
527        | rvalue ASL rvalue
528          {
529              @1.last_column = @3.last_column;
530              $$ = gen_bin_op(c, &@1, ASL_OP, &$1, &$3);
531          }
532        | rvalue ASR rvalue
533          {
534              @1.last_column = @3.last_column;
535              assert_signedness(c, &@1, $1.signedness);
536              if ($1.signedness == UNSIGNED) {
537                  $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
538              } else if ($1.signedness == SIGNED) {
539                  $$ = gen_bin_op(c, &@1, ASR_OP, &$1, &$3);
540              }
541          }
542        | rvalue LSR rvalue
543          {
544              @1.last_column = @3.last_column;
545              $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
546          }
547        | rvalue '&' rvalue
548          {
549              @1.last_column = @3.last_column;
550              $$ = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3);
551          }
552        | rvalue '|' rvalue
553          {
554              @1.last_column = @3.last_column;
555              $$ = gen_bin_op(c, &@1, ORB_OP, &$1, &$3);
556          }
557        | rvalue '^' rvalue
558          {
559              @1.last_column = @3.last_column;
560              $$ = gen_bin_op(c, &@1, XORB_OP, &$1, &$3);
561          }
562        | rvalue ANDL rvalue
563          {
564              @1.last_column = @3.last_column;
565              $$ = gen_bin_op(c, &@1, ANDL_OP, &$1, &$3);
566          }
567        | MIN '(' rvalue ',' rvalue ')'
568          {
569              @1.last_column = @3.last_column;
570              $$ = gen_bin_op(c, &@1, MINI_OP, &$3, &$5);
571          }
572        | MAX '(' rvalue ',' rvalue ')'
573          {
574              @1.last_column = @3.last_column;
575              $$ = gen_bin_op(c, &@1, MAXI_OP, &$3, &$5);
576          }
577        | '~' rvalue
578          {
579              @1.last_column = @2.last_column;
580              $$ = gen_rvalue_not(c, &@1, &$2);
581          }
582        | '!' rvalue
583          {
584              @1.last_column = @2.last_column;
585              $$ = gen_rvalue_notl(c, &@1, &$2);
586          }
587        | SAT '(' IMM ',' rvalue ')'
588          {
589              @1.last_column = @6.last_column;
590              $$ = gen_rvalue_sat(c, &@1, &$1, &$3, &$5);
591          }
592        | CAST rvalue
593          {
594              @1.last_column = @2.last_column;
595              $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness);
596          }
597        | rvalue EQ rvalue
598          {
599              @1.last_column = @3.last_column;
600              $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3);
601          }
602        | rvalue NEQ rvalue
603          {
604              @1.last_column = @3.last_column;
605              $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3);
606          }
607        | rvalue '<' rvalue
608          {
609              @1.last_column = @3.last_column;
610 
611              assert_signedness(c, &@1, $1.signedness);
612              assert_signedness(c, &@1, $3.signedness);
613              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
614                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3);
615              } else {
616                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3);
617              }
618          }
619        | rvalue '>' rvalue
620          {
621              @1.last_column = @3.last_column;
622 
623              assert_signedness(c, &@1, $1.signedness);
624              assert_signedness(c, &@1, $3.signedness);
625              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
626                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3);
627              } else {
628                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3);
629              }
630          }
631        | rvalue LTE rvalue
632          {
633              @1.last_column = @3.last_column;
634 
635              assert_signedness(c, &@1, $1.signedness);
636              assert_signedness(c, &@1, $3.signedness);
637              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
638                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3);
639              } else {
640                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3);
641              }
642          }
643        | rvalue GTE rvalue
644          {
645              @1.last_column = @3.last_column;
646 
647              assert_signedness(c, &@1, $1.signedness);
648              assert_signedness(c, &@1, $3.signedness);
649              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
650                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3);
651              } else {
652                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3);
653              }
654          }
655        | rvalue '?'
656          {
657              Ternary t = { 0 };
658              t.state = IN_LEFT;
659              t.cond = $1;
660              g_array_append_val(c->ternary, t);
661          }
662          rvalue ':'
663          {
664              Ternary *t = &g_array_index(c->ternary, Ternary,
665                                          c->ternary->len - 1);
666              t->state = IN_RIGHT;
667          }
668          rvalue
669          {
670              @1.last_column = @5.last_column;
671              $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7);
672          }
673        | FSCR '(' rvalue ')'
674          {
675              @1.last_column = @4.last_column;
676              $$ = gen_rvalue_fscr(c, &@1, &$3);
677          }
678        | SXT '(' rvalue ',' IMM ',' rvalue ')'
679          {
680              @1.last_column = @8.last_column;
681              yyassert(c, &@1, $5.type == IMMEDIATE &&
682                       $5.imm.type == VALUE,
683                       "SXT expects immediate values\n");
684              $$ = gen_extend_op(c, &@1, &$3, 64, &$7, SIGNED);
685          }
686        | ZXT '(' rvalue ',' IMM ',' rvalue ')'
687          {
688              @1.last_column = @8.last_column;
689              yyassert(c, &@1, $5.type == IMMEDIATE &&
690                       $5.imm.type == VALUE,
691                       "ZXT expects immediate values\n");
692              $$ = gen_extend_op(c, &@1, &$3, 64, &$7, UNSIGNED);
693          }
694        | '(' rvalue ')'
695          {
696              $$ = $2;
697          }
698        | ABS rvalue
699          {
700              @1.last_column = @2.last_column;
701              $$ = gen_rvalue_abs(c, &@1, &$2);
702          }
703        | CROUND '(' rvalue ',' rvalue ')'
704          {
705              @1.last_column = @6.last_column;
706              $$ = gen_convround_n(c, &@1, &$3, &$5);
707          }
708        | CROUND '(' rvalue ')'
709          {
710              @1.last_column = @4.last_column;
711              $$ = gen_convround(c, &@1, &$3);
712          }
713        | ROUND '(' rvalue ',' rvalue ')'
714          {
715              @1.last_column = @6.last_column;
716              $$ = gen_round(c, &@1, &$3, &$5);
717          }
718        | '-' rvalue
719          {
720              @1.last_column = @2.last_column;
721              $$ = gen_rvalue_neg(c, &@1, &$2);
722          }
723        | ICIRC '(' rvalue ')' ASL IMM
724          {
725              @1.last_column = @6.last_column;
726              $$ = gen_tmp(c, &@1, 32, UNSIGNED);
727              OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n");
728          }
729        | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')'
730          {
731              @1.last_column = @8.last_column;
732              gen_circ_op(c, &@1, &$3, &$5, &$7);
733          }
734        | LOCNT '(' rvalue ')'
735          {
736              @1.last_column = @4.last_column;
737              /* Leading ones count */
738              $$ = gen_locnt_op(c, &@1, &$3);
739          }
740        | COUNTONES '(' rvalue ')'
741          {
742              @1.last_column = @4.last_column;
743              /* Ones count */
744              $$ = gen_ctpop_op(c, &@1, &$3);
745          }
746        | EXTRACT '(' rvalue ',' rvalue ')'
747          {
748              @1.last_column = @6.last_column;
749              $$ = gen_extract_op(c, &@1, &$5, &$3, &$1);
750          }
751        | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')'
752          {
753              @1.last_column = @8.last_column;
754              yyassert(c, &@1, $5.type == IMMEDIATE &&
755                       $5.imm.type == VALUE &&
756                       $7.type == IMMEDIATE &&
757                       $7.imm.type == VALUE,
758                       "Range extract needs immediate values!\n");
759              $$ = gen_rextract_op(c,
760                                   &@1,
761                                   &$3,
762                                   $7.imm.value,
763                                   $5.imm.value - $7.imm.value + 1);
764          }
765        | CAST4_8U '(' rvalue ')'
766          {
767              @1.last_column = @4.last_column;
768              $$ = gen_rvalue_truncate(c, &@1, &$3);
769              $$.signedness = UNSIGNED;
770              $$ = rvalue_materialize(c, &@1, &$$);
771              $$ = gen_rvalue_extend(c, &@1, &$$);
772          }
773        | BREV '(' rvalue ')'
774          {
775              @1.last_column = @4.last_column;
776              $$ = gen_rvalue_brev(c, &@1, &$3);
777          }
778        | ROTL '(' rvalue ',' rvalue ')'
779          {
780              @1.last_column = @6.last_column;
781              $$ = gen_rotl(c, &@1, &$3, &$5);
782          }
783        | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')'
784          {
785              @1.last_column = @8.last_column;
786              gen_addsat64(c, &@1, &$3, &$5, &$7);
787          }
788        | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')'
789          {
790              @1.last_column = @8.last_column;
791              $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7);
792          }
793        | LSBNEW '(' rvalue ')'
794          {
795              @1.last_column = @4.last_column;
796              HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED);
797              $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one);
798          }
799        ;
800 
801 lvalue : FAIL
802          {
803              @1.last_column = @1.last_column;
804              yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\n");
805          }
806        | REG
807          {
808              $$ = $1;
809          }
810        | var
811          {
812              $$ = $1;
813          }
814        ;
815 
816 %%
817 
818 int main(int argc, char **argv)
819 {
820     if (argc != 5) {
821         fprintf(stderr,
822                 "Semantics: Hexagon ISA to tinycode generator compiler\n\n");
823         fprintf(stderr,
824                 "Usage: ./semantics IDEFS EMITTER_C EMITTER_H "
825                 "ENABLED_INSTRUCTIONS_LIST\n");
826         return 1;
827     }
828 
829     enum {
830         ARG_INDEX_ARGV0 = 0,
831         ARG_INDEX_IDEFS,
832         ARG_INDEX_EMITTER_C,
833         ARG_INDEX_EMITTER_H,
834         ARG_INDEX_ENABLED_INSTRUCTIONS_LIST
835     };
836 
837     FILE *enabled_file = fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST], "w");
838 
839     FILE *output_file = fopen(argv[ARG_INDEX_EMITTER_C], "w");
840     fputs("#include \"qemu/osdep.h\"\n", output_file);
841     fputs("#include \"qemu/log.h\"\n", output_file);
842     fputs("#include \"cpu.h\"\n", output_file);
843     fputs("#include \"internal.h\"\n", output_file);
844     fputs("#include \"tcg/tcg.h\"\n", output_file);
845     fputs("#include \"tcg/tcg-op.h\"\n", output_file);
846     fputs("#include \"exec/helper-gen.h\"\n", output_file);
847     fputs("#include \"insn.h\"\n", output_file);
848     fputs("#include \"opcodes.h\"\n", output_file);
849     fputs("#include \"translate.h\"\n", output_file);
850     fputs("#define QEMU_GENERATE\n", output_file);
851     fputs("#include \"genptr.h\"\n", output_file);
852     fputs("#include \"macros.h\"\n", output_file);
853     fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]);
854 
855     FILE *defines_file = fopen(argv[ARG_INDEX_EMITTER_H], "w");
856     assert(defines_file != NULL);
857     fputs("#ifndef HEX_EMITTER_H\n", defines_file);
858     fputs("#define HEX_EMITTER_H\n", defines_file);
859     fputs("\n", defines_file);
860     fputs("#include \"insn.h\"\n\n", defines_file);
861 
862     /* Parser input file */
863     Context context = { 0 };
864     context.defines_file = defines_file;
865     context.output_file = output_file;
866     context.enabled_file = enabled_file;
867     /* Initialize buffers */
868     context.out_str = g_string_new(NULL);
869     context.signature_str = g_string_new(NULL);
870     context.header_str = g_string_new(NULL);
871     context.ternary = g_array_new(FALSE, TRUE, sizeof(Ternary));
872     /* Read input file */
873     FILE *input_file = fopen(argv[ARG_INDEX_IDEFS], "r");
874     fseek(input_file, 0L, SEEK_END);
875     long input_size = ftell(input_file);
876     context.input_buffer = (char *) calloc(input_size + 1, sizeof(char));
877     fseek(input_file, 0L, SEEK_SET);
878     size_t read_chars = fread(context.input_buffer,
879                               sizeof(char),
880                               input_size,
881                               input_file);
882     if (read_chars != (size_t) input_size) {
883         fprintf(stderr, "Error: an error occurred while reading input file!\n");
884         return -1;
885     }
886     yylex_init(&context.scanner);
887     YY_BUFFER_STATE buffer;
888     buffer = yy_scan_string(context.input_buffer, context.scanner);
889     /* Start the parsing procedure */
890     yyparse(context.scanner, &context);
891     if (context.implemented_insn != context.total_insn) {
892         fprintf(stderr,
893                 "Warning: %d/%d meta instructions have been implemented!\n",
894                 context.implemented_insn,
895                 context.total_insn);
896     }
897     fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n",
898           defines_file);
899     /* Cleanup */
900     yy_delete_buffer(buffer, context.scanner);
901     yylex_destroy(context.scanner);
902     free(context.input_buffer);
903     g_string_free(context.out_str, TRUE);
904     g_string_free(context.signature_str, TRUE);
905     g_string_free(context.header_str, TRUE);
906     g_array_free(context.ternary, TRUE);
907     fclose(output_file);
908     fclose(input_file);
909     fclose(defines_file);
910     fclose(enabled_file);
911 
912     return 0;
913 }
914