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