qapi: Improve specificity of type/member descriptions
[qemu/armbru.git] / target / hexagon / idef-parser / parser-helpers.c
blob86511efb62b94db5a2c4cc793bf215f9c296031d
1 /*
2 * Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved.
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.
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.
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/>.
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>
28 #include "idef-parser.h"
29 #include "parser-helpers.h"
30 #include "idef-parser.tab.h"
31 #include "idef-parser.yy.h"
33 void yyerror(YYLTYPE *locp,
34 yyscan_t scanner __attribute__((unused)),
35 Context *c,
36 const char *s)
38 const char *code_ptr = c->input_buffer;
40 fprintf(stderr, "WARNING (%s): '%s'\n", c->inst.name->str, s);
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]);
48 fprintf(stderr, "\n");
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]);
57 fprintf(stderr, "\n");
58 for (unsigned i = 0; i < 9; i++) {
59 fprintf(stderr, " ");
61 fprintf(stderr, "^");
62 for (int i = 0; i < (locp->last_column - locp->first_column) - 1; i++) {
63 fprintf(stderr, "~");
65 fprintf(stderr, "\n");
66 c->inst.error_count++;
69 bool is_direct_predicate(HexValue *value)
71 return value->pred.id >= '0' && value->pred.id <= '3';
74 bool is_inside_ternary(Context *c)
76 return c->ternary->len > 0;
79 /* Print functions */
80 void str_print(Context *c, YYLTYPE *locp, const char *string)
82 (void) locp;
83 EMIT(c, "%s", string);
86 void uint8_print(Context *c, YYLTYPE *locp, uint8_t *num)
88 (void) locp;
89 EMIT(c, "%u", *num);
92 void uint64_print(Context *c, YYLTYPE *locp, uint64_t *num)
94 (void) locp;
95 EMIT(c, "%" PRIu64, *num);
98 void int_print(Context *c, YYLTYPE *locp, int *num)
100 (void) locp;
101 EMIT(c, "%d", *num);
104 void uint_print(Context *c, YYLTYPE *locp, unsigned *num)
106 (void) locp;
107 EMIT(c, "%u", *num);
110 void tmp_print(Context *c, YYLTYPE *locp, HexTmp *tmp)
112 (void) locp;
113 EMIT(c, "tmp_%d", tmp->index);
116 void pred_print(Context *c, YYLTYPE *locp, HexPred *pred, bool is_dotnew)
118 (void) locp;
119 char suffix = is_dotnew ? 'N' : 'V';
120 EMIT(c, "P%c%c", pred->id, suffix);
123 void reg_compose(Context *c, YYLTYPE *locp, HexReg *reg, char reg_id[5])
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;
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");
157 static void reg_arg_print(Context *c, YYLTYPE *locp, HexReg *reg)
159 char reg_id[5];
160 reg_compose(c, locp, reg, reg_id);
161 EMIT(c, "%s", reg_id);
164 void reg_print(Context *c, YYLTYPE *locp, HexReg *reg)
166 (void) locp;
167 EMIT(c, "hex_gpr[%u]", reg->id);
170 void imm_print(Context *c, YYLTYPE *locp, HexImm *imm)
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!");
196 void var_print(Context *c, YYLTYPE *locp, HexVar *var)
198 (void) locp;
199 EMIT(c, "%s", var->name->str);
202 void rvalue_print(Context *c, YYLTYPE *locp, void *pointer)
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!");
229 void out_assert(Context *c, YYLTYPE *locp,
230 void *dummy __attribute__((unused)))
232 yyassert(c, locp, false, "Unhandled print type!");
235 /* Copy output code buffer */
236 void commit(Context *c)
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);
243 EMIT_SIG(c, " " END_COMMENT "\n");
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);
253 fwrite(c->signature_str->str, sizeof(char), c->signature_str->len,
254 c->defines_file);
255 fprintf(c->defines_file, ";\n");
258 static void gen_c_int_type(Context *c, YYLTYPE *locp, unsigned bit_width,
259 HexSignedness signedness)
261 const char *signstr = (signedness == UNSIGNED) ? "u" : "";
262 OUT(c, locp, signstr, "int", &bit_width, "_t");
265 static HexValue gen_constant(Context *c,
266 YYLTYPE *locp,
267 const char *value,
268 unsigned bit_width,
269 HexSignedness signedness)
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;
285 /* Temporary values creation */
286 HexValue gen_tmp(Context *c,
287 YYLTYPE *locp,
288 unsigned bit_width,
289 HexSignedness signedness)
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;
305 static HexValue gen_constant_from_imm(Context *c,
306 YYLTYPE *locp,
307 HexValue *value)
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;
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
322 * `tcg_constant_i<width>`((int<width>_t) ...)`
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.
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");
333 c->inst.tmp_count++;
334 return rvalue;
337 HexValue gen_imm_value(Context *c __attribute__((unused)),
338 YYLTYPE *locp,
339 int value,
340 unsigned bit_width,
341 HexSignedness signedness)
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;
356 HexValue gen_imm_qemu_tmp(Context *c, YYLTYPE *locp, unsigned bit_width,
357 HexSignedness signedness)
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;
372 HexValue rvalue_materialize(Context *c, YYLTYPE *locp, HexValue *rvalue)
374 if (rvalue->type == IMMEDIATE) {
375 return gen_constant_from_imm(c, locp, rvalue);
377 return *rvalue;
380 HexValue gen_rvalue_extend(Context *c, YYLTYPE *locp, HexValue *rvalue)
382 assert_signedness(c, locp, rvalue->signedness);
383 if (rvalue->bit_width > 32) {
384 return *rvalue;
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;
407 HexValue gen_rvalue_truncate(Context *c, YYLTYPE *locp, HexValue *rvalue)
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;
420 return *rvalue;
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.
429 static bool try_find_variable(Context *c, YYLTYPE *locp,
430 HexValue *dst,
431 HexValue *varid)
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;
444 return true;
447 return false;
450 /* Calls `try_find_variable` and asserts succcess. */
451 static void find_variable(Context *c, YYLTYPE *locp,
452 HexValue *dst,
453 HexValue *varid)
455 bool found = try_find_variable(c, locp, dst, varid);
456 yyassert(c, locp, found, "Use of undeclared variable!\n");
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)
464 assert_signedness(c, locp, sign1);
465 assert_signedness(c, locp, sign2);
466 return (sign1 == UNSIGNED && sign2 == UNSIGNED) ? UNSIGNED : SIGNED;
469 void gen_varid_allocate(Context *c,
470 YYLTYPE *locp,
471 HexValue *varid,
472 unsigned bit_width,
473 HexSignedness signedness)
475 const char *bit_suffix = (bit_width == 64) ? "i64" : "i32";
476 bool found = try_find_variable(c, locp, NULL, varid);
477 Var new_var;
479 memset(&new_var, 0, sizeof(Var));
481 yyassert(c, locp, !found, "Redeclaration of variables not allowed!");
482 assert_signedness(c, locp, signedness);
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;
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);
494 enum OpTypes {
495 IMM_IMM = 0,
496 IMM_REG = 1,
497 REG_IMM = 2,
498 REG_REG = 3,
501 HexValue gen_bin_cmp(Context *c,
502 YYLTYPE *locp,
503 TCGCond type,
504 HexValue *op1,
505 HexValue *op2)
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);
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);
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);
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();
543 return res;
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)
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;
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)
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;
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)
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;
642 if (op_types == IMM_REG || op_types == REG_REG) {
644 * Handle left shift by 64/32 which hexagon-sim expects to clear out
645 * register
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);
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");
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)
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;
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);
699 edge = rvalue_materialize(c, locp, &edge);
700 if (op_is64bit) {
701 op2_m = gen_rvalue_extend(c, locp, &op2_m);
703 op1_m = rvalue_materialize(c, locp, &op1_m);
704 op2_m = rvalue_materialize(c, locp, &op2_m);
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");
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)
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;
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);
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");
759 * Note: This implementation of logical `and` does not mirror that in C.
760 * We do not short-circuit logical expressions!
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)
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;
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)
792 const char *mm;
793 HexValue op1_m = *op1;
794 HexValue op2_m = *op2;
795 bool is_unsigned;
797 assert_signedness(c, locp, res->signedness);
798 is_unsigned = res->signedness == UNSIGNED;
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";
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;
828 /* Code generation functions */
829 HexValue gen_bin_op(Context *c,
830 YYLTYPE *locp,
831 OpType type,
832 HexValue *op1,
833 HexValue *op2)
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;
845 memset(&res, 0, sizeof(HexValue));
848 * If the operands are VARID's we need to look up the
849 * type information.
851 if (op1_m.type == VARID) {
852 find_variable(c, locp, &op1_m, &op1_m);
854 if (op2_m.type == VARID) {
855 find_variable(c, locp, &op2_m, &op2_m);
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 */
863 if (type == ASL_OP && op2_m.type == IMMEDIATE &&
864 op2_m.imm.type == VALUE && op2_m.imm.value >= 32) {
865 op_is64bit = true;
868 bit_width = (op_is64bit) ? 64 : 32;
869 bit_suffix = op_is64bit ? "i64" : "i32";
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);
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);
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;
953 return res;
956 HexValue gen_cast_op(Context *c,
957 YYLTYPE *locp,
958 HexValue *src,
959 unsigned target_width,
960 HexSignedness signedness)
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");
987 return res;
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`.
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)
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.
1010 const char *sign_prefix;
1011 bool need_guarding;
1013 assert_signedness(c, locp, signedness);
1014 assert(dst_width == 64 || dst_width == 32);
1015 assert(src_width->type == IMMEDIATE);
1017 sign_prefix = (signedness == UNSIGNED) ? "" : "s";
1018 need_guarding = (src_width->imm.type != VALUE);
1020 if (src_width->imm.type == VALUE &&
1021 src_width->imm.value == 0) {
1023 * We can bail out early if the source width is known to be zero
1024 * at translation time.
1026 return gen_imm_value(c, locp, 0, dst_width, signedness);
1029 if (value->type == IMMEDIATE) {
1031 * If both the value and source width are immediates,
1032 * we can perform the extension at translation time
1033 * using QEMUs bitops.
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");
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");
1046 return res;
1047 } else {
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
1052 HexValue res = gen_tmp(c, locp, dst_width, signedness);
1055 * If the width is an immediate value we know it is non-zero
1056 * at this point, otherwise we need an if-statement
1058 if (need_guarding) {
1059 OUT(c, locp, "if (", src_width, " != 0) {\n");
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");
1070 return res;
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.
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)
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;
1091 assert_signedness(c, locp, signedness);
1092 assert(dst_width == 64 || dst_width == 32);
1093 assert(src_width->type != IMMEDIATE);
1095 res = gen_tmp(c, locp, dst_width, signedness);
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");
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");
1116 return res;
1119 HexValue gen_extend_op(Context *c,
1120 YYLTYPE *locp,
1121 HexValue *src_width,
1122 unsigned dst_width,
1123 HexValue *value,
1124 HexSignedness signedness)
1126 unsigned bit_width = (dst_width = 64) ? 64 : 32;
1127 HexValue value_m = *value;
1128 HexValue src_width_m = *src_width;
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");
1136 if (value_m.bit_width < bit_width) {
1137 value_m = gen_rvalue_extend(c, locp, &value_m);
1140 if (src_width_m.bit_width < bit_width) {
1141 src_width_m = gen_rvalue_extend(c, locp, &src_width_m);
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);
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.
1158 * Note: this is the only type of `rdeposit` that occurs, meaning the
1159 * `width` is _NEVER_ of IMMEDIATE type.
1161 void gen_rdeposit_op(Context *c,
1162 YYLTYPE *locp,
1163 HexValue *dst,
1164 HexValue *value,
1165 HexValue *begin,
1166 HexValue *width)
1169 * Otherwise if the width is not known, we fallback on reimplementing
1170 * desposit in TCG.
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;
1186 assert(dst->bit_width >= value->bit_width);
1187 assert(begin->type == IMMEDIATE && begin->imm.type == VALUE);
1188 assert(dst->type == REGISTER_ARG);
1190 yyassert(c, locp, width->type != IMMEDIATE,
1191 "Immediate index to rdeposit not handled!");
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!");
1199 width_m = rvalue_materialize(c, locp, &width_m);
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
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);
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);
1221 * We don't need to truncate `res` here, since all operations involved use
1222 * the same bit width.
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");
1233 void gen_deposit_op(Context *c,
1234 YYLTYPE *locp,
1235 HexValue *dst,
1236 HexValue *value,
1237 HexValue *index,
1238 HexCast *cast)
1240 HexValue value_m = *value;
1241 unsigned bit_width = (dst->bit_width == 64) ? 64 : 32;
1242 unsigned width = cast->bit_width;
1244 yyassert(c, locp, index->type == IMMEDIATE,
1245 "Deposit index must be immediate!\n");
1248 * Using tcg_gen_deposit_i**(dst, dst, ...) requires dst to be
1249 * initialized.
1251 gen_inst_init_args(c, locp);
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);
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");
1266 HexValue gen_rextract_op(Context *c,
1267 YYLTYPE *locp,
1268 HexValue *src,
1269 unsigned begin,
1270 unsigned width)
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;
1279 HexValue gen_extract_op(Context *c,
1280 YYLTYPE *locp,
1281 HexValue *src,
1282 HexValue *index,
1283 HexExtract *extract)
1285 unsigned bit_width = (src->bit_width == 64) ? 64 : 32;
1286 unsigned width = extract->bit_width;
1287 const char *sign_prefix;
1288 HexValue res;
1290 yyassert(c, locp, index->type == IMMEDIATE,
1291 "Extract index must be immediate!\n");
1292 assert_signedness(c, locp, extract->signedness);
1294 sign_prefix = (extract->signedness == UNSIGNED) ? "" : "s";
1295 res = gen_tmp(c, locp, bit_width, extract->signedness);
1297 OUT(c, locp, "tcg_gen_", sign_prefix, "extract_i", &bit_width,
1298 "(", &res, ", ", src);
1299 OUT(c, locp, ", ", index, " * ", &width, ", ", &width, ");\n");
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;
1310 return res;
1313 void gen_write_reg(Context *c, YYLTYPE *locp, HexValue *reg, HexValue *value)
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");
1325 void gen_assign(Context *c,
1326 YYLTYPE *locp,
1327 HexValue *dst,
1328 HexValue *value)
1330 HexValue value_m = *value;
1331 unsigned bit_width;
1333 yyassert(c, locp, !is_inside_ternary(c),
1334 "Assign in ternary not allowed!");
1336 if (dst->type == REGISTER) {
1337 gen_write_reg(c, locp, dst, &value_m);
1338 return;
1341 if (dst->type == VARID) {
1342 find_variable(c, locp, dst, dst);
1344 bit_width = dst->bit_width == 64 ? 64 : 32;
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);
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");
1359 HexValue gen_convround(Context *c,
1360 YYLTYPE *locp,
1361 HexValue *src)
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;
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);
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");
1379 return res;
1382 static HexValue gen_convround_n_b(Context *c,
1383 YYLTYPE *locp,
1384 HexValue *a,
1385 HexValue *n)
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);
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");
1404 return res;
1407 static HexValue gen_convround_n_c(Context *c,
1408 YYLTYPE *locp,
1409 HexValue *a,
1410 HexValue *n)
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);
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");
1426 return res;
1429 HexValue gen_convround_n(Context *c,
1430 YYLTYPE *locp,
1431 HexValue *src,
1432 HexValue *pos)
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;
1448 src_casted = rvalue_materialize(c, locp, &src_casted);
1449 pos_casted = rvalue_materialize(c, locp, &pos_casted);
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.
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);
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.
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");
1477 OUT(c, locp, "tcg_gen_ext_i32_i64(", &n_64, ", ", &pos_casted, ");\n");
1480 * if the bits 0, ..., pos_casted-1 are all 0, then pick r2 otherwise,
1481 * pick r3.
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");
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");
1492 /* Finally shift back val >>= n */
1493 OUT(c, locp, "tcg_gen_shr_i64(", &res);
1494 OUT(c, locp, ", ", &res, ", ", &n_64, ");\n");
1496 res = gen_rvalue_truncate(c, locp, &res);
1497 return res;
1500 HexValue gen_round(Context *c,
1501 YYLTYPE *locp,
1502 HexValue *src,
1503 HexValue *pos)
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;
1515 assert_signedness(c, locp, src->signedness);
1516 yyassert(c, locp, src->bit_width <= 32,
1517 "fRNDN not implemented for bit widths > 32!");
1519 res = gen_tmp(c, locp, 64, src->signedness);
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);
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);
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);
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");
1537 return res;
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)
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");
1564 HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *src)
1566 const char *bit_suffix = src->bit_width == 64 ? "64" : "32";
1567 HexValue src_m = *src;
1568 HexValue res;
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;
1580 HexValue gen_ctpop_op(Context *c, YYLTYPE *locp, HexValue *src)
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;
1593 HexValue gen_rotl(Context *c, YYLTYPE *locp, HexValue *src, HexValue *width)
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);
1605 amount = rvalue_materialize(c, locp, &amount);
1606 OUT(c, locp, "tcg_gen_rotl_", suffix, "(",
1607 &res, ", ", src, ", ", &amount, ");\n");
1609 return res;
1612 HexValue gen_carry_from_add(Context *c,
1613 YYLTYPE *locp,
1614 HexValue *op1,
1615 HexValue *op2,
1616 HexValue *op3)
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);
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");
1632 return cf;
1635 void gen_addsat64(Context *c,
1636 YYLTYPE *locp,
1637 HexValue *dst,
1638 HexValue *op1,
1639 HexValue *op2)
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");
1647 void gen_inst(Context *c, GString *iname)
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);
1660 * Initialize declared but uninitialized registers, but only for
1661 * non-conditional instructions
1663 void gen_inst_init_args(Context *c, YYLTYPE *locp)
1665 if (!c->inst.init_list) {
1666 return;
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!");
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;
1687 void gen_inst_code(Context *c, YYLTYPE *locp)
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);
1700 free_instruction(c);
1703 void gen_pred_assign(Context *c, YYLTYPE *locp, HexValue *left_pred,
1704 HexValue *right_pred)
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);
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");
1724 void gen_cancel(Context *c, YYLTYPE *locp)
1726 OUT(c, locp, "gen_cancel(insn->slot);\n");
1729 void gen_load_cancel(Context *c, YYLTYPE *locp)
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");
1737 void gen_load(Context *c, YYLTYPE *locp, HexValue *width,
1738 HexSignedness signedness, HexValue *ea, HexValue *dst)
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);
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) {
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.
1767 OUT(c, locp, "(TCGv) ");
1769 OUT(c, locp, dst, ", ", ea, ", ctx->mem_idx);\n");
1772 void gen_store(Context *c, YYLTYPE *locp, HexValue *width, HexValue *ea,
1773 HexValue *src)
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");
1785 void gen_sethalf(Context *c, YYLTYPE *locp, HexCast *sh, HexValue *n,
1786 HexValue *dst, HexValue *value)
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);
1794 gen_deposit_op(c, locp, dst, value, n, sh);
1797 void gen_setbits(Context *c, YYLTYPE *locp, HexValue *hi, HexValue *lo,
1798 HexValue *dst, HexValue *value)
1800 unsigned len;
1801 HexValue tmp;
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");
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");
1821 unsigned gen_if_cond(Context *c, YYLTYPE *locp, HexValue *cond)
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++;
1834 unsigned gen_if_else(Context *c, YYLTYPE *locp, unsigned index)
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;
1847 HexValue gen_rvalue_pred(Context *c, YYLTYPE *locp, HexValue *pred)
1849 /* Predicted instructions need to zero out result args */
1850 gen_inst_init_args(c, locp);
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");
1866 return *pred;
1869 HexValue gen_rvalue_var(Context *c, YYLTYPE *locp, HexValue *var)
1871 find_variable(c, locp, var, var);
1872 return *var;
1875 HexValue gen_rvalue_mpy(Context *c, YYLTYPE *locp, HexMpy *mpy,
1876 HexValue *op1, HexValue *op2)
1878 HexValue res;
1879 memset(&res, 0, sizeof(HexValue));
1881 assert_signedness(c, locp, mpy->first_signedness);
1882 assert_signedness(c, locp, mpy->second_signedness);
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);
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);
1903 return res;
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)
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");
1922 return res;
1926 HexValue gen_rvalue_not(Context *c, YYLTYPE *locp, HexValue *value)
1928 return gen_rvalue_simple_unary(c, locp, value, "~", "tcg_gen_not");
1931 HexValue gen_rvalue_notl(Context *c, YYLTYPE *locp, HexValue *value)
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");
1947 return res;
1950 HexValue gen_rvalue_sat(Context *c, YYLTYPE *locp, HexSat *sat,
1951 HexValue *width, HexValue *value)
1953 const char *unsigned_str;
1954 const char *bit_suffix = (value->bit_width == 64) ? "i64" : "i32";
1955 HexValue res;
1956 HexValue ovfl;
1958 * Note: all saturates are assumed to implicitly set overflow.
1959 * This assumption holds for the instructions currently parsed
1960 * by idef-parser.
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);
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");
1977 return res;
1980 HexValue gen_rvalue_fscr(Context *c, YYLTYPE *locp, HexValue *value)
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;
1993 HexValue gen_rvalue_abs(Context *c, YYLTYPE *locp, HexValue *value)
1995 return gen_rvalue_simple_unary(c, locp, value, "abs", "tcg_gen_abs");
1998 HexValue gen_rvalue_neg(Context *c, YYLTYPE *locp, HexValue *value)
2000 return gen_rvalue_simple_unary(c, locp, value, "-", "tcg_gen_neg");
2003 HexValue gen_rvalue_brev(Context *c, YYLTYPE *locp, HexValue *value)
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;
2014 HexValue gen_rvalue_ternary(Context *c, YYLTYPE *locp, HexValue *cond,
2015 HexValue *true_branch, HexValue *false_branch)
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);
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);
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);
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");
2038 assert(c->ternary->len > 0);
2039 g_array_remove_index(c->ternary, c->ternary->len - 1);
2041 return res;
2044 const char *cond_to_str(TCGCond cond)
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();
2076 void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg)
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");
2093 break;
2094 case PREDICATE:
2096 char suffix = arg->is_dotnew ? 'N' : 'V';
2097 EMIT_SIG(c, ", TCGv P%c%c", arg->pred.id, suffix);
2099 break;
2100 default:
2102 fprintf(stderr, "emit_arg got unsupported argument!");
2103 abort();
2108 void emit_footer(Context *c)
2110 EMIT(c, "}\n");
2111 EMIT(c, "\n");
2114 void track_string(Context *c, GString *s)
2116 g_array_append_val(c->inst.strings, s);
2119 void free_instruction(Context *c)
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);
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));
2139 void assert_signedness(Context *c,
2140 YYLTYPE *locp,
2141 HexSignedness signedness)
2143 yyassert(c, locp,
2144 signedness != UNKNOWN_SIGNEDNESS,
2145 "Unspecified signedness");