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