1 /*
2  *  Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <assert.h>
19 #include <inttypes.h>
20 #include <stdarg.h>
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include "idef-parser.h"
29 #include "parser-helpers.h"
30 #include "idef-parser.tab.h"
31 #include "idef-parser.yy.h"
32 
yyerror(YYLTYPE * locp,yyscan_t scanner,Context * c,const char * s)33 void yyerror(YYLTYPE *locp,
34              yyscan_t scanner __attribute__((unused)),
35              Context *c,
36              const char *s)
37 {
38     const char *code_ptr = c->input_buffer;
39 
40     fprintf(stderr, "WARNING (%s): '%s'\n", c->inst.name->str, s);
41 
42     fprintf(stderr, "Problematic range: ");
43     for (int i = locp->first_column; i < locp->last_column; i++) {
44         if (code_ptr[i] != '\n') {
45             fprintf(stderr, "%c", code_ptr[i]);
46         }
47     }
48     fprintf(stderr, "\n");
49 
50     for (unsigned i = 0;
51          i < 80 &&
52          code_ptr[locp->first_column - 10 + i] != '\0' &&
53          code_ptr[locp->first_column - 10 + i] != '\n';
54          i++) {
55         fprintf(stderr, "%c", code_ptr[locp->first_column - 10 + i]);
56     }
57     fprintf(stderr, "\n");
58     for (unsigned i = 0; i < 9; i++) {
59         fprintf(stderr, " ");
60     }
61     fprintf(stderr, "^");
62     for (int i = 0; i < (locp->last_column - locp->first_column) - 1; i++) {
63         fprintf(stderr, "~");
64     }
65     fprintf(stderr, "\n");
66     c->inst.error_count++;
67 }
68 
is_direct_predicate(HexValue * value)69 bool is_direct_predicate(HexValue *value)
70 {
71     return value->pred.id >= '0' && value->pred.id <= '3';
72 }
73 
is_inside_ternary(Context * c)74 bool is_inside_ternary(Context *c)
75 {
76     return c->ternary->len > 0;
77 }
78 
79 /* Print functions */
str_print(Context * c,YYLTYPE * locp,const char * string)80 void str_print(Context *c, YYLTYPE *locp, const char *string)
81 {
82     (void) locp;
83     EMIT(c, "%s", string);
84 }
85 
uint8_print(Context * c,YYLTYPE * locp,uint8_t * num)86 void uint8_print(Context *c, YYLTYPE *locp, uint8_t *num)
87 {
88     (void) locp;
89     EMIT(c, "%u", *num);
90 }
91 
uint64_print(Context * c,YYLTYPE * locp,uint64_t * num)92 void uint64_print(Context *c, YYLTYPE *locp, uint64_t *num)
93 {
94     (void) locp;
95     EMIT(c, "%" PRIu64, *num);
96 }
97 
int_print(Context * c,YYLTYPE * locp,int * num)98 void int_print(Context *c, YYLTYPE *locp, int *num)
99 {
100     (void) locp;
101     EMIT(c, "%d", *num);
102 }
103 
uint_print(Context * c,YYLTYPE * locp,unsigned * num)104 void uint_print(Context *c, YYLTYPE *locp, unsigned *num)
105 {
106     (void) locp;
107     EMIT(c, "%u", *num);
108 }
109 
tmp_print(Context * c,YYLTYPE * locp,HexTmp * tmp)110 void tmp_print(Context *c, YYLTYPE *locp, HexTmp *tmp)
111 {
112     (void) locp;
113     EMIT(c, "tmp_%d", tmp->index);
114 }
115 
pred_print(Context * c,YYLTYPE * locp,HexPred * pred,bool is_dotnew)116 void pred_print(Context *c, YYLTYPE *locp, HexPred *pred, bool is_dotnew)
117 {
118     (void) locp;
119     char suffix = is_dotnew ? 'N' : 'V';
120     EMIT(c, "P%c%c", pred->id, suffix);
121 }
122 
reg_compose(Context * c,YYLTYPE * locp,HexReg * reg,char reg_id[5])123 void reg_compose(Context *c, YYLTYPE *locp, HexReg *reg, char reg_id[5])
124 {
125     memset(reg_id, 0, 5 * sizeof(char));
126     switch (reg->type) {
127     case GENERAL_PURPOSE:
128         reg_id[0] = 'R';
129         break;
130     case CONTROL:
131         reg_id[0] = 'C';
132         break;
133     case MODIFIER:
134         reg_id[0] = 'M';
135         break;
136     case DOTNEW:
137         reg_id[0] = 'N';
138         reg_id[1] = reg->id;
139         reg_id[2] = 'N';
140         return;
141     }
142     switch (reg->bit_width) {
143     case 32:
144         reg_id[1] = reg->id;
145         reg_id[2] = 'V';
146         break;
147     case 64:
148         reg_id[1] = reg->id;
149         reg_id[2] = reg->id;
150         reg_id[3] = 'V';
151         break;
152     default:
153         yyassert(c, locp, false, "Unhandled register bit width!\n");
154     }
155 }
156 
reg_arg_print(Context * c,YYLTYPE * locp,HexReg * reg)157 static void reg_arg_print(Context *c, YYLTYPE *locp, HexReg *reg)
158 {
159     char reg_id[5];
160     reg_compose(c, locp, reg, reg_id);
161     EMIT(c, "%s", reg_id);
162 }
163 
reg_print(Context * c,YYLTYPE * locp,HexReg * reg)164 void reg_print(Context *c, YYLTYPE *locp, HexReg *reg)
165 {
166     (void) locp;
167     EMIT(c, "hex_gpr[%u]", reg->id);
168 }
169 
imm_print(Context * c,YYLTYPE * locp,HexValue * rvalue)170 void imm_print(Context *c, YYLTYPE *locp, HexValue *rvalue)
171 {
172     HexImm *imm = &rvalue->imm;
173     switch (imm->type) {
174     case I:
175         EMIT(c, "i");
176         break;
177     case VARIABLE:
178         EMIT(c, "%ciV", imm->id);
179         break;
180     case VALUE:
181         if (rvalue->bit_width == 32) {
182             if (rvalue->signedness == UNSIGNED) {
183                 EMIT(c, "((uint32_t) 0x%" PRIx32 ")", (uint32_t) imm->value);
184             }  else {
185                 EMIT(c, "((int32_t) 0x%" PRIx32 ")", (int32_t) imm->value);
186             }
187         } else if (rvalue->bit_width == 64) {
188             if (rvalue->signedness == UNSIGNED) {
189                 EMIT(c, "((uint64_t) 0x%" PRIx64 "ULL)", (uint64_t) imm->value);
190             } else {
191                 EMIT(c, "((int64_t) 0x%" PRIx64 "LL)", (int64_t) imm->value);
192             }
193         } else {
194             g_assert_not_reached();
195         }
196         break;
197     case QEMU_TMP:
198         EMIT(c, "qemu_tmp_%" PRIu64, imm->index);
199         break;
200     case IMM_PC:
201         EMIT(c, "ctx->base.pc_next");
202         break;
203     case IMM_CONSTEXT:
204         EMIT(c, "insn->extension_valid");
205         break;
206     default:
207         yyassert(c, locp, false, "Cannot print this expression!");
208     }
209 }
210 
var_print(Context * c,YYLTYPE * locp,HexVar * var)211 void var_print(Context *c, YYLTYPE *locp, HexVar *var)
212 {
213     (void) locp;
214     EMIT(c, "%s", var->name->str);
215 }
216 
rvalue_print(Context * c,YYLTYPE * locp,void * pointer)217 void rvalue_print(Context *c, YYLTYPE *locp, void *pointer)
218 {
219   HexValue *rvalue = (HexValue *) pointer;
220   switch (rvalue->type) {
221   case REGISTER:
222       reg_print(c, locp, &rvalue->reg);
223       break;
224   case REGISTER_ARG:
225       reg_arg_print(c, locp, &rvalue->reg);
226       break;
227   case TEMP:
228       tmp_print(c, locp, &rvalue->tmp);
229       break;
230   case IMMEDIATE:
231       imm_print(c, locp, rvalue);
232       break;
233   case VARID:
234       var_print(c, locp, &rvalue->var);
235       break;
236   case PREDICATE:
237       pred_print(c, locp, &rvalue->pred, rvalue->is_dotnew);
238       break;
239   default:
240       yyassert(c, locp, false, "Cannot print this expression!");
241   }
242 }
243 
out_assert(Context * c,YYLTYPE * locp,void * dummy)244 void out_assert(Context *c, YYLTYPE *locp,
245                 void *dummy __attribute__((unused)))
246 {
247     yyassert(c, locp, false, "Unhandled print type!");
248 }
249 
250 /* Copy output code buffer */
commit(Context * c)251 void commit(Context *c)
252 {
253     /* Emit instruction pseudocode */
254     EMIT_SIG(c, "\n" START_COMMENT " ");
255     for (char *x = c->inst.code_begin; x < c->inst.code_end; x++) {
256         EMIT_SIG(c, "%c", *x);
257     }
258     EMIT_SIG(c, " " END_COMMENT "\n");
259 
260     /* Commit instruction code to output file */
261     fwrite(c->signature_str->str, sizeof(char), c->signature_str->len,
262            c->output_file);
263     fwrite(c->header_str->str, sizeof(char), c->header_str->len,
264            c->output_file);
265     fwrite(c->out_str->str, sizeof(char), c->out_str->len,
266            c->output_file);
267 
268     fwrite(c->signature_str->str, sizeof(char), c->signature_str->len,
269            c->defines_file);
270     fprintf(c->defines_file, ";\n");
271 }
272 
gen_c_int_type(Context * c,YYLTYPE * locp,unsigned bit_width,HexSignedness signedness)273 static void gen_c_int_type(Context *c, YYLTYPE *locp, unsigned bit_width,
274                            HexSignedness signedness)
275 {
276     const char *signstr = (signedness == UNSIGNED) ? "u" : "";
277     OUT(c, locp, signstr, "int", &bit_width, "_t");
278 }
279 
gen_constant(Context * c,YYLTYPE * locp,const char * value,unsigned bit_width,HexSignedness signedness)280 static HexValue gen_constant(Context *c,
281                              YYLTYPE *locp,
282                              const char *value,
283                              unsigned bit_width,
284                              HexSignedness signedness)
285 {
286     HexValue rvalue;
287     assert(bit_width == 32 || bit_width == 64);
288     memset(&rvalue, 0, sizeof(HexValue));
289     rvalue.type = TEMP;
290     rvalue.bit_width = bit_width;
291     rvalue.signedness = signedness;
292     rvalue.is_dotnew = false;
293     rvalue.tmp.index = c->inst.tmp_count;
294     OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count,
295         " = tcg_constant_i", &bit_width, "(", value, ");\n");
296     c->inst.tmp_count++;
297     return rvalue;
298 }
299 
300 /* Temporary values creation */
gen_tmp(Context * c,YYLTYPE * locp,unsigned bit_width,HexSignedness signedness)301 HexValue gen_tmp(Context *c,
302                  YYLTYPE *locp,
303                  unsigned bit_width,
304                  HexSignedness signedness)
305 {
306     HexValue rvalue;
307     assert(bit_width == 32 || bit_width == 64);
308     memset(&rvalue, 0, sizeof(HexValue));
309     rvalue.type = TEMP;
310     rvalue.bit_width = bit_width;
311     rvalue.signedness = signedness;
312     rvalue.is_dotnew = false;
313     rvalue.tmp.index = c->inst.tmp_count;
314     OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count,
315         " = tcg_temp_new_i", &bit_width, "();\n");
316     c->inst.tmp_count++;
317     return rvalue;
318 }
319 
gen_constant_from_imm(Context * c,YYLTYPE * locp,HexValue * value)320 static HexValue gen_constant_from_imm(Context *c,
321                                       YYLTYPE *locp,
322                                       HexValue *value)
323 {
324     HexValue rvalue;
325     assert(value->type == IMMEDIATE);
326     memset(&rvalue, 0, sizeof(HexValue));
327     rvalue.type = TEMP;
328     rvalue.bit_width = value->bit_width;
329     rvalue.signedness = value->signedness;
330     rvalue.is_dotnew = false;
331     rvalue.tmp.index = c->inst.tmp_count;
332     /*
333      * Here we output the call to `tcg_constant_i<width>` in
334      * order to create the temporary value. Note, that we
335      * add a cast
336      *
337      *   `tcg_constant_i<width>`((int<width>_t) ...)`
338      *
339      * This cast is required to avoid implicit integer
340      * conversion warnings since all immediates are
341      * output as `((int64_t) 123ULL)`, even if the
342      * integer is 32-bit.
343      */
344     OUT(c, locp, "TCGv_i", &rvalue.bit_width, " tmp_", &c->inst.tmp_count);
345     OUT(c, locp, " = tcg_constant_i", &rvalue.bit_width,
346         "((int", &rvalue.bit_width, "_t) (", value, "));\n");
347 
348     c->inst.tmp_count++;
349     return rvalue;
350 }
351 
gen_imm_value(Context * c,YYLTYPE * locp,int value,unsigned bit_width,HexSignedness signedness)352 HexValue gen_imm_value(Context *c __attribute__((unused)),
353                        YYLTYPE *locp,
354                        int value,
355                        unsigned bit_width,
356                        HexSignedness signedness)
357 {
358     (void) locp;
359     HexValue rvalue;
360     assert(bit_width == 32 || bit_width == 64);
361     memset(&rvalue, 0, sizeof(HexValue));
362     rvalue.type = IMMEDIATE;
363     rvalue.bit_width = bit_width;
364     rvalue.signedness = signedness;
365     rvalue.is_dotnew = false;
366     rvalue.imm.type = VALUE;
367     rvalue.imm.value = value;
368     return rvalue;
369 }
370 
gen_imm_qemu_tmp(Context * c,YYLTYPE * locp,unsigned bit_width,HexSignedness signedness)371 HexValue gen_imm_qemu_tmp(Context *c, YYLTYPE *locp, unsigned bit_width,
372                           HexSignedness signedness)
373 {
374     (void) locp;
375     HexValue rvalue;
376     assert(bit_width == 32 || bit_width == 64);
377     memset(&rvalue, 0, sizeof(HexValue));
378     rvalue.type = IMMEDIATE;
379     rvalue.is_dotnew = false;
380     rvalue.bit_width = bit_width;
381     rvalue.signedness = signedness;
382     rvalue.imm.type = QEMU_TMP;
383     rvalue.imm.index = c->inst.qemu_tmp_count++;
384     return rvalue;
385 }
386 
rvalue_materialize(Context * c,YYLTYPE * locp,HexValue * rvalue)387 HexValue rvalue_materialize(Context *c, YYLTYPE *locp, HexValue *rvalue)
388 {
389     if (rvalue->type == IMMEDIATE) {
390         return gen_constant_from_imm(c, locp, rvalue);
391     }
392     return *rvalue;
393 }
394 
gen_rvalue_extend(Context * c,YYLTYPE * locp,HexValue * rvalue)395 HexValue gen_rvalue_extend(Context *c, YYLTYPE *locp, HexValue *rvalue)
396 {
397     assert_signedness(c, locp, rvalue->signedness);
398     if (rvalue->bit_width > 32) {
399         return *rvalue;
400     }
401 
402     if (rvalue->type == IMMEDIATE) {
403         HexValue res = gen_imm_qemu_tmp(c, locp, 64, rvalue->signedness);
404         gen_c_int_type(c, locp, 64, rvalue->signedness);
405         OUT(c, locp, " ", &res, " = (");
406         gen_c_int_type(c, locp, 64, rvalue->signedness);
407         OUT(c, locp, ")", rvalue, ";\n");
408         return res;
409     } else {
410         HexValue res = gen_tmp(c, locp, 64, rvalue->signedness);
411         bool is_unsigned = (rvalue->signedness == UNSIGNED);
412         const char *sign_suffix = is_unsigned ? "u" : "";
413         OUT(c, locp, "tcg_gen_ext", sign_suffix,
414             "_i32_i64(", &res, ", ", rvalue, ");\n");
415         return res;
416     }
417 }
418 
gen_rvalue_truncate(Context * c,YYLTYPE * locp,HexValue * rvalue)419 HexValue gen_rvalue_truncate(Context *c, YYLTYPE *locp, HexValue *rvalue)
420 {
421     if (rvalue->type == IMMEDIATE) {
422         HexValue res = *rvalue;
423         res.bit_width = 32;
424         return res;
425     } else {
426         if (rvalue->bit_width == 64) {
427             HexValue res = gen_tmp(c, locp, 32, rvalue->signedness);
428             OUT(c, locp, "tcg_gen_trunc_i64_tl(", &res, ", ", rvalue, ");\n");
429             return res;
430         }
431     }
432     return *rvalue;
433 }
434 
435 /*
436  * Attempts to lookup the `Var` struct associated with the given `varid`.
437  * The `dst` argument is populated with the found name, bit_width, and
438  * signedness, given that `dst` is non-NULL. Returns true if the lookup
439  * succeeded and false otherwise.
440  */
try_find_variable(Context * c,YYLTYPE * locp,HexValue * dst,HexValue * varid)441 static bool try_find_variable(Context *c, YYLTYPE *locp,
442                               HexValue *dst,
443                               HexValue *varid)
444 {
445     yyassert(c, locp, varid, "varid to lookup is NULL");
446     yyassert(c, locp, varid->type == VARID,
447              "Can only lookup variables by varid");
448     for (unsigned i = 0; i < c->inst.allocated->len; i++) {
449         Var *curr = &g_array_index(c->inst.allocated, Var, i);
450         if (g_string_equal(varid->var.name, curr->name)) {
451             if (dst) {
452                 dst->var.name = curr->name;
453                 dst->bit_width = curr->bit_width;
454                 dst->signedness = curr->signedness;
455             }
456             return true;
457         }
458     }
459     return false;
460 }
461 
462 /* Calls `try_find_variable` and asserts success. */
find_variable(Context * c,YYLTYPE * locp,HexValue * dst,HexValue * varid)463 static void find_variable(Context *c, YYLTYPE *locp,
464                           HexValue *dst,
465                           HexValue *varid)
466 {
467     bool found = try_find_variable(c, locp, dst, varid);
468     yyassert(c, locp, found, "Use of undeclared variable!\n");
469 }
470 
471 /* Handle signedness, if both unsigned -> result is unsigned, else signed */
bin_op_signedness(Context * c,YYLTYPE * locp,HexSignedness sign1,HexSignedness sign2)472 static inline HexSignedness bin_op_signedness(Context *c, YYLTYPE *locp,
473                                               HexSignedness sign1,
474                                               HexSignedness sign2)
475 {
476     assert_signedness(c, locp, sign1);
477     assert_signedness(c, locp, sign2);
478     return (sign1 == UNSIGNED && sign2 == UNSIGNED) ? UNSIGNED : SIGNED;
479 }
480 
gen_varid_allocate(Context * c,YYLTYPE * locp,HexValue * varid,unsigned bit_width,HexSignedness signedness)481 void gen_varid_allocate(Context *c,
482                         YYLTYPE *locp,
483                         HexValue *varid,
484                         unsigned bit_width,
485                         HexSignedness signedness)
486 {
487     const char *bit_suffix = (bit_width == 64) ? "i64" : "i32";
488     bool found = try_find_variable(c, locp, NULL, varid);
489     Var new_var;
490 
491     memset(&new_var, 0, sizeof(Var));
492 
493     yyassert(c, locp, !found, "Redeclaration of variables not allowed!");
494     assert_signedness(c, locp, signedness);
495 
496     /* `varid` only carries name information */
497     new_var.name = varid->var.name;
498     new_var.bit_width = bit_width;
499     new_var.signedness = signedness;
500 
501     EMIT_HEAD(c, "TCGv_%s %s", bit_suffix, varid->var.name->str);
502     EMIT_HEAD(c, " = tcg_temp_new_%s();\n", bit_suffix);
503     g_array_append_val(c->inst.allocated, new_var);
504 }
505 
506 enum OpTypes {
507     IMM_IMM = 0,
508     IMM_REG = 1,
509     REG_IMM = 2,
510     REG_REG = 3,
511 };
512 
gen_bin_cmp(Context * c,YYLTYPE * locp,TCGCond type,HexValue * op1,HexValue * op2)513 HexValue gen_bin_cmp(Context *c,
514                      YYLTYPE *locp,
515                      TCGCond type,
516                      HexValue *op1,
517                      HexValue *op2)
518 {
519     HexValue op1_m = *op1;
520     HexValue op2_m = *op2;
521     enum OpTypes op_types = (op1_m.type != IMMEDIATE) << 1
522                             | (op2_m.type != IMMEDIATE);
523 
524     bool op_is64bit = op1_m.bit_width == 64 || op2_m.bit_width == 64;
525     const char *bit_suffix = op_is64bit ? "i64" : "i32";
526     unsigned bit_width = (op_is64bit) ? 64 : 32;
527     HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED);
528 
529     /* Extend to 64-bits, if required */
530     if (op_is64bit) {
531         op1_m = gen_rvalue_extend(c, locp, &op1_m);
532         op2_m = gen_rvalue_extend(c, locp, &op2_m);
533     }
534 
535     switch (op_types) {
536     case IMM_IMM:
537     case IMM_REG:
538         yyassert(c, locp, false, "Binary comparisons between IMM op IMM and"
539                                  "IMM op REG not handled!");
540         break;
541     case REG_IMM:
542         OUT(c, locp, "tcg_gen_setcondi_", bit_suffix, "(");
543         OUT(c, locp, cond_to_str(type), ", ", &res, ", ", &op1_m, ", ", &op2_m,
544             ");\n");
545         break;
546     case REG_REG:
547         OUT(c, locp, "tcg_gen_setcond_", bit_suffix, "(");
548         OUT(c, locp, cond_to_str(type), ", ", &res, ", ", &op1_m, ", ", &op2_m,
549             ");\n");
550         break;
551     default:
552         fprintf(stderr, "Error in evaluating immediateness!");
553         abort();
554     }
555     return res;
556 }
557 
gen_simple_op(Context * c,YYLTYPE * locp,unsigned bit_width,const char * bit_suffix,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2,const char * imm_imm,const char * imm_reg,const char * reg_imm,const char * reg_reg)558 static void gen_simple_op(Context *c, YYLTYPE *locp, unsigned bit_width,
559                           const char *bit_suffix, HexValue *res,
560                           enum OpTypes op_types,
561                           HexValue *op1,
562                           HexValue *op2,
563                           const char *imm_imm,
564                           const char *imm_reg,
565                           const char *reg_imm,
566                           const char *reg_reg)
567 {
568     switch (op_types) {
569     case IMM_IMM: {
570         HexSignedness signedness = bin_op_signedness(c, locp,
571                                                      op1->signedness,
572                                                      op2->signedness);
573         gen_c_int_type(c, locp, bit_width, signedness);
574         OUT(c, locp, " ", res,
575             " = ", op1, imm_imm, op2, ";\n");
576     } break;
577     case IMM_REG:
578         OUT(c, locp, imm_reg, bit_suffix,
579             "(", res, ", ", op2, ", ", op1, ");\n");
580         break;
581     case REG_IMM:
582         OUT(c, locp, reg_imm, bit_suffix,
583             "(", res, ", ", op1, ", ", op2, ");\n");
584         break;
585     case REG_REG:
586         OUT(c, locp, reg_reg, bit_suffix,
587             "(", res, ", ", op1, ", ", op2, ");\n");
588         break;
589     }
590 }
591 
gen_sub_op(Context * c,YYLTYPE * locp,unsigned bit_width,const char * bit_suffix,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2)592 static void gen_sub_op(Context *c, YYLTYPE *locp, unsigned bit_width,
593                        const char *bit_suffix, HexValue *res,
594                        enum OpTypes op_types, HexValue *op1,
595                        HexValue *op2)
596 {
597     switch (op_types) {
598     case IMM_IMM: {
599         HexSignedness signedness = bin_op_signedness(c, locp,
600                                                      op1->signedness,
601                                                      op2->signedness);
602         gen_c_int_type(c, locp, bit_width, signedness);
603         OUT(c, locp, " ", res,
604             " = ", op1, " - ", op2, ";\n");
605     } break;
606     case IMM_REG: {
607         OUT(c, locp, "tcg_gen_subfi_", bit_suffix,
608             "(", res, ", ", op1, ", ", op2, ");\n");
609     } break;
610     case REG_IMM: {
611         OUT(c, locp, "tcg_gen_subi_", bit_suffix,
612             "(", res, ", ", op1, ", ", op2, ");\n");
613     } break;
614     case REG_REG: {
615         OUT(c, locp, "tcg_gen_sub_", bit_suffix,
616             "(", res, ", ", op1, ", ", op2, ");\n");
617     } break;
618     }
619 }
620 
gen_asl_op(Context * c,YYLTYPE * locp,unsigned bit_width,bool op_is64bit,const char * bit_suffix,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2)621 static void gen_asl_op(Context *c, YYLTYPE *locp, unsigned bit_width,
622                        bool op_is64bit, const char *bit_suffix,
623                        HexValue *res, enum OpTypes op_types,
624                        HexValue *op1, HexValue *op2)
625 {
626     HexValue op1_m = *op1;
627     HexValue op2_m = *op2;
628     switch (op_types) {
629     case IMM_IMM: {
630         HexSignedness signedness = bin_op_signedness(c, locp,
631                                                      op1->signedness,
632                                                      op2->signedness);
633         gen_c_int_type(c, locp, bit_width, signedness);
634         OUT(c, locp, " ", res,
635             " = ", op1, " << ", op2, ";\n");
636     } break;
637     case REG_IMM: {
638         OUT(c, locp, "if (", op2, " >= ", &bit_width, ") {\n");
639         OUT(c, locp, "tcg_gen_movi_", bit_suffix, "(", res, ", 0);\n");
640         OUT(c, locp, "} else {\n");
641         OUT(c, locp, "tcg_gen_shli_", bit_suffix,
642                 "(", res, ", ", op1, ", ", op2, ");\n");
643         OUT(c, locp, "}\n");
644     } break;
645     case IMM_REG:
646         op1_m.bit_width = bit_width;
647         op1_m = rvalue_materialize(c, locp, &op1_m);
648         /* fallthrough */
649     case REG_REG: {
650         OUT(c, locp, "tcg_gen_shl_", bit_suffix,
651             "(", res, ", ", &op1_m, ", ", op2, ");\n");
652     } break;
653     }
654     if (op_types == IMM_REG || op_types == REG_REG) {
655         /*
656          * Handle left shift by 64/32 which hexagon-sim expects to clear out
657          * register
658          */
659         HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED);
660         HexValue edge = gen_imm_value(c, locp, bit_width, bit_width, UNSIGNED);
661         edge = rvalue_materialize(c, locp, &edge);
662         if (op_is64bit) {
663             op2_m = gen_rvalue_extend(c, locp, &op2_m);
664         }
665         op1_m = rvalue_materialize(c, locp, &op1_m);
666         op2_m = rvalue_materialize(c, locp, &op2_m);
667         OUT(c, locp, "tcg_gen_movcond_i", &bit_width);
668         OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2_m, ", ", &edge);
669         OUT(c, locp, ", ", &zero, ", ", res, ");\n");
670     }
671 }
672 
gen_asr_op(Context * c,YYLTYPE * locp,unsigned bit_width,bool op_is64bit,const char * bit_suffix,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2)673 static void gen_asr_op(Context *c, YYLTYPE *locp, unsigned bit_width,
674                        bool op_is64bit, const char *bit_suffix,
675                        HexValue *res, enum OpTypes op_types,
676                        HexValue *op1, HexValue *op2)
677 {
678     HexValue op1_m = *op1;
679     HexValue op2_m = *op2;
680     switch (op_types) {
681     case IMM_IMM:
682     case IMM_REG:
683         yyassert(c, locp, false, "ASR between IMM op IMM, and IMM op REG"
684                                  " not handled!");
685         break;
686     case REG_IMM: {
687         HexSignedness signedness = bin_op_signedness(c, locp,
688                                                      op1->signedness,
689                                                      op2->signedness);
690         OUT(c, locp, "{\n");
691         gen_c_int_type(c, locp, bit_width, signedness);
692         OUT(c, locp, " shift = ", op2, ";\n");
693         OUT(c, locp, "if (", op2, " >= ", &bit_width, ") {\n");
694         OUT(c, locp, "    shift = ", &bit_width, " - 1;\n");
695         OUT(c, locp, "}\n");
696         OUT(c, locp, "tcg_gen_sari_", bit_suffix,
697             "(", res, ", ", op1, ", shift);\n}\n");
698     } break;
699     case REG_REG:
700         OUT(c, locp, "tcg_gen_sar_", bit_suffix,
701             "(", res, ", ", &op1_m, ", ", op2, ");\n");
702         break;
703     }
704     if (op_types == REG_REG) {
705         /* Handle right shift by values >= bit_width */
706         const char *offset = op_is64bit ? "63" : "31";
707         HexValue tmp = gen_tmp(c, locp, bit_width, SIGNED);
708         HexValue zero = gen_constant(c, locp, "0", bit_width, SIGNED);
709         HexValue edge = gen_imm_value(c, locp, bit_width, bit_width, UNSIGNED);
710 
711         edge = rvalue_materialize(c, locp, &edge);
712         if (op_is64bit) {
713             op2_m = gen_rvalue_extend(c, locp, &op2_m);
714         }
715         op1_m = rvalue_materialize(c, locp, &op1_m);
716         op2_m = rvalue_materialize(c, locp, &op2_m);
717 
718         OUT(c, locp, "tcg_gen_extract_", bit_suffix, "(",
719             &tmp, ", ", &op1_m, ", ", offset, ", 1);\n");
720         OUT(c, locp, "tcg_gen_sub_", bit_suffix, "(",
721             &tmp, ", ", &zero, ", ", &tmp, ");\n");
722         OUT(c, locp, "tcg_gen_movcond_i", &bit_width);
723         OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2_m, ", ", &edge);
724         OUT(c, locp, ", ", &tmp, ", ", res, ");\n");
725     }
726 }
727 
gen_lsr_op(Context * c,YYLTYPE * locp,unsigned bit_width,bool op_is64bit,const char * bit_suffix,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2)728 static void gen_lsr_op(Context *c, YYLTYPE *locp, unsigned bit_width,
729                        bool op_is64bit, const char *bit_suffix,
730                        HexValue *res, enum OpTypes op_types,
731                        HexValue *op1, HexValue *op2)
732 {
733     HexValue op1_m = *op1;
734     HexValue op2_m = *op2;
735     switch (op_types) {
736     case IMM_IMM:
737     case IMM_REG:
738         yyassert(c, locp, false, "LSR between IMM op IMM, and IMM op REG"
739                                  " not handled!");
740         break;
741     case REG_IMM:
742         OUT(c, locp, "if (", op2, " >= ", &bit_width, ") {\n");
743         OUT(c, locp, "tcg_gen_movi_", bit_suffix, "(", res, ", 0);\n");
744         OUT(c, locp, "} else {\n");
745         OUT(c, locp, "tcg_gen_shri_", bit_suffix,
746             "(", res, ", ", op1, ", ", op2, ");\n");
747         OUT(c, locp, "}\n");
748         break;
749     case REG_REG:
750         OUT(c, locp, "tcg_gen_shr_", bit_suffix,
751             "(", res, ", ", &op1_m, ", ", op2, ");\n");
752         break;
753     }
754     if (op_types == REG_REG) {
755         /* Handle right shift by values >= bit_width */
756         HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED);
757         HexValue edge = gen_imm_value(c, locp, bit_width, bit_width, UNSIGNED);
758         edge = rvalue_materialize(c, locp, &edge);
759         if (op_is64bit) {
760             op2_m = gen_rvalue_extend(c, locp, &op2_m);
761         }
762         op1_m = rvalue_materialize(c, locp, &op1_m);
763         op2_m = rvalue_materialize(c, locp, &op2_m);
764         OUT(c, locp, "tcg_gen_movcond_i", &bit_width);
765         OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2_m, ", ", &edge);
766         OUT(c, locp, ", ", &zero, ", ", res, ");\n");
767     }
768 }
769 
770 /*
771  * Note: This implementation of logical `and` does not mirror that in C.
772  * We do not short-circuit logical expressions!
773  */
gen_andl_op(Context * c,YYLTYPE * locp,unsigned bit_width,const char * bit_suffix,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2)774 static void gen_andl_op(Context *c, YYLTYPE *locp, unsigned bit_width,
775                         const char *bit_suffix, HexValue *res,
776                         enum OpTypes op_types, HexValue *op1,
777                         HexValue *op2)
778 {
779     (void) bit_width;
780     HexValue tmp1, tmp2;
781     HexValue zero = gen_constant(c, locp, "0", 32, UNSIGNED);
782     memset(&tmp1, 0, sizeof(HexValue));
783     memset(&tmp2, 0, sizeof(HexValue));
784     switch (op_types) {
785     case IMM_IMM:
786     case IMM_REG:
787     case REG_IMM:
788         yyassert(c, locp, false, "ANDL between IMM op IMM, IMM op REG, and"
789                                  " REG op IMM, not handled!");
790         break;
791     case REG_REG:
792         tmp1 = gen_bin_cmp(c, locp, TCG_COND_NE, op1, &zero);
793         tmp2 = gen_bin_cmp(c, locp, TCG_COND_NE, op2, &zero);
794         OUT(c, locp, "tcg_gen_and_", bit_suffix,
795             "(", res, ", ", &tmp1, ", ", &tmp2, ");\n");
796         break;
797     }
798 }
799 
gen_minmax_op(Context * c,YYLTYPE * locp,unsigned bit_width,HexValue * res,enum OpTypes op_types,HexValue * op1,HexValue * op2,bool minmax)800 static void gen_minmax_op(Context *c, YYLTYPE *locp, unsigned bit_width,
801                           HexValue *res, enum OpTypes op_types,
802                           HexValue *op1, HexValue *op2, bool minmax)
803 {
804     const char *mm;
805     HexValue op1_m = *op1;
806     HexValue op2_m = *op2;
807     bool is_unsigned;
808 
809     assert_signedness(c, locp, res->signedness);
810     is_unsigned = res->signedness == UNSIGNED;
811 
812     if (minmax) {
813         /* Max */
814         mm = is_unsigned ? "tcg_gen_umax" : "tcg_gen_smax";
815     } else {
816         /* Min */
817         mm = is_unsigned ? "tcg_gen_umin" : "tcg_gen_smin";
818     }
819     switch (op_types) {
820     case IMM_IMM:
821         yyassert(c, locp, false, "MINMAX between IMM op IMM, not handled!");
822         break;
823     case IMM_REG:
824         op1_m.bit_width = bit_width;
825         op1_m = rvalue_materialize(c, locp, &op1_m);
826         OUT(c, locp, mm, "_i", &bit_width, "(");
827         OUT(c, locp, res, ", ", &op1_m, ", ", op2, ");\n");
828         break;
829     case REG_IMM:
830         op2_m.bit_width = bit_width;
831         op2_m = rvalue_materialize(c, locp, &op2_m);
832         /* Fallthrough */
833     case REG_REG:
834         OUT(c, locp, mm, "_i", &bit_width, "(");
835         OUT(c, locp, res, ", ", op1, ", ", &op2_m, ");\n");
836         break;
837     }
838 }
839 
840 /* Code generation functions */
gen_bin_op(Context * c,YYLTYPE * locp,OpType type,HexValue * op1,HexValue * op2)841 HexValue gen_bin_op(Context *c,
842                     YYLTYPE *locp,
843                     OpType type,
844                     HexValue *op1,
845                     HexValue *op2)
846 {
847     /* Replicate operands to avoid side effects */
848     HexValue op1_m = *op1;
849     HexValue op2_m = *op2;
850     enum OpTypes op_types;
851     bool op_is64bit;
852     HexSignedness signedness;
853     unsigned bit_width;
854     const char *bit_suffix;
855     HexValue res;
856 
857     memset(&res, 0, sizeof(HexValue));
858 
859     /*
860      * If the operands are VARID's we need to look up the
861      * type information.
862      */
863     if (op1_m.type == VARID) {
864         find_variable(c, locp, &op1_m, &op1_m);
865     }
866     if (op2_m.type == VARID) {
867         find_variable(c, locp, &op2_m, &op2_m);
868     }
869 
870     op_types = (op1_m.type != IMMEDIATE) << 1
871                | (op2_m.type != IMMEDIATE);
872     op_is64bit = op1_m.bit_width == 64 || op2_m.bit_width == 64;
873     /* Shift greater than 32 are 64 bits wide */
874 
875     if (type == ASL_OP && op2_m.type == IMMEDIATE &&
876         op2_m.imm.type == VALUE && op2_m.imm.value >= 32) {
877         op_is64bit = true;
878     }
879 
880     bit_width = (op_is64bit) ? 64 : 32;
881     bit_suffix = op_is64bit ? "i64" : "i32";
882 
883     /* Extend to 64-bits, if required */
884     if (op_is64bit) {
885         op1_m = gen_rvalue_extend(c, locp, &op1_m);
886         op2_m = gen_rvalue_extend(c, locp, &op2_m);
887     }
888 
889     signedness = bin_op_signedness(c, locp, op1_m.signedness, op2_m.signedness);
890     if (op_types != IMM_IMM) {
891         res = gen_tmp(c, locp, bit_width, signedness);
892     } else {
893         res = gen_imm_qemu_tmp(c, locp, bit_width, signedness);
894     }
895 
896     switch (type) {
897     case ADD_OP:
898         gen_simple_op(c, locp, bit_width, bit_suffix, &res,
899                       op_types, &op1_m, &op2_m,
900                       " + ",
901                       "tcg_gen_addi_",
902                       "tcg_gen_addi_",
903                       "tcg_gen_add_");
904         break;
905     case SUB_OP:
906         gen_sub_op(c, locp, bit_width, bit_suffix, &res, op_types,
907                    &op1_m, &op2_m);
908         break;
909     case MUL_OP:
910         gen_simple_op(c, locp, bit_width, bit_suffix, &res,
911                       op_types, &op1_m, &op2_m,
912                       " * ",
913                       "tcg_gen_muli_",
914                       "tcg_gen_muli_",
915                       "tcg_gen_mul_");
916         break;
917     case ASL_OP:
918         gen_asl_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_types,
919                    &op1_m, &op2_m);
920         break;
921     case ASR_OP:
922         gen_asr_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_types,
923                    &op1_m, &op2_m);
924         break;
925     case LSR_OP:
926         gen_lsr_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_types,
927                    &op1_m, &op2_m);
928         break;
929     case ANDB_OP:
930         gen_simple_op(c, locp, bit_width, bit_suffix, &res,
931                       op_types, &op1_m, &op2_m,
932                       " & ",
933                       "tcg_gen_andi_",
934                       "tcg_gen_andi_",
935                       "tcg_gen_and_");
936         break;
937     case ORB_OP:
938         gen_simple_op(c, locp, bit_width, bit_suffix, &res,
939                       op_types, &op1_m, &op2_m,
940                       " | ",
941                       "tcg_gen_ori_",
942                       "tcg_gen_ori_",
943                       "tcg_gen_or_");
944         break;
945     case XORB_OP:
946         gen_simple_op(c, locp, bit_width, bit_suffix, &res,
947                       op_types, &op1_m, &op2_m,
948                       " ^ ",
949                       "tcg_gen_xori_",
950                       "tcg_gen_xori_",
951                       "tcg_gen_xor_");
952         break;
953     case ANDL_OP:
954         gen_andl_op(c, locp, bit_width, bit_suffix, &res, op_types, &op1_m,
955                     &op2_m);
956         break;
957     case MINI_OP:
958         gen_minmax_op(c, locp, bit_width, &res, op_types, &op1_m, &op2_m,
959                       false);
960         break;
961     case MAXI_OP:
962         gen_minmax_op(c, locp, bit_width, &res, op_types, &op1_m, &op2_m, true);
963         break;
964     }
965     return res;
966 }
967 
gen_cast_op(Context * c,YYLTYPE * locp,HexValue * src,unsigned target_width,HexSignedness signedness)968 HexValue gen_cast_op(Context *c,
969                      YYLTYPE *locp,
970                      HexValue *src,
971                      unsigned target_width,
972                      HexSignedness signedness)
973 {
974     HexValue res;
975     assert_signedness(c, locp, src->signedness);
976     if (src->bit_width == target_width) {
977         res = *src;
978     } else if (src->bit_width < target_width) {
979         res = gen_rvalue_extend(c, locp, src);
980     } else {
981         /* src->bit_width > target_width */
982         res = gen_rvalue_truncate(c, locp, src);
983     }
984     res.signedness = signedness;
985     return res;
986 }
987 
988 
989 /*
990  * Implements an extension when the `src_width` is an immediate.
991  * If the `value` to extend is also an immediate we use `extract/sextract`
992  * from QEMU `bitops.h`. If `value` is a TCGv then we rely on
993  * `tcg_gen_extract/tcg_gen_sextract`.
994  */
gen_extend_imm_width_op(Context * c,YYLTYPE * locp,HexValue * src_width,unsigned dst_width,HexValue * value,HexSignedness signedness)995 static HexValue gen_extend_imm_width_op(Context *c,
996                                         YYLTYPE *locp,
997                                         HexValue *src_width,
998                                         unsigned dst_width,
999                                         HexValue *value,
1000                                         HexSignedness signedness)
1001 {
1002     /*
1003      * If the source width is not an immediate value, we need to guard
1004      * our extend op with if statements to handle the case where
1005      * `src_width_m` is 0.
1006      */
1007     const char *sign_prefix;
1008     bool need_guarding;
1009 
1010     assert_signedness(c, locp, signedness);
1011     assert(dst_width == 64 || dst_width == 32);
1012     assert(src_width->type == IMMEDIATE);
1013 
1014     sign_prefix = (signedness == UNSIGNED) ? "" : "s";
1015     need_guarding = (src_width->imm.type != VALUE);
1016 
1017     if (src_width->imm.type == VALUE &&
1018         src_width->imm.value == 0) {
1019         /*
1020          * We can bail out early if the source width is known to be zero
1021          * at translation time.
1022          */
1023         return gen_imm_value(c, locp, 0, dst_width, signedness);
1024     }
1025 
1026     if (value->type == IMMEDIATE) {
1027         /*
1028          * If both the value and source width are immediates,
1029          * we can perform the extension at translation time
1030          * using QEMUs bitops.
1031          */
1032         HexValue res = gen_imm_qemu_tmp(c, locp, dst_width, signedness);
1033         gen_c_int_type(c, locp, dst_width, signedness);
1034         OUT(c, locp, " ", &res, " = 0;\n");
1035         if (need_guarding) {
1036             OUT(c, locp, "if (", src_width, " != 0) {\n");
1037         }
1038         OUT(c, locp, &res, " = ", sign_prefix, "extract", &dst_width);
1039         OUT(c, locp, "(", value, ", 0, ", src_width, ");\n");
1040         if (need_guarding) {
1041             OUT(c, locp, "}\n");
1042         }
1043         return res;
1044     } else {
1045         /*
1046          * If the source width is an immediate and the value to
1047          * extend is a TCGv, then use tcg_gen_extract/tcg_gen_sextract
1048          */
1049         HexValue res = gen_tmp(c, locp, dst_width, signedness);
1050 
1051         /*
1052          * If the width is an immediate value we know it is non-zero
1053          * at this point, otherwise we need an if-statement
1054          */
1055         if (need_guarding) {
1056             OUT(c, locp, "if (", src_width, " != 0) {\n");
1057         }
1058         OUT(c, locp, "tcg_gen_", sign_prefix, "extract_i", &dst_width);
1059         OUT(c, locp, "(", &res, ", ", value, ", 0, ", src_width,
1060             ");\n");
1061         if (need_guarding) {
1062             OUT(c, locp, "} else {\n");
1063             OUT(c, locp, "tcg_gen_movi_i", &dst_width, "(", &res,
1064                 ", 0);\n");
1065             OUT(c, locp, "}\n");
1066         }
1067         return res;
1068     }
1069 }
1070 
1071 /*
1072  * Implements an extension when the `src_width` is given by
1073  * a TCGv. Here we need to reimplement the behaviour of
1074  * `tcg_gen_extract` and the like using shifts and masks.
1075  */
gen_extend_tcg_width_op(Context * c,YYLTYPE * locp,HexValue * src_width,unsigned dst_width,HexValue * value,HexSignedness signedness)1076 static HexValue gen_extend_tcg_width_op(Context *c,
1077                                         YYLTYPE *locp,
1078                                         HexValue *src_width,
1079                                         unsigned dst_width,
1080                                         HexValue *value,
1081                                         HexSignedness signedness)
1082 {
1083     HexValue src_width_m = rvalue_materialize(c, locp, src_width);
1084     HexValue zero = gen_constant(c, locp, "0", dst_width, UNSIGNED);
1085     HexValue shift = gen_tmp(c, locp, dst_width, UNSIGNED);
1086     HexValue res;
1087 
1088     assert_signedness(c, locp, signedness);
1089     assert(dst_width == 64 || dst_width == 32);
1090     assert(src_width->type != IMMEDIATE);
1091 
1092     res = gen_tmp(c, locp, dst_width, signedness);
1093 
1094     OUT(c, locp, "tcg_gen_subfi_i", &dst_width);
1095     OUT(c, locp, "(", &shift, ", ", &dst_width, ", ", &src_width_m, ");\n");
1096     if (signedness == UNSIGNED) {
1097         HexValue mask = gen_constant(c, locp, "-1", dst_width, UNSIGNED);
1098         OUT(c, locp, "tcg_gen_shr_i", &dst_width, "(",
1099             &res, ", ", &mask, ", ", &shift, ");\n");
1100         OUT(c, locp, "tcg_gen_and_i", &dst_width, "(",
1101             &res, ", ", &res, ", ", value, ");\n");
1102     } else {
1103         OUT(c, locp, "tcg_gen_shl_i", &dst_width, "(",
1104             &res, ", ", value, ", ", &shift, ");\n");
1105         OUT(c, locp, "tcg_gen_sar_i", &dst_width, "(",
1106             &res, ", ", &res, ", ", &shift, ");\n");
1107     }
1108     OUT(c, locp, "tcg_gen_movcond_i", &dst_width, "(TCG_COND_EQ, ", &res,
1109         ", ");
1110     OUT(c, locp, &src_width_m, ", ", &zero, ", ", &zero, ", ", &res,
1111         ");\n");
1112 
1113     return res;
1114 }
1115 
gen_extend_op(Context * c,YYLTYPE * locp,HexValue * src_width,unsigned dst_width,HexValue * value,HexSignedness signedness)1116 HexValue gen_extend_op(Context *c,
1117                        YYLTYPE *locp,
1118                        HexValue *src_width,
1119                        unsigned dst_width,
1120                        HexValue *value,
1121                        HexSignedness signedness)
1122 {
1123     unsigned bit_width = (dst_width == 64) ? 64 : 32;
1124     HexValue value_m = *value;
1125     HexValue src_width_m = *src_width;
1126 
1127     assert_signedness(c, locp, signedness);
1128     yyassert(c, locp, value_m.bit_width <= bit_width &&
1129                       src_width_m.bit_width <= bit_width,
1130                       "Extending to a size smaller than the current size"
1131                       " makes no sense");
1132 
1133     if (value_m.bit_width < bit_width) {
1134         value_m = gen_rvalue_extend(c, locp, &value_m);
1135     }
1136 
1137     if (src_width_m.bit_width < bit_width) {
1138         src_width_m = gen_rvalue_extend(c, locp, &src_width_m);
1139     }
1140 
1141     if (src_width_m.type == IMMEDIATE) {
1142         return gen_extend_imm_width_op(c, locp, &src_width_m, bit_width,
1143                                        &value_m, signedness);
1144     } else {
1145         return gen_extend_tcg_width_op(c, locp, &src_width_m, bit_width,
1146                                        &value_m, signedness);
1147     }
1148 }
1149 
1150 /*
1151  * Implements `rdeposit` for the special case where `width`
1152  * is of TCGv type. In this case we need to reimplement the behaviour
1153  * of `tcg_gen_deposit*` using binary operations and masks/shifts.
1154  *
1155  * Note: this is the only type of `rdeposit` that occurs, meaning the
1156  * `width` is _NEVER_ of IMMEDIATE type.
1157  */
gen_rdeposit_op(Context * c,YYLTYPE * locp,HexValue * dst,HexValue * value,HexValue * begin,HexValue * width)1158 void gen_rdeposit_op(Context *c,
1159                      YYLTYPE *locp,
1160                      HexValue *dst,
1161                      HexValue *value,
1162                      HexValue *begin,
1163                      HexValue *width)
1164 {
1165     /*
1166      * Otherwise if the width is not known, we fallback on reimplementing
1167      * deposit in TCG.
1168      */
1169     HexValue begin_m = *begin;
1170     HexValue value_m = *value;
1171     HexValue width_m = *width;
1172     const char *mask_str = (dst->bit_width == 32)
1173         ? "0xffffffffUL"
1174         : "0xffffffffffffffffUL";
1175     HexValue mask = gen_constant(c, locp, mask_str, dst->bit_width,
1176                                  UNSIGNED);
1177     const char *dst_width_str = (dst->bit_width == 32) ? "32" : "64";
1178     HexValue k64 = gen_constant(c, locp, dst_width_str, dst->bit_width,
1179                                 UNSIGNED);
1180     HexValue res;
1181     HexValue zero;
1182 
1183     assert(dst->bit_width >= value->bit_width);
1184     assert(begin->type == IMMEDIATE && begin->imm.type == VALUE);
1185     assert(dst->type == REGISTER_ARG);
1186 
1187     yyassert(c, locp, width->type != IMMEDIATE,
1188              "Immediate index to rdeposit not handled!");
1189 
1190     yyassert(c, locp, value_m.bit_width == dst->bit_width &&
1191                       begin_m.bit_width == dst->bit_width &&
1192                       width_m.bit_width == dst->bit_width,
1193                       "Extension/truncation should be taken care of"
1194                       " before rdeposit!");
1195 
1196     width_m = rvalue_materialize(c, locp, &width_m);
1197 
1198     /*
1199      * mask = 0xffffffffffffffff >> (64 - width)
1200      * mask = mask << begin
1201      * value = (value << begin) & mask
1202      * res = dst & ~mask
1203      * res = res | value
1204      * dst = (width != 0) ? res : dst
1205      */
1206     k64 = gen_bin_op(c, locp, SUB_OP, &k64, &width_m);
1207     mask = gen_bin_op(c, locp, LSR_OP, &mask, &k64);
1208     mask = gen_bin_op(c, locp, ASL_OP, &mask, &begin_m);
1209     value_m = gen_bin_op(c, locp, ASL_OP, &value_m, &begin_m);
1210     value_m = gen_bin_op(c, locp, ANDB_OP, &value_m, &mask);
1211 
1212     OUT(c, locp, "tcg_gen_not_i", &dst->bit_width, "(", &mask, ", ",
1213         &mask, ");\n");
1214     res = gen_bin_op(c, locp, ANDB_OP, dst, &mask);
1215     res = gen_bin_op(c, locp, ORB_OP, &res, &value_m);
1216 
1217     /*
1218      * We don't need to truncate `res` here, since all operations involved use
1219      * the same bit width.
1220      */
1221 
1222     /* If the width is zero, then return the identity dst = dst */
1223     zero = gen_constant(c, locp, "0", res.bit_width, UNSIGNED);
1224     OUT(c, locp, "tcg_gen_movcond_i", &res.bit_width, "(TCG_COND_NE, ",
1225         dst);
1226     OUT(c, locp, ", ", &width_m, ", ", &zero, ", ", &res, ", ", dst,
1227         ");\n");
1228 }
1229 
gen_deposit_op(Context * c,YYLTYPE * locp,HexValue * dst,HexValue * value,HexValue * index,HexCast * cast)1230 void gen_deposit_op(Context *c,
1231                     YYLTYPE *locp,
1232                     HexValue *dst,
1233                     HexValue *value,
1234                     HexValue *index,
1235                     HexCast *cast)
1236 {
1237     HexValue value_m = *value;
1238     unsigned bit_width = (dst->bit_width == 64) ? 64 : 32;
1239     unsigned width = cast->bit_width;
1240 
1241     yyassert(c, locp, index->type == IMMEDIATE,
1242              "Deposit index must be immediate!\n");
1243 
1244     /*
1245      * Using tcg_gen_deposit_i**(dst, dst, ...) requires dst to be
1246      * initialized.
1247      */
1248     gen_inst_init_args(c, locp);
1249 
1250     /* If the destination value is 32, truncate the value, otherwise extend */
1251     if (dst->bit_width != value->bit_width) {
1252         if (bit_width == 32) {
1253             value_m = gen_rvalue_truncate(c, locp, &value_m);
1254         } else {
1255             value_m = gen_rvalue_extend(c, locp, &value_m);
1256         }
1257     }
1258     value_m = rvalue_materialize(c, locp, &value_m);
1259     OUT(c, locp, "tcg_gen_deposit_i", &bit_width, "(", dst, ", ", dst, ", ");
1260     OUT(c, locp, &value_m, ", ", index, " * ", &width, ", ", &width, ");\n");
1261 }
1262 
gen_rextract_op(Context * c,YYLTYPE * locp,HexValue * src,unsigned begin,unsigned width)1263 HexValue gen_rextract_op(Context *c,
1264                          YYLTYPE *locp,
1265                          HexValue *src,
1266                          unsigned begin,
1267                          unsigned width)
1268 {
1269     unsigned bit_width = (src->bit_width == 64) ? 64 : 32;
1270     HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED);
1271     OUT(c, locp, "tcg_gen_extract_i", &bit_width, "(", &res);
1272     OUT(c, locp, ", ", src, ", ", &begin, ", ", &width, ");\n");
1273     return res;
1274 }
1275 
gen_extract_op(Context * c,YYLTYPE * locp,HexValue * src,HexValue * index,HexExtract * extract)1276 HexValue gen_extract_op(Context *c,
1277                         YYLTYPE *locp,
1278                         HexValue *src,
1279                         HexValue *index,
1280                         HexExtract *extract)
1281 {
1282     unsigned bit_width = (src->bit_width == 64) ? 64 : 32;
1283     unsigned width = extract->bit_width;
1284     const char *sign_prefix;
1285     HexValue res;
1286 
1287     yyassert(c, locp, index->type == IMMEDIATE,
1288              "Extract index must be immediate!\n");
1289     assert_signedness(c, locp, extract->signedness);
1290 
1291     sign_prefix = (extract->signedness == UNSIGNED) ? "" : "s";
1292     res = gen_tmp(c, locp, bit_width, extract->signedness);
1293 
1294     OUT(c, locp, "tcg_gen_", sign_prefix, "extract_i", &bit_width,
1295         "(", &res, ", ", src);
1296     OUT(c, locp, ", ", index, " * ", &width, ", ", &width, ");\n");
1297 
1298     /* Some extract operations have bit_width != storage_bit_width */
1299     if (extract->storage_bit_width > bit_width) {
1300         HexValue tmp = gen_tmp(c, locp, extract->storage_bit_width,
1301                                extract->signedness);
1302         const char *sign_suffix = (extract->signedness == UNSIGNED) ? "u" : "";
1303         OUT(c, locp, "tcg_gen_ext", sign_suffix, "_i32_i64(",
1304             &tmp, ", ", &res, ");\n");
1305         res = tmp;
1306     }
1307     return res;
1308 }
1309 
gen_write_reg(Context * c,YYLTYPE * locp,HexValue * reg,HexValue * value)1310 void gen_write_reg(Context *c, YYLTYPE *locp, HexValue *reg, HexValue *value)
1311 {
1312     HexValue value_m = *value;
1313     yyassert(c, locp, reg->type == REGISTER, "reg must be a register!");
1314     value_m = gen_rvalue_truncate(c, locp, &value_m);
1315     value_m = rvalue_materialize(c, locp, &value_m);
1316     OUT(c,
1317         locp,
1318         "gen_log_reg_write(ctx, ", &reg->reg.id, ", ",
1319         &value_m, ");\n");
1320 }
1321 
gen_assign(Context * c,YYLTYPE * locp,HexValue * dst,HexValue * value)1322 void gen_assign(Context *c,
1323                 YYLTYPE *locp,
1324                 HexValue *dst,
1325                 HexValue *value)
1326 {
1327     HexValue value_m = *value;
1328     unsigned bit_width;
1329 
1330     yyassert(c, locp, !is_inside_ternary(c),
1331              "Assign in ternary not allowed!");
1332 
1333     if (dst->type == REGISTER) {
1334         gen_write_reg(c, locp, dst, &value_m);
1335         return;
1336     }
1337 
1338     if (dst->type == VARID) {
1339         find_variable(c, locp, dst, dst);
1340     }
1341     bit_width = dst->bit_width == 64 ? 64 : 32;
1342 
1343     if (bit_width != value_m.bit_width) {
1344         if (bit_width == 64) {
1345             value_m = gen_rvalue_extend(c, locp, &value_m);
1346         } else {
1347             value_m = gen_rvalue_truncate(c, locp, &value_m);
1348         }
1349     }
1350 
1351     const char *imm_suffix = (value_m.type == IMMEDIATE) ? "i" : "";
1352     OUT(c, locp, "tcg_gen_mov", imm_suffix, "_i", &bit_width,
1353         "(", dst, ", ", &value_m, ");\n");
1354 }
1355 
gen_convround(Context * c,YYLTYPE * locp,HexValue * src)1356 HexValue gen_convround(Context *c,
1357                        YYLTYPE *locp,
1358                        HexValue *src)
1359 {
1360     HexValue src_m = *src;
1361     unsigned bit_width = src_m.bit_width;
1362     const char *size = (bit_width == 32) ? "32" : "64";
1363     HexValue res = gen_tmp(c, locp, bit_width, src->signedness);
1364     HexValue mask = gen_constant(c, locp, "0x3", bit_width, UNSIGNED);
1365     HexValue one = gen_constant(c, locp, "1", bit_width, UNSIGNED);
1366     HexValue and;
1367     HexValue src_p1;
1368 
1369     and = gen_bin_op(c, locp, ANDB_OP, &src_m, &mask);
1370     src_p1 = gen_bin_op(c, locp, ADD_OP, &src_m, &one);
1371 
1372     OUT(c, locp, "tcg_gen_movcond_i", size, "(TCG_COND_EQ, ", &res);
1373     OUT(c, locp, ", ", &and, ", ", &mask, ", ");
1374     OUT(c, locp, &src_p1, ", ", &src_m, ");\n");
1375 
1376     return res;
1377 }
1378 
gen_convround_n_b(Context * c,YYLTYPE * locp,HexValue * a,HexValue * n)1379 static HexValue gen_convround_n_b(Context *c,
1380                                   YYLTYPE *locp,
1381                                   HexValue *a,
1382                                   HexValue *n)
1383 {
1384     HexValue one = gen_constant(c, locp, "1", 32, UNSIGNED);
1385     HexValue res = gen_tmp(c, locp, 64, UNSIGNED);
1386     HexValue tmp = gen_tmp(c, locp, 32, UNSIGNED);
1387     HexValue tmp_64 = gen_tmp(c, locp, 64, UNSIGNED);
1388 
1389     assert(n->type != IMMEDIATE);
1390     OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n");
1391     OUT(c, locp, "tcg_gen_shl_i32(", &tmp);
1392     OUT(c, locp, ", ", &one, ", ", n, ");\n");
1393     OUT(c, locp, "tcg_gen_and_i32(", &tmp);
1394     OUT(c, locp, ", ", &tmp, ", ", a, ");\n");
1395     OUT(c, locp, "tcg_gen_shri_i32(", &tmp);
1396     OUT(c, locp, ", ", &tmp, ", 1);\n");
1397     OUT(c, locp, "tcg_gen_ext_i32_i64(", &tmp_64, ", ", &tmp, ");\n");
1398     OUT(c, locp, "tcg_gen_add_i64(", &res);
1399     OUT(c, locp, ", ", &res, ", ", &tmp_64, ");\n");
1400 
1401     return res;
1402 }
1403 
gen_convround_n_c(Context * c,YYLTYPE * locp,HexValue * a,HexValue * n)1404 static HexValue gen_convround_n_c(Context *c,
1405                                   YYLTYPE *locp,
1406                                   HexValue *a,
1407                                   HexValue *n)
1408 {
1409     HexValue res = gen_tmp(c, locp, 64, UNSIGNED);
1410     HexValue one = gen_constant(c, locp, "1", 32, UNSIGNED);
1411     HexValue tmp = gen_tmp(c, locp, 32, UNSIGNED);
1412     HexValue tmp_64 = gen_tmp(c, locp, 64, UNSIGNED);
1413 
1414     OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n");
1415     OUT(c, locp, "tcg_gen_subi_i32(", &tmp);
1416     OUT(c, locp, ", ", n, ", 1);\n");
1417     OUT(c, locp, "tcg_gen_shl_i32(", &tmp);
1418     OUT(c, locp, ", ", &one, ", ", &tmp, ");\n");
1419     OUT(c, locp, "tcg_gen_ext_i32_i64(", &tmp_64, ", ", &tmp, ");\n");
1420     OUT(c, locp, "tcg_gen_add_i64(", &res);
1421     OUT(c, locp, ", ", &res, ", ", &tmp_64, ");\n");
1422 
1423     return res;
1424 }
1425 
gen_convround_n(Context * c,YYLTYPE * locp,HexValue * src,HexValue * pos)1426 HexValue gen_convround_n(Context *c,
1427                          YYLTYPE *locp,
1428                          HexValue *src,
1429                          HexValue *pos)
1430 {
1431     HexValue zero = gen_constant(c, locp, "0", 64, UNSIGNED);
1432     HexValue l_32 = gen_constant(c, locp, "1", 32, UNSIGNED);
1433     HexValue cond = gen_tmp(c, locp, 32, UNSIGNED);
1434     HexValue cond_64 = gen_tmp(c, locp, 64, UNSIGNED);
1435     HexValue mask = gen_tmp(c, locp, 32, UNSIGNED);
1436     HexValue n_64 = gen_tmp(c, locp, 64, UNSIGNED);
1437     HexValue res = gen_tmp(c, locp, 64, UNSIGNED);
1438     /* If input is 64 bit cast it to 32 */
1439     HexValue src_casted = gen_cast_op(c, locp, src, 32, src->signedness);
1440     HexValue pos_casted = gen_cast_op(c, locp, pos, 32, pos->signedness);
1441     HexValue r1;
1442     HexValue r2;
1443     HexValue r3;
1444 
1445     src_casted = rvalue_materialize(c, locp, &src_casted);
1446     pos_casted = rvalue_materialize(c, locp, &pos_casted);
1447 
1448     /*
1449      * r1, r2, and r3 represent the results of three different branches.
1450      *   - r1 picked if pos_casted == 0
1451      *   - r2 picked if (src_casted & ((1 << (pos_casted - 1)) - 1)) == 0),
1452      *     that is if bits 0, ..., pos_casted-1 are all 0.
1453      *   - r3 picked otherwise.
1454      */
1455     r1 = gen_rvalue_extend(c, locp, &src_casted);
1456     r2 = gen_convround_n_b(c, locp, &src_casted, &pos_casted);
1457     r3 = gen_convround_n_c(c, locp, &src_casted, &pos_casted);
1458 
1459     /*
1460      * Calculate the condition
1461      *   (src_casted & ((1 << (pos_casted - 1)) - 1)) == 0),
1462      * which checks if the bits 0,...,pos-1 are all 0.
1463      */
1464     OUT(c, locp, "tcg_gen_sub_i32(", &mask);
1465     OUT(c, locp, ", ", &pos_casted, ", ", &l_32, ");\n");
1466     OUT(c, locp, "tcg_gen_shl_i32(", &mask);
1467     OUT(c, locp, ", ", &l_32, ", ", &mask, ");\n");
1468     OUT(c, locp, "tcg_gen_sub_i32(", &mask);
1469     OUT(c, locp, ", ", &mask, ", ", &l_32, ");\n");
1470     OUT(c, locp, "tcg_gen_and_i32(", &cond);
1471     OUT(c, locp, ", ", &src_casted, ", ", &mask, ");\n");
1472     OUT(c, locp, "tcg_gen_extu_i32_i64(", &cond_64, ", ", &cond, ");\n");
1473 
1474     OUT(c, locp, "tcg_gen_ext_i32_i64(", &n_64, ", ", &pos_casted, ");\n");
1475 
1476     /*
1477      * if the bits 0, ..., pos_casted-1 are all 0, then pick r2 otherwise,
1478      * pick r3.
1479      */
1480     OUT(c, locp, "tcg_gen_movcond_i64");
1481     OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &cond_64, ", ", &zero);
1482     OUT(c, locp, ", ", &r2, ", ", &r3, ");\n");
1483 
1484     /* Lastly, if the pos_casted == 0, then pick r1 */
1485     OUT(c, locp, "tcg_gen_movcond_i64");
1486     OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &n_64, ", ", &zero);
1487     OUT(c, locp, ", ", &r1, ", ", &res, ");\n");
1488 
1489     /* Finally shift back val >>= n */
1490     OUT(c, locp, "tcg_gen_shr_i64(", &res);
1491     OUT(c, locp, ", ", &res, ", ", &n_64, ");\n");
1492 
1493     res = gen_rvalue_truncate(c, locp, &res);
1494     return res;
1495 }
1496 
gen_round(Context * c,YYLTYPE * locp,HexValue * src,HexValue * pos)1497 HexValue gen_round(Context *c,
1498                    YYLTYPE *locp,
1499                    HexValue *src,
1500                    HexValue *pos)
1501 {
1502     HexValue zero = gen_constant(c, locp, "0", 64, UNSIGNED);
1503     HexValue one = gen_constant(c, locp, "1", 64, UNSIGNED);
1504     HexValue res;
1505     HexValue n_m1;
1506     HexValue shifted;
1507     HexValue sum;
1508     HexValue src_width;
1509     HexValue a;
1510     HexValue b;
1511 
1512     assert_signedness(c, locp, src->signedness);
1513     yyassert(c, locp, src->bit_width <= 32,
1514              "fRNDN not implemented for bit widths > 32!");
1515 
1516     res = gen_tmp(c, locp, 64, src->signedness);
1517 
1518     src_width = gen_imm_value(c, locp, src->bit_width, 32, UNSIGNED);
1519     a = gen_extend_op(c, locp, &src_width, 64, src, SIGNED);
1520     a = rvalue_materialize(c, locp, &a);
1521 
1522     src_width = gen_imm_value(c, locp, 5, 32, UNSIGNED);
1523     b = gen_extend_op(c, locp, &src_width, 64, pos, UNSIGNED);
1524     b = rvalue_materialize(c, locp, &b);
1525 
1526     n_m1 = gen_bin_op(c, locp, SUB_OP, &b, &one);
1527     shifted = gen_bin_op(c, locp, ASL_OP, &one, &n_m1);
1528     sum = gen_bin_op(c, locp, ADD_OP, &shifted, &a);
1529 
1530     OUT(c, locp, "tcg_gen_movcond_i64");
1531     OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &b, ", ", &zero);
1532     OUT(c, locp, ", ", &a, ", ", &sum, ");\n");
1533 
1534     return res;
1535 }
1536 
1537 /* Circular addressing mode with auto-increment */
gen_circ_op(Context * c,YYLTYPE * locp,HexValue * addr,HexValue * increment,HexValue * modifier)1538 void gen_circ_op(Context *c,
1539                  YYLTYPE *locp,
1540                  HexValue *addr,
1541                  HexValue *increment,
1542                  HexValue *modifier)
1543 {
1544     HexValue increment_m = *increment;
1545     increment_m = rvalue_materialize(c, locp, &increment_m);
1546     OUT(c,
1547         locp,
1548         "gen_helper_fcircadd(",
1549         addr,
1550         ", ",
1551         addr,
1552         ", ",
1553         &increment_m,
1554         ", ",
1555         modifier);
1556     OUT(c, locp, ", CS);\n");
1557 }
1558 
gen_locnt_op(Context * c,YYLTYPE * locp,HexValue * src)1559 HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *src)
1560 {
1561     const char *bit_suffix = src->bit_width == 64 ? "64" : "32";
1562     HexValue src_m = *src;
1563     HexValue res;
1564 
1565     assert_signedness(c, locp, src->signedness);
1566     res = gen_tmp(c, locp, src->bit_width == 64 ? 64 : 32, src->signedness);
1567     src_m = rvalue_materialize(c, locp, &src_m);
1568     OUT(c, locp, "tcg_gen_not_i", bit_suffix, "(",
1569         &res, ", ", &src_m, ");\n");
1570     OUT(c, locp, "tcg_gen_clzi_i", bit_suffix, "(", &res, ", ", &res, ", ");
1571     OUT(c, locp, bit_suffix, ");\n");
1572     return res;
1573 }
1574 
gen_ctpop_op(Context * c,YYLTYPE * locp,HexValue * src)1575 HexValue gen_ctpop_op(Context *c, YYLTYPE *locp, HexValue *src)
1576 {
1577     const char *bit_suffix = src->bit_width == 64 ? "64" : "32";
1578     HexValue src_m = *src;
1579     HexValue res;
1580     assert_signedness(c, locp, src->signedness);
1581     res = gen_tmp(c, locp, src->bit_width == 64 ? 64 : 32, src->signedness);
1582     src_m = rvalue_materialize(c, locp, &src_m);
1583     OUT(c, locp, "tcg_gen_ctpop_i", bit_suffix,
1584         "(", &res, ", ", &src_m, ");\n");
1585     return res;
1586 }
1587 
gen_rotl(Context * c,YYLTYPE * locp,HexValue * src,HexValue * width)1588 HexValue gen_rotl(Context *c, YYLTYPE *locp, HexValue *src, HexValue *width)
1589 {
1590     const char *suffix = src->bit_width == 64 ? "i64" : "i32";
1591     HexValue amount = *width;
1592     HexValue res;
1593     assert_signedness(c, locp, src->signedness);
1594     res = gen_tmp(c, locp, src->bit_width, src->signedness);
1595     if (amount.bit_width < src->bit_width) {
1596         amount = gen_rvalue_extend(c, locp, &amount);
1597     } else {
1598         amount = gen_rvalue_truncate(c, locp, &amount);
1599     }
1600     amount = rvalue_materialize(c, locp, &amount);
1601     OUT(c, locp, "tcg_gen_rotl_", suffix, "(",
1602         &res, ", ", src, ", ", &amount, ");\n");
1603 
1604     return res;
1605 }
1606 
gen_carry_from_add(Context * c,YYLTYPE * locp,HexValue * op1,HexValue * op2,HexValue * op3)1607 HexValue gen_carry_from_add(Context *c,
1608                             YYLTYPE *locp,
1609                             HexValue *op1,
1610                             HexValue *op2,
1611                             HexValue *op3)
1612 {
1613     HexValue zero = gen_constant(c, locp, "0", 64, UNSIGNED);
1614     HexValue res = gen_tmp(c, locp, 64, UNSIGNED);
1615     HexValue cf = gen_tmp(c, locp, 64, UNSIGNED);
1616     HexValue op1_m = rvalue_materialize(c, locp, op1);
1617     HexValue op2_m = rvalue_materialize(c, locp, op2);
1618     HexValue op3_m = rvalue_materialize(c, locp, op3);
1619     op3_m = gen_rvalue_extend(c, locp, &op3_m);
1620 
1621     OUT(c, locp, "tcg_gen_add2_i64(", &res, ", ", &cf, ", ", &op1_m, ", ",
1622         &zero);
1623     OUT(c, locp, ", ", &op3_m, ", ", &zero, ");\n");
1624     OUT(c, locp, "tcg_gen_add2_i64(", &res, ", ", &cf, ", ", &res, ", ", &cf);
1625     OUT(c, locp, ", ", &op2_m, ", ", &zero, ");\n");
1626 
1627     return cf;
1628 }
1629 
gen_addsat64(Context * c,YYLTYPE * locp,HexValue * dst,HexValue * op1,HexValue * op2)1630 void gen_addsat64(Context *c,
1631                   YYLTYPE *locp,
1632                   HexValue *dst,
1633                   HexValue *op1,
1634                   HexValue *op2)
1635 {
1636     HexValue op1_m = rvalue_materialize(c, locp, op1);
1637     HexValue op2_m = rvalue_materialize(c, locp, op2);
1638     OUT(c, locp, "gen_add_sat_i64(ctx, ", dst, ", ", &op1_m, ", ",
1639                                   &op2_m, ");\n");
1640 }
1641 
gen_inst(Context * c,GString * iname)1642 void gen_inst(Context *c, GString *iname)
1643 {
1644     c->total_insn++;
1645     c->inst.name = iname;
1646     c->inst.allocated = g_array_new(FALSE, FALSE, sizeof(Var));
1647     c->inst.init_list = g_array_new(FALSE, FALSE, sizeof(HexValue));
1648     c->inst.strings = g_array_new(FALSE, FALSE, sizeof(GString *));
1649     EMIT_SIG(c, "void emit_%s(DisasContext *ctx, Insn *insn, Packet *pkt",
1650              c->inst.name->str);
1651 }
1652 
1653 
1654 /*
1655  * Initialize declared but uninitialized instruction arguments. Only needed for
1656  * predicate arguments, initialization of registers is handled by the Hexagon
1657  * frontend.
1658  */
gen_inst_init_args(Context * c,YYLTYPE * locp)1659 void gen_inst_init_args(Context *c, YYLTYPE *locp)
1660 {
1661     HexValue *val = NULL;
1662     char suffix;
1663 
1664     /* If init_list is NULL arguments have already been initialized */
1665     if (!c->inst.init_list) {
1666         return;
1667     }
1668 
1669     for (unsigned i = 0; i < c->inst.init_list->len; i++) {
1670         val = &g_array_index(c->inst.init_list, HexValue, i);
1671         suffix = val->is_dotnew ? 'N' : 'V';
1672         yyassert(c, locp, val->type == PREDICATE,
1673                  "Only predicates need to be initialized!");
1674         yyassert(c, locp, val->bit_width == 32,
1675                  "Predicates should always be 32 bits");
1676         EMIT_HEAD(c, "tcg_gen_movi_i32(P%c%c, 0);\n", val->pred.id, suffix);
1677     }
1678 
1679     /* Free argument init list once we have initialized everything */
1680     g_array_free(c->inst.init_list, TRUE);
1681     c->inst.init_list = NULL;
1682 }
1683 
gen_inst_code(Context * c,YYLTYPE * locp)1684 void gen_inst_code(Context *c, YYLTYPE *locp)
1685 {
1686     if (c->inst.error_count != 0) {
1687         fprintf(stderr,
1688                 "Parsing of instruction %s generated %d errors!\n",
1689                 c->inst.name->str,
1690                 c->inst.error_count);
1691     } else {
1692         c->implemented_insn++;
1693         fprintf(c->enabled_file, "%s\n", c->inst.name->str);
1694         emit_footer(c);
1695         commit(c);
1696     }
1697     free_instruction(c);
1698 }
1699 
gen_pred_assign(Context * c,YYLTYPE * locp,HexValue * left_pred,HexValue * right_pred)1700 void gen_pred_assign(Context *c, YYLTYPE *locp, HexValue *left_pred,
1701                      HexValue *right_pred)
1702 {
1703     char pred_id[2] = {left_pred->pred.id, 0};
1704     bool is_direct = is_direct_predicate(left_pred);
1705     HexValue r = rvalue_materialize(c, locp, right_pred);
1706     r = gen_rvalue_truncate(c, locp, &r);
1707     yyassert(c, locp, !is_inside_ternary(c),
1708              "Predicate assign not allowed in ternary!");
1709     /* Extract predicate TCGv */
1710     if (is_direct) {
1711         *left_pred = gen_tmp(c, locp, 32, UNSIGNED);
1712     }
1713     /* Extract first 8 bits, and store new predicate value */
1714     OUT(c, locp, "tcg_gen_andi_i32(", left_pred, ", ", &r, ", 0xff);\n");
1715     if (is_direct) {
1716         OUT(c, locp, "gen_log_pred_write(ctx, ", pred_id, ", ", left_pred,
1717             ");\n");
1718     }
1719 }
1720 
gen_cancel(Context * c,YYLTYPE * locp)1721 void gen_cancel(Context *c, YYLTYPE *locp)
1722 {
1723     OUT(c, locp, "gen_cancel(insn->slot);\n");
1724 }
1725 
gen_load_cancel(Context * c,YYLTYPE * locp)1726 void gen_load_cancel(Context *c, YYLTYPE *locp)
1727 {
1728     OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n");
1729     OUT(c, locp, "ctx->s1_store_processed = false;\n");
1730     OUT(c, locp, "process_store(ctx, 1);\n");
1731     OUT(c, locp, "}\n");
1732 }
1733 
gen_load(Context * c,YYLTYPE * locp,HexValue * width,HexSignedness signedness,HexValue * ea,HexValue * dst)1734 void gen_load(Context *c, YYLTYPE *locp, HexValue *width,
1735               HexSignedness signedness, HexValue *ea, HexValue *dst)
1736 {
1737     unsigned dst_bit_width;
1738     unsigned src_bit_width;
1739 
1740     /* Memop width is specified in the load macro */
1741     assert_signedness(c, locp, signedness);
1742 
1743     /* If dst is a variable, assert that is declared and load the type info */
1744     if (dst->type == VARID) {
1745         find_variable(c, locp, dst, dst);
1746     }
1747 
1748     src_bit_width = width->imm.value * 8;
1749     dst_bit_width = MAX(dst->bit_width, 32);
1750 
1751     /* Lookup the effective address EA */
1752     find_variable(c, locp, ea, ea);
1753     OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n");
1754     OUT(c, locp, "probe_noshuf_load(", ea, ", ", width, ", ctx->mem_idx);\n");
1755     OUT(c, locp, "process_store(ctx, 1);\n");
1756     OUT(c, locp, "}\n");
1757 
1758     OUT(c, locp, "tcg_gen_qemu_ld_i", &dst_bit_width);
1759     OUT(c, locp, "(");
1760     OUT(c, locp, dst, ", ", ea, ", ctx->mem_idx, MO_", &src_bit_width);
1761     if (signedness == SIGNED) {
1762         OUT(c, locp, " | MO_SIGN");
1763     }
1764     OUT(c, locp, " | MO_TE);\n");
1765 }
1766 
gen_store(Context * c,YYLTYPE * locp,HexValue * width,HexValue * ea,HexValue * src)1767 void gen_store(Context *c, YYLTYPE *locp, HexValue *width, HexValue *ea,
1768                HexValue *src)
1769 {
1770     HexValue src_m = *src;
1771     /* Memop width is specified in the store macro */
1772     unsigned mem_width = width->imm.value;
1773     /* Lookup the effective address EA */
1774     find_variable(c, locp, ea, ea);
1775     src_m = rvalue_materialize(c, locp, &src_m);
1776     OUT(c, locp, "gen_store", &mem_width, "(tcg_env, ", ea, ", ", &src_m);
1777     OUT(c, locp, ", insn->slot);\n");
1778 }
1779 
gen_sethalf(Context * c,YYLTYPE * locp,HexCast * sh,HexValue * n,HexValue * dst,HexValue * value)1780 void gen_sethalf(Context *c, YYLTYPE *locp, HexCast *sh, HexValue *n,
1781                  HexValue *dst, HexValue *value)
1782 {
1783     yyassert(c, locp, n->type == IMMEDIATE,
1784              "Deposit index must be immediate!\n");
1785     if (dst->type == VARID) {
1786         find_variable(c, locp, dst, dst);
1787     }
1788 
1789     gen_deposit_op(c, locp, dst, value, n, sh);
1790 }
1791 
gen_setbits(Context * c,YYLTYPE * locp,HexValue * hi,HexValue * lo,HexValue * dst,HexValue * value)1792 void gen_setbits(Context *c, YYLTYPE *locp, HexValue *hi, HexValue *lo,
1793                  HexValue *dst, HexValue *value)
1794 {
1795     unsigned len;
1796     HexValue tmp;
1797 
1798     yyassert(c, locp, hi->type == IMMEDIATE &&
1799              hi->imm.type == VALUE &&
1800              lo->type == IMMEDIATE &&
1801              lo->imm.type == VALUE,
1802              "Range deposit needs immediate values!\n");
1803 
1804     *value = gen_rvalue_truncate(c, locp, value);
1805     len = hi->imm.value + 1 - lo->imm.value;
1806     tmp = gen_tmp(c, locp, 32, value->signedness);
1807     /* Emit an `and` to ensure `value` is either 0 or 1. */
1808     OUT(c, locp, "tcg_gen_andi_i32(", &tmp, ", ", value, ", 1);\n");
1809     /* Use `neg` to map 0 -> 0 and 1 -> 0xffff... */
1810     OUT(c, locp, "tcg_gen_neg_i32(", &tmp, ", ", &tmp, ");\n");
1811     OUT(c, locp, "tcg_gen_deposit_i32(", dst, ", ", dst,
1812         ", ", &tmp, ", ");
1813     OUT(c, locp, lo, ", ", &len, ");\n");
1814 }
1815 
gen_if_cond(Context * c,YYLTYPE * locp,HexValue * cond)1816 unsigned gen_if_cond(Context *c, YYLTYPE *locp, HexValue *cond)
1817 {
1818     const char *bit_suffix;
1819     /* Generate an end label, if false branch to that label */
1820     OUT(c, locp, "TCGLabel *if_label_", &c->inst.if_count,
1821         " = gen_new_label();\n");
1822     *cond = rvalue_materialize(c, locp, cond);
1823     bit_suffix = (cond->bit_width == 64) ? "i64" : "i32";
1824     OUT(c, locp, "tcg_gen_brcondi_", bit_suffix, "(TCG_COND_EQ, ", cond,
1825         ", 0, if_label_", &c->inst.if_count, ");\n");
1826     return c->inst.if_count++;
1827 }
1828 
gen_if_else(Context * c,YYLTYPE * locp,unsigned index)1829 unsigned gen_if_else(Context *c, YYLTYPE *locp, unsigned index)
1830 {
1831     unsigned if_index = c->inst.if_count++;
1832     /* Generate label to jump if else is not verified */
1833     OUT(c, locp, "TCGLabel *if_label_", &if_index,
1834         " = gen_new_label();\n");
1835     /* Jump out of the else statement */
1836     OUT(c, locp, "tcg_gen_br(if_label_", &if_index, ");\n");
1837     /* Fix the else label */
1838     OUT(c, locp, "gen_set_label(if_label_", &index, ");\n");
1839     return if_index;
1840 }
1841 
gen_rvalue_pred(Context * c,YYLTYPE * locp,HexValue * pred)1842 HexValue gen_rvalue_pred(Context *c, YYLTYPE *locp, HexValue *pred)
1843 {
1844     /* Predicted instructions need to zero out result args */
1845     gen_inst_init_args(c, locp);
1846 
1847     if (is_direct_predicate(pred)) {
1848         bool is_dotnew = pred->is_dotnew;
1849         char predicate_id[2] = { pred->pred.id, '\0' };
1850         char *pred_str = (char *) &predicate_id;
1851         *pred = gen_tmp(c, locp, 32, UNSIGNED);
1852         if (is_dotnew) {
1853             OUT(c, locp, "tcg_gen_mov_i32(", pred,
1854                 ", ctx->new_pred_value[");
1855             OUT(c, locp, pred_str, "]);\n");
1856         } else {
1857             OUT(c, locp, "gen_read_preg(", pred, ", ", pred_str, ");\n");
1858         }
1859     }
1860 
1861     return *pred;
1862 }
1863 
gen_rvalue_var(Context * c,YYLTYPE * locp,HexValue * var)1864 HexValue gen_rvalue_var(Context *c, YYLTYPE *locp, HexValue *var)
1865 {
1866     find_variable(c, locp, var, var);
1867     return *var;
1868 }
1869 
gen_rvalue_mpy(Context * c,YYLTYPE * locp,HexMpy * mpy,HexValue * op1,HexValue * op2)1870 HexValue gen_rvalue_mpy(Context *c, YYLTYPE *locp, HexMpy *mpy,
1871                         HexValue *op1, HexValue *op2)
1872 {
1873     HexValue res;
1874     memset(&res, 0, sizeof(HexValue));
1875 
1876     assert_signedness(c, locp, mpy->first_signedness);
1877     assert_signedness(c, locp, mpy->second_signedness);
1878 
1879     *op1 = gen_cast_op(c, locp, op1, mpy->first_bit_width * 2,
1880                      mpy->first_signedness);
1881     /* Handle fMPTY3216.. */
1882     if (mpy->first_bit_width == 32) {
1883         *op2 = gen_cast_op(c, locp, op2, 64, mpy->second_signedness);
1884     } else {
1885         *op2 = gen_cast_op(c, locp, op2, mpy->second_bit_width * 2,
1886                          mpy->second_signedness);
1887     }
1888     res = gen_bin_op(c, locp, MUL_OP, op1, op2);
1889     /* Handle special cases required by the language */
1890     if (mpy->first_bit_width == 16 && mpy->second_bit_width == 16) {
1891         HexValue src_width = gen_imm_value(c, locp, 32, 32, UNSIGNED);
1892         HexSignedness signedness = bin_op_signedness(c, locp,
1893                                                      mpy->first_signedness,
1894                                                      mpy->second_signedness);
1895         res = gen_extend_op(c, locp, &src_width, 64, &res,
1896                             signedness);
1897     }
1898     return res;
1899 }
1900 
gen_rvalue_simple_unary(Context * c,YYLTYPE * locp,HexValue * value,const char * c_code,const char * tcg_code)1901 static inline HexValue gen_rvalue_simple_unary(Context *c, YYLTYPE *locp,
1902                                                HexValue *value,
1903                                                const char *c_code,
1904                                                const char *tcg_code)
1905 {
1906     unsigned bit_width = (value->bit_width == 64) ? 64 : 32;
1907     HexValue res;
1908     if (value->type == IMMEDIATE) {
1909         res = gen_imm_qemu_tmp(c, locp, bit_width, value->signedness);
1910         gen_c_int_type(c, locp, value->bit_width, value->signedness);
1911         OUT(c, locp, " ", &res, " = ", c_code, "(", value, ");\n");
1912     } else {
1913         res = gen_tmp(c, locp, bit_width, value->signedness);
1914         OUT(c, locp, tcg_code, "_i", &bit_width, "(", &res, ", ", value,
1915             ");\n");
1916     }
1917     return res;
1918 }
1919 
1920 
gen_rvalue_not(Context * c,YYLTYPE * locp,HexValue * value)1921 HexValue gen_rvalue_not(Context *c, YYLTYPE *locp, HexValue *value)
1922 {
1923     return gen_rvalue_simple_unary(c, locp, value, "~", "tcg_gen_not");
1924 }
1925 
gen_rvalue_notl(Context * c,YYLTYPE * locp,HexValue * value)1926 HexValue gen_rvalue_notl(Context *c, YYLTYPE *locp, HexValue *value)
1927 {
1928     unsigned bit_width = (value->bit_width == 64) ? 64 : 32;
1929     HexValue res;
1930     if (value->type == IMMEDIATE) {
1931         res = gen_imm_qemu_tmp(c, locp, bit_width, value->signedness);
1932         gen_c_int_type(c, locp, value->bit_width, value->signedness);
1933         OUT(c, locp, " ", &res, " = !(", value, ");\n");
1934     } else {
1935         HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED);
1936         HexValue one = gen_constant(c, locp, "0xff", bit_width, UNSIGNED);
1937         res = gen_tmp(c, locp, bit_width, value->signedness);
1938         OUT(c, locp, "tcg_gen_movcond_i", &bit_width);
1939         OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", value, ", ", &zero);
1940         OUT(c, locp, ", ", &one, ", ", &zero, ");\n");
1941     }
1942     return res;
1943 }
1944 
gen_rvalue_sat(Context * c,YYLTYPE * locp,HexSat * sat,HexValue * width,HexValue * value)1945 HexValue gen_rvalue_sat(Context *c, YYLTYPE *locp, HexSat *sat,
1946                         HexValue *width, HexValue *value)
1947 {
1948     const char *unsigned_str;
1949     const char *bit_suffix = (value->bit_width == 64) ? "i64" : "i32";
1950     HexValue res;
1951     HexValue ovfl;
1952     /*
1953      * Note: all saturates are assumed to implicitly set overflow.
1954      * This assumption holds for the instructions currently parsed
1955      * by idef-parser.
1956      */
1957     yyassert(c, locp, width->imm.value < value->bit_width,
1958              "To compute overflow, source width must be greater than"
1959              " saturation width!");
1960     yyassert(c, locp, !is_inside_ternary(c),
1961              "Saturating from within a ternary is not allowed!");
1962     assert_signedness(c, locp, sat->signedness);
1963 
1964     unsigned_str = (sat->signedness == UNSIGNED) ? "u" : "";
1965     res = gen_tmp(c, locp, value->bit_width, sat->signedness);
1966     ovfl = gen_tmp(c, locp, 32, sat->signedness);
1967     OUT(c, locp, "gen_sat", unsigned_str, "_", bit_suffix, "_ovfl(");
1968     OUT(c, locp, &ovfl, ", ", &res, ", ", value, ", ", &width->imm.value,
1969         ");\n");
1970     OUT(c, locp, "gen_set_usr_field_if(ctx, USR_OVF,", &ovfl, ");\n");
1971 
1972     return res;
1973 }
1974 
gen_rvalue_fscr(Context * c,YYLTYPE * locp,HexValue * value)1975 HexValue gen_rvalue_fscr(Context *c, YYLTYPE *locp, HexValue *value)
1976 {
1977     HexValue key = gen_tmp(c, locp, 64, UNSIGNED);
1978     HexValue res = gen_tmp(c, locp, 64, UNSIGNED);
1979     HexValue frame_key = gen_tmp(c, locp, 32, UNSIGNED);
1980     *value = gen_rvalue_extend(c, locp, value);
1981     OUT(c, locp, "gen_read_reg(", &frame_key, ", HEX_REG_FRAMEKEY);\n");
1982     OUT(c, locp, "tcg_gen_concat_i32_i64(",
1983         &key, ", ", &frame_key, ", ", &frame_key, ");\n");
1984     OUT(c, locp, "tcg_gen_xor_i64(", &res, ", ", value, ", ", &key, ");\n");
1985     return res;
1986 }
1987 
gen_rvalue_abs(Context * c,YYLTYPE * locp,HexValue * value)1988 HexValue gen_rvalue_abs(Context *c, YYLTYPE *locp, HexValue *value)
1989 {
1990     return gen_rvalue_simple_unary(c, locp, value, "abs", "tcg_gen_abs");
1991 }
1992 
gen_rvalue_neg(Context * c,YYLTYPE * locp,HexValue * value)1993 HexValue gen_rvalue_neg(Context *c, YYLTYPE *locp, HexValue *value)
1994 {
1995     return gen_rvalue_simple_unary(c, locp, value, "-", "tcg_gen_neg");
1996 }
1997 
gen_rvalue_brev(Context * c,YYLTYPE * locp,HexValue * value)1998 HexValue gen_rvalue_brev(Context *c, YYLTYPE *locp, HexValue *value)
1999 {
2000     HexValue res;
2001     yyassert(c, locp, value->bit_width <= 32,
2002              "fbrev not implemented for 64-bit integers!");
2003     res = gen_tmp(c, locp, value->bit_width, value->signedness);
2004     *value = rvalue_materialize(c, locp, value);
2005     OUT(c, locp, "gen_helper_fbrev(", &res, ", ", value, ");\n");
2006     return res;
2007 }
2008 
gen_rvalue_ternary(Context * c,YYLTYPE * locp,HexValue * cond,HexValue * true_branch,HexValue * false_branch)2009 HexValue gen_rvalue_ternary(Context *c, YYLTYPE *locp, HexValue *cond,
2010                             HexValue *true_branch, HexValue *false_branch)
2011 {
2012     bool is_64bit = (true_branch->bit_width == 64) ||
2013                     (false_branch->bit_width == 64);
2014     unsigned bit_width = (is_64bit) ? 64 : 32;
2015     HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED);
2016     HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED);
2017 
2018     if (is_64bit) {
2019         *cond = gen_rvalue_extend(c, locp, cond);
2020         *true_branch = gen_rvalue_extend(c, locp, true_branch);
2021         *false_branch = gen_rvalue_extend(c, locp, false_branch);
2022     } else {
2023         *cond = gen_rvalue_truncate(c, locp, cond);
2024     }
2025     *cond = rvalue_materialize(c, locp, cond);
2026     *true_branch = rvalue_materialize(c, locp, true_branch);
2027     *false_branch = rvalue_materialize(c, locp, false_branch);
2028 
2029     OUT(c, locp, "tcg_gen_movcond_i", &bit_width);
2030     OUT(c, locp, "(TCG_COND_NE, ", &res, ", ", cond, ", ", &zero);
2031     OUT(c, locp, ", ", true_branch, ", ", false_branch, ");\n");
2032 
2033     assert(c->ternary->len > 0);
2034     g_array_remove_index(c->ternary, c->ternary->len - 1);
2035 
2036     return res;
2037 }
2038 
cond_to_str(TCGCond cond)2039 const char *cond_to_str(TCGCond cond)
2040 {
2041     switch (cond) {
2042     case TCG_COND_NEVER:
2043         return "TCG_COND_NEVER";
2044     case TCG_COND_ALWAYS:
2045         return "TCG_COND_ALWAYS";
2046     case TCG_COND_EQ:
2047         return "TCG_COND_EQ";
2048     case TCG_COND_NE:
2049         return "TCG_COND_NE";
2050     case TCG_COND_LT:
2051         return "TCG_COND_LT";
2052     case TCG_COND_GE:
2053         return "TCG_COND_GE";
2054     case TCG_COND_LE:
2055         return "TCG_COND_LE";
2056     case TCG_COND_GT:
2057         return "TCG_COND_GT";
2058     case TCG_COND_LTU:
2059         return "TCG_COND_LTU";
2060     case TCG_COND_GEU:
2061         return "TCG_COND_GEU";
2062     case TCG_COND_LEU:
2063         return "TCG_COND_LEU";
2064     case TCG_COND_GTU:
2065         return "TCG_COND_GTU";
2066     default:
2067         abort();
2068     }
2069 }
2070 
emit_arg(Context * c,YYLTYPE * locp,HexValue * arg)2071 void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg)
2072 {
2073     switch (arg->type) {
2074     case REGISTER_ARG:
2075         if (arg->reg.type == DOTNEW) {
2076             EMIT_SIG(c, ", TCGv N%cN", arg->reg.id);
2077         } else {
2078             bool is64 = (arg->bit_width == 64);
2079             const char *type = is64 ? "TCGv_i64" : "TCGv_i32";
2080             char reg_id[5];
2081             reg_compose(c, locp, &(arg->reg), reg_id);
2082             EMIT_SIG(c, ", %s %s", type, reg_id);
2083             /* MuV register requires also CS for circular addressing*/
2084             if (arg->reg.type == MODIFIER) {
2085                 EMIT_SIG(c, ", TCGv CS");
2086             }
2087         }
2088         break;
2089     case PREDICATE:
2090         {
2091             char suffix = arg->is_dotnew ? 'N' : 'V';
2092             EMIT_SIG(c, ", TCGv P%c%c", arg->pred.id, suffix);
2093         }
2094         break;
2095     default:
2096         {
2097             fprintf(stderr, "emit_arg got unsupported argument!");
2098             abort();
2099         }
2100     }
2101 }
2102 
emit_footer(Context * c)2103 void emit_footer(Context *c)
2104 {
2105     EMIT(c, "}\n");
2106     EMIT(c, "\n");
2107 }
2108 
track_string(Context * c,GString * s)2109 void track_string(Context *c, GString *s)
2110 {
2111     g_array_append_val(c->inst.strings, s);
2112 }
2113 
free_instruction(Context * c)2114 void free_instruction(Context *c)
2115 {
2116     assert(!is_inside_ternary(c));
2117     /* Free the strings */
2118     g_string_truncate(c->signature_str, 0);
2119     g_string_truncate(c->out_str, 0);
2120     g_string_truncate(c->header_str, 0);
2121     /* Free strings allocated by the instruction */
2122     for (unsigned i = 0; i < c->inst.strings->len; i++) {
2123         g_string_free(g_array_index(c->inst.strings, GString*, i), TRUE);
2124     }
2125     g_array_free(c->inst.strings, TRUE);
2126     /*
2127      * Free list of arguments that might need initialization, if they haven't
2128      * already been freed.
2129      */
2130     if (c->inst.init_list) {
2131         g_array_free(c->inst.init_list, TRUE);
2132     }
2133     /* Free INAME token value */
2134     g_string_free(c->inst.name, TRUE);
2135     /* Free declared TCGv variables */
2136     g_array_free(c->inst.allocated, TRUE);
2137     /* Initialize instruction-specific portion of the context */
2138     memset(&(c->inst), 0, sizeof(Inst));
2139 }
2140 
assert_signedness(Context * c,YYLTYPE * locp,HexSignedness signedness)2141 void assert_signedness(Context *c,
2142                        YYLTYPE *locp,
2143                        HexSignedness signedness)
2144 {
2145     yyassert(c, locp,
2146              signedness != UNKNOWN_SIGNEDNESS,
2147              "Unspecified signedness");
2148 }
2149