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