2 * Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 #include "idef-parser.h"
29 #include "parser-helpers.h"
30 #include "idef-parser.tab.h"
31 #include "idef-parser.yy.h"
33 void yyerror(YYLTYPE
*locp
,
34 yyscan_t scanner
__attribute__((unused
)),
38 const char *code_ptr
= c
->input_buffer
;
40 fprintf(stderr
, "WARNING (%s): '%s'\n", c
->inst
.name
->str
, s
);
42 fprintf(stderr
, "Problematic range: ");
43 for (int i
= locp
->first_column
; i
< locp
->last_column
; i
++) {
44 if (code_ptr
[i
] != '\n') {
45 fprintf(stderr
, "%c", code_ptr
[i
]);
48 fprintf(stderr
, "\n");
52 code_ptr
[locp
->first_column
- 10 + i
] != '\0' &&
53 code_ptr
[locp
->first_column
- 10 + i
] != '\n';
55 fprintf(stderr
, "%c", code_ptr
[locp
->first_column
- 10 + i
]);
57 fprintf(stderr
, "\n");
58 for (unsigned i
= 0; i
< 9; i
++) {
62 for (int i
= 0; i
< (locp
->last_column
- locp
->first_column
) - 1; i
++) {
65 fprintf(stderr
, "\n");
66 c
->inst
.error_count
++;
69 bool is_direct_predicate(HexValue
*value
)
71 return value
->pred
.id
>= '0' && value
->pred
.id
<= '3';
74 bool is_inside_ternary(Context
*c
)
76 return c
->ternary
->len
> 0;
80 void str_print(Context
*c
, YYLTYPE
*locp
, const char *string
)
83 EMIT(c
, "%s", string
);
86 void uint8_print(Context
*c
, YYLTYPE
*locp
, uint8_t *num
)
92 void uint64_print(Context
*c
, YYLTYPE
*locp
, uint64_t *num
)
95 EMIT(c
, "%" PRIu64
, *num
);
98 void int_print(Context
*c
, YYLTYPE
*locp
, int *num
)
104 void uint_print(Context
*c
, YYLTYPE
*locp
, unsigned *num
)
110 void tmp_print(Context
*c
, YYLTYPE
*locp
, HexTmp
*tmp
)
113 EMIT(c
, "tmp_%d", tmp
->index
);
116 void pred_print(Context
*c
, YYLTYPE
*locp
, HexPred
*pred
, bool is_dotnew
)
119 char suffix
= is_dotnew
? 'N' : 'V';
120 EMIT(c
, "P%c%c", pred
->id
, suffix
);
123 void reg_compose(Context
*c
, YYLTYPE
*locp
, HexReg
*reg
, char reg_id
[5])
125 memset(reg_id
, 0, 5 * sizeof(char));
127 case GENERAL_PURPOSE
:
142 switch (reg
->bit_width
) {
153 yyassert(c
, locp
, false, "Unhandled register bit width!\n");
157 static void reg_arg_print(Context
*c
, YYLTYPE
*locp
, HexReg
*reg
)
160 reg_compose(c
, locp
, reg
, reg_id
);
161 EMIT(c
, "%s", reg_id
);
164 void reg_print(Context
*c
, YYLTYPE
*locp
, HexReg
*reg
)
167 EMIT(c
, "hex_gpr[%u]", reg
->id
);
170 void imm_print(Context
*c
, YYLTYPE
*locp
, HexImm
*imm
)
177 EMIT(c
, "%ciV", imm
->id
);
180 EMIT(c
, "((int64_t) %" PRIu64
"ULL)", (int64_t) imm
->value
);
183 EMIT(c
, "qemu_tmp_%" PRIu64
, imm
->index
);
186 EMIT(c
, "ctx->base.pc_next");
192 EMIT(c
, "insn->extension_valid");
195 yyassert(c
, locp
, false, "Cannot print this expression!");
199 void var_print(Context
*c
, YYLTYPE
*locp
, HexVar
*var
)
202 EMIT(c
, "%s", var
->name
->str
);
205 void rvalue_print(Context
*c
, YYLTYPE
*locp
, void *pointer
)
207 HexValue
*rvalue
= (HexValue
*) pointer
;
208 switch (rvalue
->type
) {
210 reg_print(c
, locp
, &rvalue
->reg
);
213 reg_arg_print(c
, locp
, &rvalue
->reg
);
216 tmp_print(c
, locp
, &rvalue
->tmp
);
219 imm_print(c
, locp
, &rvalue
->imm
);
222 var_print(c
, locp
, &rvalue
->var
);
225 pred_print(c
, locp
, &rvalue
->pred
, rvalue
->is_dotnew
);
228 yyassert(c
, locp
, false, "Cannot print this expression!");
232 void out_assert(Context
*c
, YYLTYPE
*locp
,
233 void *dummy
__attribute__((unused
)))
235 yyassert(c
, locp
, false, "Unhandled print type!");
238 /* Copy output code buffer */
239 void commit(Context
*c
)
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
);
246 EMIT_SIG(c
, " " END_COMMENT
"\n");
248 /* Commit instruction code to output file */
249 fwrite(c
->signature_str
->str
, sizeof(char), c
->signature_str
->len
,
251 fwrite(c
->header_str
->str
, sizeof(char), c
->header_str
->len
,
253 fwrite(c
->out_str
->str
, sizeof(char), c
->out_str
->len
,
256 fwrite(c
->signature_str
->str
, sizeof(char), c
->signature_str
->len
,
258 fprintf(c
->defines_file
, ";\n");
261 static void gen_c_int_type(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
262 HexSignedness signedness
)
264 const char *signstr
= (signedness
== UNSIGNED
) ? "u" : "";
265 OUT(c
, locp
, signstr
, "int", &bit_width
, "_t");
268 static HexValue
gen_constant(Context
*c
,
272 HexSignedness signedness
)
275 assert(bit_width
== 32 || bit_width
== 64);
276 memset(&rvalue
, 0, sizeof(HexValue
));
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");
288 /* Temporary values creation */
289 HexValue
gen_tmp(Context
*c
,
292 HexSignedness signedness
)
295 assert(bit_width
== 32 || bit_width
== 64);
296 memset(&rvalue
, 0, sizeof(HexValue
));
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");
308 static HexValue
gen_constant_from_imm(Context
*c
,
313 assert(value
->type
== IMMEDIATE
);
314 memset(&rvalue
, 0, sizeof(HexValue
));
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
;
321 * Here we output the call to `tcg_constant_i<width>` in
322 * order to create the temporary value. Note, that we
325 * `tcg_constant_i<width>`((int<width>_t) ...)`
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
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");
340 HexValue
gen_imm_value(Context
*c
__attribute__((unused
)),
344 HexSignedness signedness
)
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
;
359 HexValue
gen_imm_qemu_tmp(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
360 HexSignedness signedness
)
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
++;
375 HexValue
rvalue_materialize(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
377 if (rvalue
->type
== IMMEDIATE
) {
378 return gen_constant_from_imm(c
, locp
, rvalue
);
383 HexValue
gen_rvalue_extend(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
385 assert_signedness(c
, locp
, rvalue
->signedness
);
386 if (rvalue
->bit_width
> 32) {
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");
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");
410 HexValue
gen_rvalue_truncate(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
412 if (rvalue
->type
== IMMEDIATE
) {
413 HexValue res
= *rvalue
;
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");
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.
432 static bool try_find_variable(Context
*c
, YYLTYPE
*locp
,
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
)) {
443 dst
->var
.name
= curr
->name
;
444 dst
->bit_width
= curr
->bit_width
;
445 dst
->signedness
= curr
->signedness
;
453 /* Calls `try_find_variable` and asserts succcess. */
454 static void find_variable(Context
*c
, YYLTYPE
*locp
,
458 bool found
= try_find_variable(c
, locp
, dst
, varid
);
459 yyassert(c
, locp
, found
, "Use of undeclared variable!\n");
462 /* Handle signedness, if both unsigned -> result is unsigned, else signed */
463 static inline HexSignedness
bin_op_signedness(Context
*c
, YYLTYPE
*locp
,
467 assert_signedness(c
, locp
, sign1
);
468 assert_signedness(c
, locp
, sign2
);
469 return (sign1
== UNSIGNED
&& sign2
== UNSIGNED
) ? UNSIGNED
: SIGNED
;
472 void gen_varid_allocate(Context
*c
,
476 HexSignedness signedness
)
478 const char *bit_suffix
= (bit_width
== 64) ? "i64" : "i32";
479 bool found
= try_find_variable(c
, locp
, NULL
, varid
);
482 memset(&new_var
, 0, sizeof(Var
));
484 yyassert(c
, locp
, !found
, "Redeclaration of variables not allowed!");
485 assert_signedness(c
, locp
, signedness
);
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
;
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
);
504 HexValue
gen_bin_cmp(Context
*c
,
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
);
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
);
520 /* Extend to 64-bits, if required */
522 op1_m
= gen_rvalue_extend(c
, locp
, &op1_m
);
523 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
529 yyassert(c
, locp
, false, "Binary comparisons between IMM op IMM and"
530 "IMM op REG not handled!");
533 OUT(c
, locp
, "tcg_gen_setcondi_", bit_suffix
, "(");
534 OUT(c
, locp
, cond_to_str(type
), ", ", &res
, ", ", &op1_m
, ", ", &op2_m
,
538 OUT(c
, locp
, "tcg_gen_setcond_", bit_suffix
, "(");
539 OUT(c
, locp
, cond_to_str(type
), ", ", &res
, ", ", &op1_m
, ", ", &op2_m
,
543 fprintf(stderr
, "Error in evalutating immediateness!");
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
,
561 HexSignedness signedness
= bin_op_signedness(c
, locp
,
564 gen_c_int_type(c
, locp
, bit_width
, signedness
);
565 OUT(c
, locp
, " ", res
,
566 " = ", op1
, imm_imm
, op2
, ";\n");
569 OUT(c
, locp
, imm_reg
, bit_suffix
,
570 "(", res
, ", ", op2
, ", ", op1
, ");\n");
573 OUT(c
, locp
, reg_imm
, bit_suffix
,
574 "(", res
, ", ", op1
, ", ", op2
, ");\n");
577 OUT(c
, locp
, reg_reg
, bit_suffix
,
578 "(", res
, ", ", op1
, ", ", op2
, ");\n");
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
,
590 HexSignedness signedness
= bin_op_signedness(c
, locp
,
593 gen_c_int_type(c
, locp
, bit_width
, signedness
);
594 OUT(c
, locp
, " ", res
,
595 " = ", op1
, " - ", op2
, ";\n");
598 OUT(c
, locp
, "tcg_gen_subfi_", bit_suffix
,
599 "(", res
, ", ", op1
, ", ", op2
, ");\n");
602 OUT(c
, locp
, "tcg_gen_subi_", bit_suffix
,
603 "(", res
, ", ", op1
, ", ", op2
, ");\n");
606 OUT(c
, locp
, "tcg_gen_sub_", bit_suffix
,
607 "(", res
, ", ", op1
, ", ", op2
, ");\n");
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
)
617 HexValue op1_m
= *op1
;
618 HexValue op2_m
= *op2
;
621 HexSignedness signedness
= bin_op_signedness(c
, locp
,
624 gen_c_int_type(c
, locp
, bit_width
, signedness
);
625 OUT(c
, locp
, " ", res
,
626 " = ", op1
, " << ", op2
, ";\n");
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");
637 op1_m
.bit_width
= bit_width
;
638 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
641 OUT(c
, locp
, "tcg_gen_shl_", bit_suffix
,
642 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
645 if (op_types
== IMM_REG
|| op_types
== REG_REG
) {
647 * Handle left shift by 64/32 which hexagon-sim expects to clear out
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
);
654 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
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");
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
)
669 HexValue op1_m
= *op1
;
670 HexValue op2_m
= *op2
;
674 yyassert(c
, locp
, false, "ASR between IMM op IMM, and IMM op REG"
678 HexSignedness signedness
= bin_op_signedness(c
, locp
,
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");
687 OUT(c
, locp
, "tcg_gen_sari_", bit_suffix
,
688 "(", res
, ", ", op1
, ", shift);\n}\n");
691 OUT(c
, locp
, "tcg_gen_sar_", bit_suffix
,
692 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
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
);
702 edge
= rvalue_materialize(c
, locp
, &edge
);
704 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
706 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
707 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
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");
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
)
724 HexValue op1_m
= *op1
;
725 HexValue op2_m
= *op2
;
729 yyassert(c
, locp
, false, "LSR between IMM op IMM, and IMM op REG"
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");
741 OUT(c
, locp
, "tcg_gen_shr_", bit_suffix
,
742 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
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
);
751 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
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");
762 * Note: This implementation of logical `and` does not mirror that in C.
763 * We do not short-circuit logical expressions!
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
,
772 HexValue zero
= gen_constant(c
, locp
, "0", 32, UNSIGNED
);
773 memset(&tmp1
, 0, sizeof(HexValue
));
774 memset(&tmp2
, 0, sizeof(HexValue
));
779 yyassert(c
, locp
, false, "ANDL between IMM op IMM, IMM op REG, and"
780 " REG op IMM, not handled!");
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");
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
)
796 HexValue op1_m
= *op1
;
797 HexValue op2_m
= *op2
;
800 assert_signedness(c
, locp
, res
->signedness
);
801 is_unsigned
= res
->signedness
== UNSIGNED
;
805 mm
= is_unsigned
? "tcg_gen_umax" : "tcg_gen_smax";
808 mm
= is_unsigned
? "tcg_gen_umin" : "tcg_gen_smin";
812 yyassert(c
, locp
, false, "MINMAX between IMM op IMM, not handled!");
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");
821 op2_m
.bit_width
= bit_width
;
822 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
825 OUT(c
, locp
, mm
, "_i", &bit_width
, "(");
826 OUT(c
, locp
, res
, ", ", op1
, ", ", &op2_m
, ");\n");
831 /* Code generation functions */
832 HexValue
gen_bin_op(Context
*c
,
838 /* Replicate operands to avoid side effects */
839 HexValue op1_m
= *op1
;
840 HexValue op2_m
= *op2
;
841 enum OpTypes op_types
;
843 HexSignedness signedness
;
845 const char *bit_suffix
;
848 memset(&res
, 0, sizeof(HexValue
));
851 * If the operands are VARID's we need to look up the
854 if (op1_m
.type
== VARID
) {
855 find_variable(c
, locp
, &op1_m
, &op1_m
);
857 if (op2_m
.type
== VARID
) {
858 find_variable(c
, locp
, &op2_m
, &op2_m
);
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 */
866 if (type
== ASL_OP
&& op2_m
.type
== IMMEDIATE
&&
867 op2_m
.imm
.type
== VALUE
&& op2_m
.imm
.value
>= 32) {
871 bit_width
= (op_is64bit
) ? 64 : 32;
872 bit_suffix
= op_is64bit
? "i64" : "i32";
874 /* Extend to 64-bits, if required */
876 op1_m
= gen_rvalue_extend(c
, locp
, &op1_m
);
877 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
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
);
884 res
= gen_imm_qemu_tmp(c
, locp
, bit_width
, signedness
);
889 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
890 op_types
, &op1_m
, &op2_m
,
897 gen_sub_op(c
, locp
, bit_width
, bit_suffix
, &res
, op_types
,
901 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
902 op_types
, &op1_m
, &op2_m
,
909 gen_asl_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
913 gen_asr_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
917 gen_lsr_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
921 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
922 op_types
, &op1_m
, &op2_m
,
929 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
930 op_types
, &op1_m
, &op2_m
,
937 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
938 op_types
, &op1_m
, &op2_m
,
945 gen_andl_op(c
, locp
, bit_width
, bit_suffix
, &res
, op_types
, &op1_m
,
949 gen_minmax_op(c
, locp
, bit_width
, &res
, op_types
, &op1_m
, &op2_m
,
953 gen_minmax_op(c
, locp
, bit_width
, &res
, op_types
, &op1_m
, &op2_m
, true);
959 HexValue
gen_cast_op(Context
*c
,
962 unsigned target_width
,
963 HexSignedness signedness
)
965 assert_signedness(c
, locp
, src
->signedness
);
966 if (src
->bit_width
== target_width
) {
968 } else if (src
->type
== IMMEDIATE
) {
970 res
.bit_width
= target_width
;
971 res
.signedness
= signedness
;
974 HexValue res
= gen_tmp(c
, locp
, target_width
, signedness
);
976 if (src
->bit_width
> target_width
) {
977 OUT(c
, locp
, "tcg_gen_trunc_i64_tl(", &res
, ", ", src
, ");\n");
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");
986 OUT(c
, locp
, "tcg_gen_ext_i32_i64(",
987 &res
, ", ", src
, ");\n");
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`.
1001 static HexValue
gen_extend_imm_width_op(Context
*c
,
1003 HexValue
*src_width
,
1006 HexSignedness signedness
)
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.
1013 const char *sign_prefix
;
1016 assert_signedness(c
, locp
, signedness
);
1017 assert(dst_width
== 64 || dst_width
== 32);
1018 assert(src_width
->type
== IMMEDIATE
);
1020 sign_prefix
= (signedness
== UNSIGNED
) ? "" : "s";
1021 need_guarding
= (src_width
->imm
.type
!= VALUE
);
1023 if (src_width
->imm
.type
== VALUE
&&
1024 src_width
->imm
.value
== 0) {
1026 * We can bail out early if the source width is known to be zero
1027 * at translation time.
1029 return gen_imm_value(c
, locp
, 0, dst_width
, signedness
);
1032 if (value
->type
== IMMEDIATE
) {
1034 * If both the value and source width are immediates,
1035 * we can perform the extension at translation time
1036 * using QEMUs bitops.
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");
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");
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
1055 HexValue res
= gen_tmp(c
, locp
, dst_width
, signedness
);
1058 * If the width is an immediate value we know it is non-zero
1059 * at this point, otherwise we need an if-statement
1061 if (need_guarding
) {
1062 OUT(c
, locp
, "if (", src_width
, " != 0) {\n");
1064 OUT(c
, locp
, "tcg_gen_", sign_prefix
, "extract_i", &dst_width
);
1065 OUT(c
, locp
, "(", &res
, ", ", value
, ", 0, ", src_width
,
1067 if (need_guarding
) {
1068 OUT(c
, locp
, "} else {\n");
1069 OUT(c
, locp
, "tcg_gen_movi_i", &dst_width
, "(", &res
,
1071 OUT(c
, locp
, "}\n");
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.
1082 static HexValue
gen_extend_tcg_width_op(Context
*c
,
1084 HexValue
*src_width
,
1087 HexSignedness signedness
)
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
);
1094 assert_signedness(c
, locp
, signedness
);
1095 assert(dst_width
== 64 || dst_width
== 32);
1096 assert(src_width
->type
!= IMMEDIATE
);
1098 res
= gen_tmp(c
, locp
, dst_width
, signedness
);
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");
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");
1114 OUT(c
, locp
, "tcg_gen_movcond_i", &dst_width
, "(TCG_COND_EQ, ", &res
,
1116 OUT(c
, locp
, &src_width_m
, ", ", &zero
, ", ", &zero
, ", ", &res
,
1122 HexValue
gen_extend_op(Context
*c
,
1124 HexValue
*src_width
,
1127 HexSignedness signedness
)
1129 unsigned bit_width
= (dst_width
= 64) ? 64 : 32;
1130 HexValue value_m
= *value
;
1131 HexValue src_width_m
= *src_width
;
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"
1139 if (value_m
.bit_width
< bit_width
) {
1140 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1143 if (src_width_m
.bit_width
< bit_width
) {
1144 src_width_m
= gen_rvalue_extend(c
, locp
, &src_width_m
);
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
);
1151 return gen_extend_tcg_width_op(c
, locp
, &src_width_m
, bit_width
,
1152 &value_m
, signedness
);
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.
1161 * Note: this is the only type of `rdeposit` that occurs, meaning the
1162 * `width` is _NEVER_ of IMMEDIATE type.
1164 void gen_rdeposit_op(Context
*c
,
1172 * Otherwise if the width is not known, we fallback on reimplementing
1175 HexValue begin_m
= *begin
;
1176 HexValue value_m
= *value
;
1177 HexValue width_m
= *width
;
1178 const char *mask_str
= (dst
->bit_width
== 32)
1180 : "0xffffffffffffffffUL";
1181 HexValue mask
= gen_constant(c
, locp
, mask_str
, dst
->bit_width
,
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
,
1189 assert(dst
->bit_width
>= value
->bit_width
);
1190 assert(begin
->type
== IMMEDIATE
&& begin
->imm
.type
== VALUE
);
1191 assert(dst
->type
== REGISTER_ARG
);
1193 yyassert(c
, locp
, width
->type
!= IMMEDIATE
,
1194 "Immediate index to rdeposit not handled!");
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!");
1202 width_m
= rvalue_materialize(c
, locp
, &width_m
);
1205 * mask = 0xffffffffffffffff >> (64 - width)
1206 * mask = mask << begin
1207 * value = (value << begin) & mask
1210 * dst = (width != 0) ? res : dst
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
);
1218 OUT(c
, locp
, "tcg_gen_not_i", &dst
->bit_width
, "(", &mask
, ", ",
1220 res
= gen_bin_op(c
, locp
, ANDB_OP
, dst
, &mask
);
1221 res
= gen_bin_op(c
, locp
, ORB_OP
, &res
, &value_m
);
1224 * We don't need to truncate `res` here, since all operations involved use
1225 * the same bit width.
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, ",
1232 OUT(c
, locp
, ", ", &width_m
, ", ", &zero
, ", ", &res
, ", ", dst
,
1236 void gen_deposit_op(Context
*c
,
1243 HexValue value_m
= *value
;
1244 unsigned bit_width
= (dst
->bit_width
== 64) ? 64 : 32;
1245 unsigned width
= cast
->bit_width
;
1247 yyassert(c
, locp
, index
->type
== IMMEDIATE
,
1248 "Deposit index must be immediate!\n");
1251 * Using tcg_gen_deposit_i**(dst, dst, ...) requires dst to be
1254 gen_inst_init_args(c
, locp
);
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
);
1261 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
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");
1269 HexValue
gen_rextract_op(Context
*c
,
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");
1282 HexValue
gen_extract_op(Context
*c
,
1286 HexExtract
*extract
)
1288 unsigned bit_width
= (src
->bit_width
== 64) ? 64 : 32;
1289 unsigned width
= extract
->bit_width
;
1290 const char *sign_prefix
;
1293 yyassert(c
, locp
, index
->type
== IMMEDIATE
,
1294 "Extract index must be immediate!\n");
1295 assert_signedness(c
, locp
, extract
->signedness
);
1297 sign_prefix
= (extract
->signedness
== UNSIGNED
) ? "" : "s";
1298 res
= gen_tmp(c
, locp
, bit_width
, extract
->signedness
);
1300 OUT(c
, locp
, "tcg_gen_", sign_prefix
, "extract_i", &bit_width
,
1301 "(", &res
, ", ", src
);
1302 OUT(c
, locp
, ", ", index
, " * ", &width
, ", ", &width
, ");\n");
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");
1316 void gen_write_reg(Context
*c
, YYLTYPE
*locp
, HexValue
*reg
, HexValue
*value
)
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
);
1324 "gen_log_reg_write(", ®
->reg
.id
, ", ",
1328 "ctx_log_reg_write(ctx, ", ®
->reg
.id
,
1332 void gen_assign(Context
*c
,
1337 HexValue value_m
= *value
;
1340 yyassert(c
, locp
, !is_inside_ternary(c
),
1341 "Assign in ternary not allowed!");
1343 if (dst
->type
== REGISTER
) {
1344 gen_write_reg(c
, locp
, dst
, &value_m
);
1348 if (dst
->type
== VARID
) {
1349 find_variable(c
, locp
, dst
, dst
);
1351 bit_width
= dst
->bit_width
== 64 ? 64 : 32;
1353 if (bit_width
!= value_m
.bit_width
) {
1354 if (bit_width
== 64) {
1355 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1357 value_m
= gen_rvalue_truncate(c
, locp
, &value_m
);
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");
1366 HexValue
gen_convround(Context
*c
,
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
);
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
);
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");
1389 static HexValue
gen_convround_n_b(Context
*c
,
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
);
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");
1414 static HexValue
gen_convround_n_c(Context
*c
,
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
);
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");
1436 HexValue
gen_convround_n(Context
*c
,
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
);
1455 src_casted
= rvalue_materialize(c
, locp
, &src_casted
);
1456 pos_casted
= rvalue_materialize(c
, locp
, &pos_casted
);
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.
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
);
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.
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");
1484 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &n_64
, ", ", &pos_casted
, ");\n");
1487 * if the bits 0, ..., pos_casted-1 are all 0, then pick r2 otherwise,
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");
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");
1499 /* Finally shift back val >>= n */
1500 OUT(c
, locp
, "tcg_gen_shr_i64(", &res
);
1501 OUT(c
, locp
, ", ", &res
, ", ", &n_64
, ");\n");
1503 res
= gen_rvalue_truncate(c
, locp
, &res
);
1507 HexValue
gen_round(Context
*c
,
1512 HexValue zero
= gen_constant(c
, locp
, "0", 64, UNSIGNED
);
1513 HexValue one
= gen_constant(c
, locp
, "1", 64, UNSIGNED
);
1522 assert_signedness(c
, locp
, src
->signedness
);
1523 yyassert(c
, locp
, src
->bit_width
<= 32,
1524 "fRNDN not implemented for bit widths > 32!");
1526 res
= gen_tmp(c
, locp
, 64, src
->signedness
);
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
);
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
);
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
);
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");
1547 /* Circular addressing mode with auto-increment */
1548 void gen_circ_op(Context
*c
,
1551 HexValue
*increment
,
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");
1560 "gen_helper_fcircadd(",
1568 OUT(c
, locp
, ", ", &cs
, ");\n");
1571 HexValue
gen_locnt_op(Context
*c
, YYLTYPE
*locp
, HexValue
*src
)
1573 const char *bit_suffix
= src
->bit_width
== 64 ? "64" : "32";
1574 HexValue src_m
= *src
;
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");
1587 HexValue
gen_ctpop_op(Context
*c
, YYLTYPE
*locp
, HexValue
*src
)
1589 const char *bit_suffix
= src
->bit_width
== 64 ? "64" : "32";
1590 HexValue src_m
= *src
;
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");
1600 HexValue
gen_rotl(Context
*c
, YYLTYPE
*locp
, HexValue
*src
, HexValue
*width
)
1602 const char *suffix
= src
->bit_width
== 64 ? "i64" : "i32";
1603 HexValue amount
= *width
;
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
);
1610 amount
= gen_rvalue_truncate(c
, locp
, &amount
);
1612 amount
= rvalue_materialize(c
, locp
, &amount
);
1613 OUT(c
, locp
, "tcg_gen_rotl_", suffix
, "(",
1614 &res
, ", ", src
, ", ", &amount
, ");\n");
1619 HexValue
gen_carry_from_add(Context
*c
,
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
);
1633 OUT(c
, locp
, "tcg_gen_add2_i64(", &res
, ", ", &cf
, ", ", &op1_m
, ", ",
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");
1642 void gen_addsat64(Context
*c
,
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");
1653 void gen_inst(Context
*c
, GString
*iname
)
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",
1666 * Initialize declared but uninitialized registers, but only for
1667 * non-conditional instructions
1669 void gen_inst_init_args(Context
*c
, YYLTYPE
*locp
)
1671 if (!c
->inst
.init_list
) {
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
) {
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
);
1686 yyassert(c
, locp
, false, "Invalid arg type!");
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
;
1695 void gen_inst_code(Context
*c
, YYLTYPE
*locp
)
1697 if (c
->inst
.error_count
!= 0) {
1699 "Parsing of instruction %s generated %d errors!\n",
1701 c
->inst
.error_count
);
1703 c
->implemented_insn
++;
1704 fprintf(c
->enabled_file
, "%s\n", c
->inst
.name
->str
);
1708 free_instruction(c
);
1711 void gen_pred_assign(Context
*c
, YYLTYPE
*locp
, HexValue
*left_pred
,
1712 HexValue
*right_pred
)
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 */
1722 *left_pred
= gen_tmp(c
, locp
, 32, UNSIGNED
);
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
,
1729 OUT(c
, locp
, "gen_log_pred_write(ctx, ", pred_id
, ", ", left_pred
,
1731 OUT(c
, locp
, "ctx_log_pred_write(ctx, ", pred_id
, ");\n");
1735 void gen_cancel(Context
*c
, YYLTYPE
*locp
)
1737 OUT(c
, locp
, "gen_cancel(insn->slot);\n");
1740 void gen_load_cancel(Context
*c
, YYLTYPE
*locp
)
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");
1749 void gen_load(Context
*c
, YYLTYPE
*locp
, HexValue
*width
,
1750 HexSignedness signedness
, HexValue
*ea
, HexValue
*dst
)
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)
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
);
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
);
1773 if (dst
->bit_width
> width
->imm
.value
* 8) {
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.
1779 OUT(c
, locp
, "(TCGv) ");
1781 OUT(c
, locp
, dst
, ", ", ea
, ", ctx->mem_idx);\n");
1784 void gen_store(Context
*c
, YYLTYPE
*locp
, HexValue
*width
, HexValue
*ea
,
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");
1797 void gen_sethalf(Context
*c
, YYLTYPE
*locp
, HexCast
*sh
, HexValue
*n
,
1798 HexValue
*dst
, HexValue
*value
)
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
);
1806 gen_deposit_op(c
, locp
, dst
, value
, n
, sh
);
1809 void gen_setbits(Context
*c
, YYLTYPE
*locp
, HexValue
*hi
, HexValue
*lo
,
1810 HexValue
*dst
, HexValue
*value
)
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");
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
,
1830 OUT(c
, locp
, lo
, ", ", &len
, ");\n");
1833 unsigned gen_if_cond(Context
*c
, YYLTYPE
*locp
, HexValue
*cond
)
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
++;
1846 unsigned gen_if_else(Context
*c
, YYLTYPE
*locp
, unsigned index
)
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");
1859 HexValue
gen_rvalue_pred(Context
*c
, YYLTYPE
*locp
, HexValue
*pred
)
1861 /* Predicted instructions need to zero out result args */
1862 gen_inst_init_args(c
, locp
);
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
);
1870 OUT(c
, locp
, "tcg_gen_mov_i32(", pred
,
1871 ", hex_new_pred_value[");
1872 OUT(c
, locp
, pred_str
, "]);\n");
1874 OUT(c
, locp
, "gen_read_preg(", pred
, ", ", pred_str
, ");\n");
1881 HexValue
gen_rvalue_var(Context
*c
, YYLTYPE
*locp
, HexValue
*var
)
1883 find_variable(c
, locp
, var
, var
);
1887 HexValue
gen_rvalue_mpy(Context
*c
, YYLTYPE
*locp
, HexMpy
*mpy
,
1888 HexValue
*op1
, HexValue
*op2
)
1891 memset(&res
, 0, sizeof(HexValue
));
1893 assert_signedness(c
, locp
, mpy
->first_signedness
);
1894 assert_signedness(c
, locp
, mpy
->second_signedness
);
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
);
1902 *op2
= gen_cast_op(c
, locp
, op2
, mpy
->second_bit_width
* 2,
1903 mpy
->second_signedness
);
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
,
1918 static inline HexValue
gen_rvalue_simple_unary(Context
*c
, YYLTYPE
*locp
,
1921 const char *tcg_code
)
1923 unsigned bit_width
= (value
->bit_width
== 64) ? 64 : 32;
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");
1930 res
= gen_tmp(c
, locp
, bit_width
, value
->signedness
);
1931 OUT(c
, locp
, tcg_code
, "_i", &bit_width
, "(", &res
, ", ", value
,
1938 HexValue
gen_rvalue_not(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1940 return gen_rvalue_simple_unary(c
, locp
, value
, "~", "tcg_gen_not");
1943 HexValue
gen_rvalue_notl(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1945 unsigned bit_width
= (value
->bit_width
== 64) ? 64 : 32;
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");
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");
1962 HexValue
gen_rvalue_sat(Context
*c
, YYLTYPE
*locp
, HexSat
*sat
,
1963 HexValue
*width
, HexValue
*value
)
1965 const char *unsigned_str
;
1966 const char *bit_suffix
= (value
->bit_width
== 64) ? "i64" : "i32";
1970 * Note: all saturates are assumed to implicitly set overflow.
1971 * This assumption holds for the instructions currently parsed
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
);
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
,
1987 OUT(c
, locp
, "gen_set_usr_field_if(USR_OVF,", &ovfl
, ");\n");
1992 HexValue
gen_rvalue_fscr(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
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");
2005 HexValue
gen_rvalue_abs(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
2007 return gen_rvalue_simple_unary(c
, locp
, value
, "abs", "tcg_gen_abs");
2010 HexValue
gen_rvalue_neg(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
2012 return gen_rvalue_simple_unary(c
, locp
, value
, "-", "tcg_gen_neg");
2015 HexValue
gen_rvalue_brev(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
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");
2026 HexValue
gen_rvalue_ternary(Context
*c
, YYLTYPE
*locp
, HexValue
*cond
,
2027 HexValue
*true_branch
, HexValue
*false_branch
)
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
);
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
);
2040 *cond
= gen_rvalue_truncate(c
, locp
, cond
);
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
);
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");
2050 assert(c
->ternary
->len
> 0);
2051 g_array_remove_index(c
->ternary
, c
->ternary
->len
- 1);
2056 const char *cond_to_str(TCGCond cond
)
2059 case TCG_COND_NEVER
:
2060 return "TCG_COND_NEVER";
2061 case TCG_COND_ALWAYS
:
2062 return "TCG_COND_ALWAYS";
2064 return "TCG_COND_EQ";
2066 return "TCG_COND_NE";
2068 return "TCG_COND_LT";
2070 return "TCG_COND_GE";
2072 return "TCG_COND_LE";
2074 return "TCG_COND_GT";
2076 return "TCG_COND_LTU";
2078 return "TCG_COND_GEU";
2080 return "TCG_COND_LEU";
2082 return "TCG_COND_GTU";
2088 void emit_arg(Context
*c
, YYLTYPE
*locp
, HexValue
*arg
)
2090 switch (arg
->type
) {
2092 if (arg
->reg
.type
== DOTNEW
) {
2093 EMIT_SIG(c
, ", TCGv N%cN", arg
->reg
.id
);
2095 bool is64
= (arg
->bit_width
== 64);
2096 const char *type
= is64
? "TCGv_i64" : "TCGv_i32";
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");
2108 char suffix
= arg
->is_dotnew
? 'N' : 'V';
2109 EMIT_SIG(c
, ", TCGv P%c%c", arg
->pred
.id
, suffix
);
2114 fprintf(stderr
, "emit_arg got unsupported argument!");
2120 void emit_footer(Context
*c
)
2126 void track_string(Context
*c
, GString
*s
)
2128 g_array_append_val(c
->inst
.strings
, s
);
2131 void free_instruction(Context
*c
)
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
);
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
));
2151 void assert_signedness(Context
*c
,
2153 HexSignedness signedness
)
2156 signedness
!= UNKNOWN_SIGNEDNESS
,
2157 "Unspecified signedness");