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                     /* Enqueue register into initialization list */
237                     g_array_append_val(c->inst.init_list, $1);
238                 }
239               | PRED
240                 {
241                     emit_arg(c, &@1, &$1);
242                     /* Enqueue predicate into initialization list */
243                     g_array_append_val(c->inst.init_list, $1);
244                 }
245               | IN REG
246                 {
247                     emit_arg(c, &@2, &$2);
248                 }
249               | IN PRED
250                 {
251                     emit_arg(c, &@2, &$2);
252                 }
253               | IMM
254                 {
255                     EMIT_SIG(c, ", int %ciV", $1.imm.id);
256                 }
257               ;
258 
259 code_block : '{' statements '}'
260            | '{' '}'
261            ;
262 
263 /* A list of one or more statements */
264 statements : statements statement
265            | statement
266            ;
267 
268 /* Statements can be assignment (rvalue ';'), control or memory statements */
269 statement : control_statement
270           | var_decl ';'
271           | rvalue ';'
272           | code_block
273           | ';'
274           ;
275 
276 assign_statement : lvalue '=' rvalue
277                    {
278                        @1.last_column = @3.last_column;
279                        gen_assign(c, &@1, &$1, &$3);
280                        $$ = $1;
281                    }
282                  | var_decl '=' rvalue
283                    {
284                        @1.last_column = @3.last_column;
285                        gen_assign(c, &@1, &$1, &$3);
286                        $$ = $1;
287                    }
288                  | lvalue INC rvalue
289                    {
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;
294                    }
295                  | lvalue DEC rvalue
296                    {
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;
301                    }
302                  | lvalue ANDA rvalue
303                    {
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;
308                    }
309                  | lvalue ORA rvalue
310                    {
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;
315                    }
316                  | lvalue XORA rvalue
317                    {
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;
322                    }
323                  | PRED '=' rvalue
324                    {
325                        @1.last_column = @3.last_column;
326                        gen_pred_assign(c, &@1, &$1, &$3);
327                    }
328                  | IMM '=' rvalue
329                    {
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;
338                    }
339                  | LOAD '(' IMM ',' IMM ',' SIGN ',' var ',' lvalue ')'
340                    {
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);
347                    }
348                  | STORE '(' IMM ',' IMM ',' var ',' rvalue ')'
349                    /* Store primitive */
350                    {
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);
357                    }
358                  | LPCFG '=' rvalue
359                    {
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");
366                    }
367                  | DEPOSIT '(' rvalue ',' rvalue ',' rvalue ')'
368                    {
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);
373                    }
374                  | SETHALF '(' rvalue ',' lvalue ',' rvalue ')'
375                    {
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);
380                    }
381                  | SETBITS '(' rvalue ',' rvalue ',' rvalue ',' rvalue ')'
382                    {
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);
387                    }
388                  | INSBITS '(' lvalue ',' rvalue ',' rvalue ',' rvalue ')'
389                    {
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);
394                    }
395                  | IDENTITY '(' rvalue ')'
396                    {
397                        @1.last_column = @4.last_column;
398                        $$ = $3;
399                    }
400                  ;
401 
402 control_statement : frame_check
403                   | cancel_statement
404                   | if_statement
405                   | for_statement
406                   ;
407 
408 frame_check : FCHK '(' rvalue ',' rvalue ')' ';'
409             ;
410 
411 cancel_statement : LOAD_CANCEL
412                    {
413                        gen_load_cancel(c, &@1);
414                    }
415                  | STORE_CANCEL
416                    {
417                        gen_cancel(c, &@1);
418                    }
419                  | CANCEL
420                  ;
421 
422 if_statement : if_stmt
423                {
424                    /* Fix else label */
425                    OUT(c, &@1, "gen_set_label(if_label_", &$1, ");\n");
426                }
427              | if_stmt ELSE
428                {
429                    @1.last_column = @2.last_column;
430                    $2 = gen_if_else(c, &@1, $1);
431                }
432                statement
433                {
434                    OUT(c, &@1, "gen_set_label(if_label_", &$2, ");\n");
435                }
436              ;
437 
438 for_statement : FOR '(' IMM '=' IMM ';' IMM '<' IMM ';' IMM PLUSPLUS ')'
439                 {
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");
449                 }
450                 code_block
451                 {
452                     OUT(c, &@1, "}\n");
453                 }
454               ;
455 
456 if_stmt : IF '(' rvalue ')'
457           {
458               @1.last_column = @3.last_column;
459               $1 = gen_if_cond(c, &@1, &$3);
460           }
461           statement
462           {
463               $$ = $1;
464           }
465         ;
466 
467 rvalue : FAIL
468          {
469              yyassert(c, &@1, false, "Encountered a FAIL token as rvalue.\n");
470          }
471        | assign_statement
472        | REG
473          {
474              $$ = $1;
475          }
476        | IMM
477          {
478              $$ = $1;
479          }
480        | PRED
481          {
482              $$ = gen_rvalue_pred(c, &@1, &$1);
483          }
484        | PC
485          {
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;
494          }
495        | CONSTEXT
496          {
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;
504          }
505        | var
506          {
507              $$ = gen_rvalue_var(c, &@1, &$1);
508          }
509        | MPY '(' rvalue ',' rvalue ')'
510          {
511              @1.last_column = @6.last_column;
512              $$ = gen_rvalue_mpy(c, &@1, &$1, &$3, &$5);
513          }
514        | rvalue '+' rvalue
515          {
516              @1.last_column = @3.last_column;
517              $$ = gen_bin_op(c, &@1, ADD_OP, &$1, &$3);
518          }
519        | rvalue '-' rvalue
520          {
521              @1.last_column = @3.last_column;
522              $$ = gen_bin_op(c, &@1, SUB_OP, &$1, &$3);
523          }
524        | rvalue '*' rvalue
525          {
526              @1.last_column = @3.last_column;
527              $$ = gen_bin_op(c, &@1, MUL_OP, &$1, &$3);
528          }
529        | rvalue ASL rvalue
530          {
531              @1.last_column = @3.last_column;
532              $$ = gen_bin_op(c, &@1, ASL_OP, &$1, &$3);
533          }
534        | rvalue ASR rvalue
535          {
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);
542              }
543          }
544        | rvalue LSR rvalue
545          {
546              @1.last_column = @3.last_column;
547              $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3);
548          }
549        | rvalue '&' rvalue
550          {
551              @1.last_column = @3.last_column;
552              $$ = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3);
553          }
554        | rvalue '|' rvalue
555          {
556              @1.last_column = @3.last_column;
557              $$ = gen_bin_op(c, &@1, ORB_OP, &$1, &$3);
558          }
559        | rvalue '^' rvalue
560          {
561              @1.last_column = @3.last_column;
562              $$ = gen_bin_op(c, &@1, XORB_OP, &$1, &$3);
563          }
564        | rvalue ANDL rvalue
565          {
566              @1.last_column = @3.last_column;
567              $$ = gen_bin_op(c, &@1, ANDL_OP, &$1, &$3);
568          }
569        | MIN '(' rvalue ',' rvalue ')'
570          {
571              @1.last_column = @3.last_column;
572              $$ = gen_bin_op(c, &@1, MINI_OP, &$3, &$5);
573          }
574        | MAX '(' rvalue ',' rvalue ')'
575          {
576              @1.last_column = @3.last_column;
577              $$ = gen_bin_op(c, &@1, MAXI_OP, &$3, &$5);
578          }
579        | '~' rvalue
580          {
581              @1.last_column = @2.last_column;
582              $$ = gen_rvalue_not(c, &@1, &$2);
583          }
584        | '!' rvalue
585          {
586              @1.last_column = @2.last_column;
587              $$ = gen_rvalue_notl(c, &@1, &$2);
588          }
589        | SAT '(' IMM ',' rvalue ')'
590          {
591              @1.last_column = @6.last_column;
592              $$ = gen_rvalue_sat(c, &@1, &$1, &$3, &$5);
593          }
594        | CAST rvalue
595          {
596              @1.last_column = @2.last_column;
597              $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness);
598          }
599        | rvalue EQ rvalue
600          {
601              @1.last_column = @3.last_column;
602              $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3);
603          }
604        | rvalue NEQ rvalue
605          {
606              @1.last_column = @3.last_column;
607              $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3);
608          }
609        | rvalue '<' rvalue
610          {
611              @1.last_column = @3.last_column;
612 
613              assert_signedness(c, &@1, $1.signedness);
614              assert_signedness(c, &@1, $3.signedness);
615              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
616                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3);
617              } else {
618                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3);
619              }
620          }
621        | rvalue '>' rvalue
622          {
623              @1.last_column = @3.last_column;
624 
625              assert_signedness(c, &@1, $1.signedness);
626              assert_signedness(c, &@1, $3.signedness);
627              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
628                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3);
629              } else {
630                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3);
631              }
632          }
633        | rvalue LTE rvalue
634          {
635              @1.last_column = @3.last_column;
636 
637              assert_signedness(c, &@1, $1.signedness);
638              assert_signedness(c, &@1, $3.signedness);
639              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
640                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3);
641              } else {
642                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3);
643              }
644          }
645        | rvalue GTE rvalue
646          {
647              @1.last_column = @3.last_column;
648 
649              assert_signedness(c, &@1, $1.signedness);
650              assert_signedness(c, &@1, $3.signedness);
651              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
652                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3);
653              } else {
654                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3);
655              }
656          }
657        | rvalue '?'
658          {
659              Ternary t = { 0 };
660              t.state = IN_LEFT;
661              t.cond = $1;
662              g_array_append_val(c->ternary, t);
663          }
664          rvalue ':'
665          {
666              Ternary *t = &g_array_index(c->ternary, Ternary,
667                                          c->ternary->len - 1);
668              t->state = IN_RIGHT;
669          }
670          rvalue
671          {
672              @1.last_column = @5.last_column;
673              $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7);
674          }
675        | FSCR '(' rvalue ')'
676          {
677              @1.last_column = @4.last_column;
678              $$ = gen_rvalue_fscr(c, &@1, &$3);
679          }
680        | SXT '(' rvalue ',' IMM ',' rvalue ')'
681          {
682              @1.last_column = @8.last_column;
683              yyassert(c, &@1, $5.type == IMMEDIATE &&
684                       $5.imm.type == VALUE,
685                       "SXT expects immediate values\n");
686              $$ = gen_extend_op(c, &@1, &$3, 64, &$7, SIGNED);
687          }
688        | ZXT '(' rvalue ',' IMM ',' rvalue ')'
689          {
690              @1.last_column = @8.last_column;
691              yyassert(c, &@1, $5.type == IMMEDIATE &&
692                       $5.imm.type == VALUE,
693                       "ZXT expects immediate values\n");
694              $$ = gen_extend_op(c, &@1, &$3, 64, &$7, UNSIGNED);
695          }
696        | '(' rvalue ')'
697          {
698              $$ = $2;
699          }
700        | ABS rvalue
701          {
702              @1.last_column = @2.last_column;
703              $$ = gen_rvalue_abs(c, &@1, &$2);
704          }
705        | CROUND '(' rvalue ',' rvalue ')'
706          {
707              @1.last_column = @6.last_column;
708              $$ = gen_convround_n(c, &@1, &$3, &$5);
709          }
710        | CROUND '(' rvalue ')'
711          {
712              @1.last_column = @4.last_column;
713              $$ = gen_convround(c, &@1, &$3);
714          }
715        | ROUND '(' rvalue ',' rvalue ')'
716          {
717              @1.last_column = @6.last_column;
718              $$ = gen_round(c, &@1, &$3, &$5);
719          }
720        | '-' rvalue
721          {
722              @1.last_column = @2.last_column;
723              $$ = gen_rvalue_neg(c, &@1, &$2);
724          }
725        | ICIRC '(' rvalue ')' ASL IMM
726          {
727              @1.last_column = @6.last_column;
728              $$ = gen_tmp(c, &@1, 32, UNSIGNED);
729              OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n");
730          }
731        | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')'
732          {
733              @1.last_column = @8.last_column;
734              gen_circ_op(c, &@1, &$3, &$5, &$7);
735          }
736        | LOCNT '(' rvalue ')'
737          {
738              @1.last_column = @4.last_column;
739              /* Leading ones count */
740              $$ = gen_locnt_op(c, &@1, &$3);
741          }
742        | COUNTONES '(' rvalue ')'
743          {
744              @1.last_column = @4.last_column;
745              /* Ones count */
746              $$ = gen_ctpop_op(c, &@1, &$3);
747          }
748        | EXTRACT '(' rvalue ',' rvalue ')'
749          {
750              @1.last_column = @6.last_column;
751              $$ = gen_extract_op(c, &@1, &$5, &$3, &$1);
752          }
753        | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')'
754          {
755              @1.last_column = @8.last_column;
756              yyassert(c, &@1, $5.type == IMMEDIATE &&
757                       $5.imm.type == VALUE &&
758                       $7.type == IMMEDIATE &&
759                       $7.imm.type == VALUE,
760                       "Range extract needs immediate values!\n");
761              $$ = gen_rextract_op(c,
762                                   &@1,
763                                   &$3,
764                                   $7.imm.value,
765                                   $5.imm.value - $7.imm.value + 1);
766          }
767        | CAST4_8U '(' rvalue ')'
768          {
769              @1.last_column = @4.last_column;
770              $$ = gen_rvalue_truncate(c, &@1, &$3);
771              $$.signedness = UNSIGNED;
772              $$ = rvalue_materialize(c, &@1, &$$);
773              $$ = gen_rvalue_extend(c, &@1, &$$);
774          }
775        | BREV '(' rvalue ')'
776          {
777              @1.last_column = @4.last_column;
778              $$ = gen_rvalue_brev(c, &@1, &$3);
779          }
780        | ROTL '(' rvalue ',' rvalue ')'
781          {
782              @1.last_column = @6.last_column;
783              $$ = gen_rotl(c, &@1, &$3, &$5);
784          }
785        | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')'
786          {
787              @1.last_column = @8.last_column;
788              gen_addsat64(c, &@1, &$3, &$5, &$7);
789          }
790        | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')'
791          {
792              @1.last_column = @8.last_column;
793              $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7);
794          }
795        | LSBNEW '(' rvalue ')'
796          {
797              @1.last_column = @4.last_column;
798              HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED);
799              $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one);
800          }
801        ;
802 
803 lvalue : FAIL
804          {
805              @1.last_column = @1.last_column;
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], "r");
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 }
916