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