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              /* Assign target signedness */
598              $2.signedness = $1.signedness;
599              $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness);
600          }
601        | rvalue EQ rvalue
602          {
603              @1.last_column = @3.last_column;
604              $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3);
605          }
606        | rvalue NEQ rvalue
607          {
608              @1.last_column = @3.last_column;
609              $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3);
610          }
611        | rvalue '<' rvalue
612          {
613              @1.last_column = @3.last_column;
614 
615              assert_signedness(c, &@1, $1.signedness);
616              assert_signedness(c, &@1, $3.signedness);
617              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
618                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3);
619              } else {
620                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3);
621              }
622          }
623        | rvalue '>' rvalue
624          {
625              @1.last_column = @3.last_column;
626 
627              assert_signedness(c, &@1, $1.signedness);
628              assert_signedness(c, &@1, $3.signedness);
629              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
630                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3);
631              } else {
632                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3);
633              }
634          }
635        | rvalue LTE rvalue
636          {
637              @1.last_column = @3.last_column;
638 
639              assert_signedness(c, &@1, $1.signedness);
640              assert_signedness(c, &@1, $3.signedness);
641              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
642                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3);
643              } else {
644                  $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3);
645              }
646          }
647        | rvalue GTE rvalue
648          {
649              @1.last_column = @3.last_column;
650 
651              assert_signedness(c, &@1, $1.signedness);
652              assert_signedness(c, &@1, $3.signedness);
653              if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) {
654                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3);
655              } else {
656                  $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3);
657              }
658          }
659        | rvalue '?'
660          {
661              Ternary t = { 0 };
662              t.state = IN_LEFT;
663              t.cond = $1;
664              g_array_append_val(c->ternary, t);
665          }
666          rvalue ':'
667          {
668              Ternary *t = &g_array_index(c->ternary, Ternary,
669                                          c->ternary->len - 1);
670              t->state = IN_RIGHT;
671          }
672          rvalue
673          {
674              @1.last_column = @5.last_column;
675              $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7);
676          }
677        | FSCR '(' rvalue ')'
678          {
679              @1.last_column = @4.last_column;
680              $$ = gen_rvalue_fscr(c, &@1, &$3);
681          }
682        | SXT '(' rvalue ',' IMM ',' rvalue ')'
683          {
684              @1.last_column = @8.last_column;
685              yyassert(c, &@1, $5.type == IMMEDIATE &&
686                       $5.imm.type == VALUE,
687                       "SXT expects immediate values\n");
688              $$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, SIGNED);
689          }
690        | ZXT '(' rvalue ',' IMM ',' rvalue ')'
691          {
692              @1.last_column = @8.last_column;
693              yyassert(c, &@1, $5.type == IMMEDIATE &&
694                       $5.imm.type == VALUE,
695                       "ZXT expects immediate values\n");
696              $$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, UNSIGNED);
697          }
698        | '(' rvalue ')'
699          {
700              $$ = $2;
701          }
702        | ABS rvalue
703          {
704              @1.last_column = @2.last_column;
705              $$ = gen_rvalue_abs(c, &@1, &$2);
706          }
707        | CROUND '(' rvalue ',' rvalue ')'
708          {
709              @1.last_column = @6.last_column;
710              $$ = gen_convround_n(c, &@1, &$3, &$5);
711          }
712        | CROUND '(' rvalue ')'
713          {
714              @1.last_column = @4.last_column;
715              $$ = gen_convround(c, &@1, &$3);
716          }
717        | ROUND '(' rvalue ',' rvalue ')'
718          {
719              @1.last_column = @6.last_column;
720              $$ = gen_round(c, &@1, &$3, &$5);
721          }
722        | '-' rvalue
723          {
724              @1.last_column = @2.last_column;
725              $$ = gen_rvalue_neg(c, &@1, &$2);
726          }
727        | ICIRC '(' rvalue ')' ASL IMM
728          {
729              @1.last_column = @6.last_column;
730              $$ = gen_tmp(c, &@1, 32, UNSIGNED);
731              OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n");
732          }
733        | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')'
734          {
735              @1.last_column = @8.last_column;
736              gen_circ_op(c, &@1, &$3, &$5, &$7);
737          }
738        | LOCNT '(' rvalue ')'
739          {
740              @1.last_column = @4.last_column;
741              /* Leading ones count */
742              $$ = gen_locnt_op(c, &@1, &$3);
743          }
744        | COUNTONES '(' rvalue ')'
745          {
746              @1.last_column = @4.last_column;
747              /* Ones count */
748              $$ = gen_ctpop_op(c, &@1, &$3);
749          }
750        | EXTRACT '(' rvalue ',' rvalue ')'
751          {
752              @1.last_column = @6.last_column;
753              $$ = gen_extract_op(c, &@1, &$5, &$3, &$1);
754          }
755        | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')'
756          {
757              @1.last_column = @8.last_column;
758              yyassert(c, &@1, $5.type == IMMEDIATE &&
759                       $5.imm.type == VALUE &&
760                       $7.type == IMMEDIATE &&
761                       $7.imm.type == VALUE,
762                       "Range extract needs immediate values!\n");
763              $$ = gen_rextract_op(c,
764                                   &@1,
765                                   &$3,
766                                   $7.imm.value,
767                                   $5.imm.value - $7.imm.value + 1);
768          }
769        | CAST4_8U '(' rvalue ')'
770          {
771              @1.last_column = @4.last_column;
772              $$ = gen_rvalue_truncate(c, &@1, &$3);
773              $$.signedness = UNSIGNED;
774              $$ = rvalue_materialize(c, &@1, &$$);
775              $$ = gen_rvalue_extend(c, &@1, &$$);
776          }
777        | BREV '(' rvalue ')'
778          {
779              @1.last_column = @4.last_column;
780              $$ = gen_rvalue_brev(c, &@1, &$3);
781          }
782        | ROTL '(' rvalue ',' rvalue ')'
783          {
784              @1.last_column = @6.last_column;
785              $$ = gen_rotl(c, &@1, &$3, &$5);
786          }
787        | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')'
788          {
789              @1.last_column = @8.last_column;
790              gen_addsat64(c, &@1, &$3, &$5, &$7);
791          }
792        | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')'
793          {
794              @1.last_column = @8.last_column;
795              $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7);
796          }
797        | LSBNEW '(' rvalue ')'
798          {
799              @1.last_column = @4.last_column;
800              HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED);
801              $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one);
802          }
803        ;
804 
805 lvalue : FAIL
806          {
807              @1.last_column = @1.last_column;
808              yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\n");
809          }
810        | REG
811          {
812              $$ = $1;
813          }
814        | var
815          {
816              $$ = $1;
817          }
818        ;
819 
820 %%
821 
822 int main(int argc, char **argv)
823 {
824     if (argc != 5) {
825         fprintf(stderr,
826                 "Semantics: Hexagon ISA to tinycode generator compiler\n\n");
827         fprintf(stderr,
828                 "Usage: ./semantics IDEFS EMITTER_C EMITTER_H "
829                 "ENABLED_INSTRUCTIONS_LIST\n");
830         return 1;
831     }
832 
833     enum {
834         ARG_INDEX_ARGV0 = 0,
835         ARG_INDEX_IDEFS,
836         ARG_INDEX_EMITTER_C,
837         ARG_INDEX_EMITTER_H,
838         ARG_INDEX_ENABLED_INSTRUCTIONS_LIST
839     };
840 
841     FILE *enabled_file = fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST], "w");
842 
843     FILE *output_file = fopen(argv[ARG_INDEX_EMITTER_C], "w");
844     fputs("#include \"qemu/osdep.h\"\n", output_file);
845     fputs("#include \"qemu/log.h\"\n", output_file);
846     fputs("#include \"cpu.h\"\n", output_file);
847     fputs("#include \"internal.h\"\n", output_file);
848     fputs("#include \"tcg/tcg-op.h\"\n", output_file);
849     fputs("#include \"insn.h\"\n", output_file);
850     fputs("#include \"opcodes.h\"\n", output_file);
851     fputs("#include \"translate.h\"\n", output_file);
852     fputs("#define QEMU_GENERATE\n", output_file);
853     fputs("#include \"genptr.h\"\n", output_file);
854     fputs("#include \"tcg/tcg.h\"\n", output_file);
855     fputs("#include \"macros.h\"\n", output_file);
856     fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]);
857 
858     FILE *defines_file = fopen(argv[ARG_INDEX_EMITTER_H], "w");
859     assert(defines_file != NULL);
860     fputs("#ifndef HEX_EMITTER_H\n", defines_file);
861     fputs("#define HEX_EMITTER_H\n", defines_file);
862     fputs("\n", defines_file);
863     fputs("#include \"insn.h\"\n\n", defines_file);
864 
865     /* Parser input file */
866     Context context = { 0 };
867     context.defines_file = defines_file;
868     context.output_file = output_file;
869     context.enabled_file = enabled_file;
870     /* Initialize buffers */
871     context.out_str = g_string_new(NULL);
872     context.signature_str = g_string_new(NULL);
873     context.header_str = g_string_new(NULL);
874     context.ternary = g_array_new(FALSE, TRUE, sizeof(Ternary));
875     /* Read input file */
876     FILE *input_file = fopen(argv[ARG_INDEX_IDEFS], "r");
877     fseek(input_file, 0L, SEEK_END);
878     long input_size = ftell(input_file);
879     context.input_buffer = (char *) calloc(input_size + 1, sizeof(char));
880     fseek(input_file, 0L, SEEK_SET);
881     size_t read_chars = fread(context.input_buffer,
882                               sizeof(char),
883                               input_size,
884                               input_file);
885     if (read_chars != (size_t) input_size) {
886         fprintf(stderr, "Error: an error occurred while reading input file!\n");
887         return -1;
888     }
889     yylex_init(&context.scanner);
890     YY_BUFFER_STATE buffer;
891     buffer = yy_scan_string(context.input_buffer, context.scanner);
892     /* Start the parsing procedure */
893     yyparse(context.scanner, &context);
894     if (context.implemented_insn != context.total_insn) {
895         fprintf(stderr,
896                 "Warning: %d/%d meta instructions have been implemented!\n",
897                 context.implemented_insn,
898                 context.total_insn);
899     }
900     fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n",
901           defines_file);
902     /* Cleanup */
903     yy_delete_buffer(buffer, context.scanner);
904     yylex_destroy(context.scanner);
905     free(context.input_buffer);
906     g_string_free(context.out_str, TRUE);
907     g_string_free(context.signature_str, TRUE);
908     g_string_free(context.header_str, TRUE);
909     g_array_free(context.ternary, TRUE);
910     fclose(output_file);
911     fclose(input_file);
912     fclose(defines_file);
913     fclose(enabled_file);
914 
915     return 0;
916 }
917