2 * Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
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
, HexValue
*rvalue
)
172 HexImm
*imm
= &rvalue
->imm
;
178 EMIT(c
, "%ciV", imm
->id
);
181 if (rvalue
->bit_width
== 32) {
182 if (rvalue
->signedness
== UNSIGNED
) {
183 EMIT(c
, "((uint32_t) 0x%" PRIx32
")", (uint32_t) imm
->value
);
185 EMIT(c
, "((int32_t) 0x%" PRIx32
")", (int32_t) imm
->value
);
187 } else if (rvalue
->bit_width
== 64) {
188 if (rvalue
->signedness
== UNSIGNED
) {
189 EMIT(c
, "((uint64_t) 0x%" PRIx64
"ULL)", (uint64_t) imm
->value
);
191 EMIT(c
, "((int64_t) 0x%" PRIx64
"LL)", (int64_t) imm
->value
);
194 g_assert_not_reached();
198 EMIT(c
, "qemu_tmp_%" PRIu64
, imm
->index
);
201 EMIT(c
, "ctx->base.pc_next");
204 EMIT(c
, "insn->extension_valid");
207 yyassert(c
, locp
, false, "Cannot print this expression!");
211 void var_print(Context
*c
, YYLTYPE
*locp
, HexVar
*var
)
214 EMIT(c
, "%s", var
->name
->str
);
217 void rvalue_print(Context
*c
, YYLTYPE
*locp
, void *pointer
)
219 HexValue
*rvalue
= (HexValue
*) pointer
;
220 switch (rvalue
->type
) {
222 reg_print(c
, locp
, &rvalue
->reg
);
225 reg_arg_print(c
, locp
, &rvalue
->reg
);
228 tmp_print(c
, locp
, &rvalue
->tmp
);
231 imm_print(c
, locp
, rvalue
);
234 var_print(c
, locp
, &rvalue
->var
);
237 pred_print(c
, locp
, &rvalue
->pred
, rvalue
->is_dotnew
);
240 yyassert(c
, locp
, false, "Cannot print this expression!");
244 void out_assert(Context
*c
, YYLTYPE
*locp
,
245 void *dummy
__attribute__((unused
)))
247 yyassert(c
, locp
, false, "Unhandled print type!");
250 /* Copy output code buffer */
251 void commit(Context
*c
)
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
);
258 EMIT_SIG(c
, " " END_COMMENT
"\n");
260 /* Commit instruction code to output file */
261 fwrite(c
->signature_str
->str
, sizeof(char), c
->signature_str
->len
,
263 fwrite(c
->header_str
->str
, sizeof(char), c
->header_str
->len
,
265 fwrite(c
->out_str
->str
, sizeof(char), c
->out_str
->len
,
268 fwrite(c
->signature_str
->str
, sizeof(char), c
->signature_str
->len
,
270 fprintf(c
->defines_file
, ";\n");
273 static void gen_c_int_type(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
274 HexSignedness signedness
)
276 const char *signstr
= (signedness
== UNSIGNED
) ? "u" : "";
277 OUT(c
, locp
, signstr
, "int", &bit_width
, "_t");
280 static HexValue
gen_constant(Context
*c
,
284 HexSignedness signedness
)
287 assert(bit_width
== 32 || bit_width
== 64);
288 memset(&rvalue
, 0, sizeof(HexValue
));
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");
300 /* Temporary values creation */
301 HexValue
gen_tmp(Context
*c
,
304 HexSignedness signedness
)
307 assert(bit_width
== 32 || bit_width
== 64);
308 memset(&rvalue
, 0, sizeof(HexValue
));
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");
320 static HexValue
gen_constant_from_imm(Context
*c
,
325 assert(value
->type
== IMMEDIATE
);
326 memset(&rvalue
, 0, sizeof(HexValue
));
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
;
333 * Here we output the call to `tcg_constant_i<width>` in
334 * order to create the temporary value. Note, that we
337 * `tcg_constant_i<width>`((int<width>_t) ...)`
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
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");
352 HexValue
gen_imm_value(Context
*c
__attribute__((unused
)),
356 HexSignedness signedness
)
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
;
371 HexValue
gen_imm_qemu_tmp(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
372 HexSignedness signedness
)
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
++;
387 HexValue
rvalue_materialize(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
389 if (rvalue
->type
== IMMEDIATE
) {
390 return gen_constant_from_imm(c
, locp
, rvalue
);
395 HexValue
gen_rvalue_extend(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
397 assert_signedness(c
, locp
, rvalue
->signedness
);
398 if (rvalue
->bit_width
> 32) {
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");
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");
419 HexValue
gen_rvalue_truncate(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
421 if (rvalue
->type
== IMMEDIATE
) {
422 HexValue res
= *rvalue
;
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");
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.
441 static bool try_find_variable(Context
*c
, YYLTYPE
*locp
,
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
)) {
452 dst
->var
.name
= curr
->name
;
453 dst
->bit_width
= curr
->bit_width
;
454 dst
->signedness
= curr
->signedness
;
462 /* Calls `try_find_variable` and asserts succcess. */
463 static void find_variable(Context
*c
, YYLTYPE
*locp
,
467 bool found
= try_find_variable(c
, locp
, dst
, varid
);
468 yyassert(c
, locp
, found
, "Use of undeclared variable!\n");
471 /* Handle signedness, if both unsigned -> result is unsigned, else signed */
472 static inline HexSignedness
bin_op_signedness(Context
*c
, YYLTYPE
*locp
,
476 assert_signedness(c
, locp
, sign1
);
477 assert_signedness(c
, locp
, sign2
);
478 return (sign1
== UNSIGNED
&& sign2
== UNSIGNED
) ? UNSIGNED
: SIGNED
;
481 void gen_varid_allocate(Context
*c
,
485 HexSignedness signedness
)
487 const char *bit_suffix
= (bit_width
== 64) ? "i64" : "i32";
488 bool found
= try_find_variable(c
, locp
, NULL
, varid
);
491 memset(&new_var
, 0, sizeof(Var
));
493 yyassert(c
, locp
, !found
, "Redeclaration of variables not allowed!");
494 assert_signedness(c
, locp
, signedness
);
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
;
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
);
513 HexValue
gen_bin_cmp(Context
*c
,
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
);
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
);
529 /* Extend to 64-bits, if required */
531 op1_m
= gen_rvalue_extend(c
, locp
, &op1_m
);
532 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
538 yyassert(c
, locp
, false, "Binary comparisons between IMM op IMM and"
539 "IMM op REG not handled!");
542 OUT(c
, locp
, "tcg_gen_setcondi_", bit_suffix
, "(");
543 OUT(c
, locp
, cond_to_str(type
), ", ", &res
, ", ", &op1_m
, ", ", &op2_m
,
547 OUT(c
, locp
, "tcg_gen_setcond_", bit_suffix
, "(");
548 OUT(c
, locp
, cond_to_str(type
), ", ", &res
, ", ", &op1_m
, ", ", &op2_m
,
552 fprintf(stderr
, "Error in evalutating immediateness!");
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
,
570 HexSignedness signedness
= bin_op_signedness(c
, locp
,
573 gen_c_int_type(c
, locp
, bit_width
, signedness
);
574 OUT(c
, locp
, " ", res
,
575 " = ", op1
, imm_imm
, op2
, ";\n");
578 OUT(c
, locp
, imm_reg
, bit_suffix
,
579 "(", res
, ", ", op2
, ", ", op1
, ");\n");
582 OUT(c
, locp
, reg_imm
, bit_suffix
,
583 "(", res
, ", ", op1
, ", ", op2
, ");\n");
586 OUT(c
, locp
, reg_reg
, bit_suffix
,
587 "(", res
, ", ", op1
, ", ", op2
, ");\n");
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
,
599 HexSignedness signedness
= bin_op_signedness(c
, locp
,
602 gen_c_int_type(c
, locp
, bit_width
, signedness
);
603 OUT(c
, locp
, " ", res
,
604 " = ", op1
, " - ", op2
, ";\n");
607 OUT(c
, locp
, "tcg_gen_subfi_", bit_suffix
,
608 "(", res
, ", ", op1
, ", ", op2
, ");\n");
611 OUT(c
, locp
, "tcg_gen_subi_", bit_suffix
,
612 "(", res
, ", ", op1
, ", ", op2
, ");\n");
615 OUT(c
, locp
, "tcg_gen_sub_", bit_suffix
,
616 "(", res
, ", ", op1
, ", ", op2
, ");\n");
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
)
626 HexValue op1_m
= *op1
;
627 HexValue op2_m
= *op2
;
630 HexSignedness signedness
= bin_op_signedness(c
, locp
,
633 gen_c_int_type(c
, locp
, bit_width
, signedness
);
634 OUT(c
, locp
, " ", res
,
635 " = ", op1
, " << ", op2
, ";\n");
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");
646 op1_m
.bit_width
= bit_width
;
647 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
650 OUT(c
, locp
, "tcg_gen_shl_", bit_suffix
,
651 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
654 if (op_types
== IMM_REG
|| op_types
== REG_REG
) {
656 * Handle left shift by 64/32 which hexagon-sim expects to clear out
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
);
663 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
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");
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
)
678 HexValue op1_m
= *op1
;
679 HexValue op2_m
= *op2
;
683 yyassert(c
, locp
, false, "ASR between IMM op IMM, and IMM op REG"
687 HexSignedness signedness
= bin_op_signedness(c
, locp
,
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");
696 OUT(c
, locp
, "tcg_gen_sari_", bit_suffix
,
697 "(", res
, ", ", op1
, ", shift);\n}\n");
700 OUT(c
, locp
, "tcg_gen_sar_", bit_suffix
,
701 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
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
);
711 edge
= rvalue_materialize(c
, locp
, &edge
);
713 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
715 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
716 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
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");
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
)
733 HexValue op1_m
= *op1
;
734 HexValue op2_m
= *op2
;
738 yyassert(c
, locp
, false, "LSR between IMM op IMM, and IMM op REG"
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");
750 OUT(c
, locp
, "tcg_gen_shr_", bit_suffix
,
751 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
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
);
760 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
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");
771 * Note: This implementation of logical `and` does not mirror that in C.
772 * We do not short-circuit logical expressions!
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
,
781 HexValue zero
= gen_constant(c
, locp
, "0", 32, UNSIGNED
);
782 memset(&tmp1
, 0, sizeof(HexValue
));
783 memset(&tmp2
, 0, sizeof(HexValue
));
788 yyassert(c
, locp
, false, "ANDL between IMM op IMM, IMM op REG, and"
789 " REG op IMM, not handled!");
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");
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
)
805 HexValue op1_m
= *op1
;
806 HexValue op2_m
= *op2
;
809 assert_signedness(c
, locp
, res
->signedness
);
810 is_unsigned
= res
->signedness
== UNSIGNED
;
814 mm
= is_unsigned
? "tcg_gen_umax" : "tcg_gen_smax";
817 mm
= is_unsigned
? "tcg_gen_umin" : "tcg_gen_smin";
821 yyassert(c
, locp
, false, "MINMAX between IMM op IMM, not handled!");
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");
830 op2_m
.bit_width
= bit_width
;
831 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
834 OUT(c
, locp
, mm
, "_i", &bit_width
, "(");
835 OUT(c
, locp
, res
, ", ", op1
, ", ", &op2_m
, ");\n");
840 /* Code generation functions */
841 HexValue
gen_bin_op(Context
*c
,
847 /* Replicate operands to avoid side effects */
848 HexValue op1_m
= *op1
;
849 HexValue op2_m
= *op2
;
850 enum OpTypes op_types
;
852 HexSignedness signedness
;
854 const char *bit_suffix
;
857 memset(&res
, 0, sizeof(HexValue
));
860 * If the operands are VARID's we need to look up the
863 if (op1_m
.type
== VARID
) {
864 find_variable(c
, locp
, &op1_m
, &op1_m
);
866 if (op2_m
.type
== VARID
) {
867 find_variable(c
, locp
, &op2_m
, &op2_m
);
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 */
875 if (type
== ASL_OP
&& op2_m
.type
== IMMEDIATE
&&
876 op2_m
.imm
.type
== VALUE
&& op2_m
.imm
.value
>= 32) {
880 bit_width
= (op_is64bit
) ? 64 : 32;
881 bit_suffix
= op_is64bit
? "i64" : "i32";
883 /* Extend to 64-bits, if required */
885 op1_m
= gen_rvalue_extend(c
, locp
, &op1_m
);
886 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
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
);
893 res
= gen_imm_qemu_tmp(c
, locp
, bit_width
, signedness
);
898 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
899 op_types
, &op1_m
, &op2_m
,
906 gen_sub_op(c
, locp
, bit_width
, bit_suffix
, &res
, op_types
,
910 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
911 op_types
, &op1_m
, &op2_m
,
918 gen_asl_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
922 gen_asr_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
926 gen_lsr_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
930 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
931 op_types
, &op1_m
, &op2_m
,
938 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
939 op_types
, &op1_m
, &op2_m
,
946 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
947 op_types
, &op1_m
, &op2_m
,
954 gen_andl_op(c
, locp
, bit_width
, bit_suffix
, &res
, op_types
, &op1_m
,
958 gen_minmax_op(c
, locp
, bit_width
, &res
, op_types
, &op1_m
, &op2_m
,
962 gen_minmax_op(c
, locp
, bit_width
, &res
, op_types
, &op1_m
, &op2_m
, true);
968 HexValue
gen_cast_op(Context
*c
,
971 unsigned target_width
,
972 HexSignedness signedness
)
975 assert_signedness(c
, locp
, src
->signedness
);
976 if (src
->bit_width
== target_width
) {
978 } else if (src
->bit_width
< target_width
) {
979 res
= gen_rvalue_extend(c
, locp
, src
);
981 /* src->bit_width > target_width */
982 res
= gen_rvalue_truncate(c
, locp
, src
);
984 res
.signedness
= signedness
;
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`.
995 static HexValue
gen_extend_imm_width_op(Context
*c
,
1000 HexSignedness signedness
)
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.
1007 const char *sign_prefix
;
1010 assert_signedness(c
, locp
, signedness
);
1011 assert(dst_width
== 64 || dst_width
== 32);
1012 assert(src_width
->type
== IMMEDIATE
);
1014 sign_prefix
= (signedness
== UNSIGNED
) ? "" : "s";
1015 need_guarding
= (src_width
->imm
.type
!= VALUE
);
1017 if (src_width
->imm
.type
== VALUE
&&
1018 src_width
->imm
.value
== 0) {
1020 * We can bail out early if the source width is known to be zero
1021 * at translation time.
1023 return gen_imm_value(c
, locp
, 0, dst_width
, signedness
);
1026 if (value
->type
== IMMEDIATE
) {
1028 * If both the value and source width are immediates,
1029 * we can perform the extension at translation time
1030 * using QEMUs bitops.
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");
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");
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
1049 HexValue res
= gen_tmp(c
, locp
, dst_width
, signedness
);
1052 * If the width is an immediate value we know it is non-zero
1053 * at this point, otherwise we need an if-statement
1055 if (need_guarding
) {
1056 OUT(c
, locp
, "if (", src_width
, " != 0) {\n");
1058 OUT(c
, locp
, "tcg_gen_", sign_prefix
, "extract_i", &dst_width
);
1059 OUT(c
, locp
, "(", &res
, ", ", value
, ", 0, ", src_width
,
1061 if (need_guarding
) {
1062 OUT(c
, locp
, "} else {\n");
1063 OUT(c
, locp
, "tcg_gen_movi_i", &dst_width
, "(", &res
,
1065 OUT(c
, locp
, "}\n");
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.
1076 static HexValue
gen_extend_tcg_width_op(Context
*c
,
1078 HexValue
*src_width
,
1081 HexSignedness signedness
)
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
);
1088 assert_signedness(c
, locp
, signedness
);
1089 assert(dst_width
== 64 || dst_width
== 32);
1090 assert(src_width
->type
!= IMMEDIATE
);
1092 res
= gen_tmp(c
, locp
, dst_width
, signedness
);
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");
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");
1108 OUT(c
, locp
, "tcg_gen_movcond_i", &dst_width
, "(TCG_COND_EQ, ", &res
,
1110 OUT(c
, locp
, &src_width_m
, ", ", &zero
, ", ", &zero
, ", ", &res
,
1116 HexValue
gen_extend_op(Context
*c
,
1118 HexValue
*src_width
,
1121 HexSignedness signedness
)
1123 unsigned bit_width
= (dst_width
== 64) ? 64 : 32;
1124 HexValue value_m
= *value
;
1125 HexValue src_width_m
= *src_width
;
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"
1133 if (value_m
.bit_width
< bit_width
) {
1134 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1137 if (src_width_m
.bit_width
< bit_width
) {
1138 src_width_m
= gen_rvalue_extend(c
, locp
, &src_width_m
);
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
);
1145 return gen_extend_tcg_width_op(c
, locp
, &src_width_m
, bit_width
,
1146 &value_m
, signedness
);
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.
1155 * Note: this is the only type of `rdeposit` that occurs, meaning the
1156 * `width` is _NEVER_ of IMMEDIATE type.
1158 void gen_rdeposit_op(Context
*c
,
1166 * Otherwise if the width is not known, we fallback on reimplementing
1169 HexValue begin_m
= *begin
;
1170 HexValue value_m
= *value
;
1171 HexValue width_m
= *width
;
1172 const char *mask_str
= (dst
->bit_width
== 32)
1174 : "0xffffffffffffffffUL";
1175 HexValue mask
= gen_constant(c
, locp
, mask_str
, dst
->bit_width
,
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
,
1183 assert(dst
->bit_width
>= value
->bit_width
);
1184 assert(begin
->type
== IMMEDIATE
&& begin
->imm
.type
== VALUE
);
1185 assert(dst
->type
== REGISTER_ARG
);
1187 yyassert(c
, locp
, width
->type
!= IMMEDIATE
,
1188 "Immediate index to rdeposit not handled!");
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!");
1196 width_m
= rvalue_materialize(c
, locp
, &width_m
);
1199 * mask = 0xffffffffffffffff >> (64 - width)
1200 * mask = mask << begin
1201 * value = (value << begin) & mask
1204 * dst = (width != 0) ? res : dst
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
);
1212 OUT(c
, locp
, "tcg_gen_not_i", &dst
->bit_width
, "(", &mask
, ", ",
1214 res
= gen_bin_op(c
, locp
, ANDB_OP
, dst
, &mask
);
1215 res
= gen_bin_op(c
, locp
, ORB_OP
, &res
, &value_m
);
1218 * We don't need to truncate `res` here, since all operations involved use
1219 * the same bit width.
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, ",
1226 OUT(c
, locp
, ", ", &width_m
, ", ", &zero
, ", ", &res
, ", ", dst
,
1230 void gen_deposit_op(Context
*c
,
1237 HexValue value_m
= *value
;
1238 unsigned bit_width
= (dst
->bit_width
== 64) ? 64 : 32;
1239 unsigned width
= cast
->bit_width
;
1241 yyassert(c
, locp
, index
->type
== IMMEDIATE
,
1242 "Deposit index must be immediate!\n");
1245 * Using tcg_gen_deposit_i**(dst, dst, ...) requires dst to be
1248 gen_inst_init_args(c
, locp
);
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
);
1255 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
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");
1263 HexValue
gen_rextract_op(Context
*c
,
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");
1276 HexValue
gen_extract_op(Context
*c
,
1280 HexExtract
*extract
)
1282 unsigned bit_width
= (src
->bit_width
== 64) ? 64 : 32;
1283 unsigned width
= extract
->bit_width
;
1284 const char *sign_prefix
;
1287 yyassert(c
, locp
, index
->type
== IMMEDIATE
,
1288 "Extract index must be immediate!\n");
1289 assert_signedness(c
, locp
, extract
->signedness
);
1291 sign_prefix
= (extract
->signedness
== UNSIGNED
) ? "" : "s";
1292 res
= gen_tmp(c
, locp
, bit_width
, extract
->signedness
);
1294 OUT(c
, locp
, "tcg_gen_", sign_prefix
, "extract_i", &bit_width
,
1295 "(", &res
, ", ", src
);
1296 OUT(c
, locp
, ", ", index
, " * ", &width
, ", ", &width
, ");\n");
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");
1310 void gen_write_reg(Context
*c
, YYLTYPE
*locp
, HexValue
*reg
, HexValue
*value
)
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
);
1318 "gen_log_reg_write(ctx, ", ®
->reg
.id
, ", ",
1322 void gen_assign(Context
*c
,
1327 HexValue value_m
= *value
;
1330 yyassert(c
, locp
, !is_inside_ternary(c
),
1331 "Assign in ternary not allowed!");
1333 if (dst
->type
== REGISTER
) {
1334 gen_write_reg(c
, locp
, dst
, &value_m
);
1338 if (dst
->type
== VARID
) {
1339 find_variable(c
, locp
, dst
, dst
);
1341 bit_width
= dst
->bit_width
== 64 ? 64 : 32;
1343 if (bit_width
!= value_m
.bit_width
) {
1344 if (bit_width
== 64) {
1345 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1347 value_m
= gen_rvalue_truncate(c
, locp
, &value_m
);
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");
1356 HexValue
gen_convround(Context
*c
,
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
);
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
);
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");
1379 static HexValue
gen_convround_n_b(Context
*c
,
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
);
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");
1404 static HexValue
gen_convround_n_c(Context
*c
,
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
);
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");
1426 HexValue
gen_convround_n(Context
*c
,
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
);
1445 src_casted
= rvalue_materialize(c
, locp
, &src_casted
);
1446 pos_casted
= rvalue_materialize(c
, locp
, &pos_casted
);
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.
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
);
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.
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");
1474 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &n_64
, ", ", &pos_casted
, ");\n");
1477 * if the bits 0, ..., pos_casted-1 are all 0, then pick r2 otherwise,
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");
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");
1489 /* Finally shift back val >>= n */
1490 OUT(c
, locp
, "tcg_gen_shr_i64(", &res
);
1491 OUT(c
, locp
, ", ", &res
, ", ", &n_64
, ");\n");
1493 res
= gen_rvalue_truncate(c
, locp
, &res
);
1497 HexValue
gen_round(Context
*c
,
1502 HexValue zero
= gen_constant(c
, locp
, "0", 64, UNSIGNED
);
1503 HexValue one
= gen_constant(c
, locp
, "1", 64, UNSIGNED
);
1512 assert_signedness(c
, locp
, src
->signedness
);
1513 yyassert(c
, locp
, src
->bit_width
<= 32,
1514 "fRNDN not implemented for bit widths > 32!");
1516 res
= gen_tmp(c
, locp
, 64, src
->signedness
);
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
);
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
);
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
);
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");
1537 /* Circular addressing mode with auto-increment */
1538 void gen_circ_op(Context
*c
,
1541 HexValue
*increment
,
1544 HexValue cs
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1545 HexValue increment_m
= *increment
;
1546 increment_m
= rvalue_materialize(c
, locp
, &increment_m
);
1547 OUT(c
, locp
, "gen_read_reg(", &cs
, ", HEX_REG_CS0 + MuN);\n");
1550 "gen_helper_fcircadd(",
1558 OUT(c
, locp
, ", ", &cs
, ");\n");
1561 HexValue
gen_locnt_op(Context
*c
, YYLTYPE
*locp
, HexValue
*src
)
1563 const char *bit_suffix
= src
->bit_width
== 64 ? "64" : "32";
1564 HexValue src_m
= *src
;
1567 assert_signedness(c
, locp
, src
->signedness
);
1568 res
= gen_tmp(c
, locp
, src
->bit_width
== 64 ? 64 : 32, src
->signedness
);
1569 src_m
= rvalue_materialize(c
, locp
, &src_m
);
1570 OUT(c
, locp
, "tcg_gen_not_i", bit_suffix
, "(",
1571 &res
, ", ", &src_m
, ");\n");
1572 OUT(c
, locp
, "tcg_gen_clzi_i", bit_suffix
, "(", &res
, ", ", &res
, ", ");
1573 OUT(c
, locp
, bit_suffix
, ");\n");
1577 HexValue
gen_ctpop_op(Context
*c
, YYLTYPE
*locp
, HexValue
*src
)
1579 const char *bit_suffix
= src
->bit_width
== 64 ? "64" : "32";
1580 HexValue src_m
= *src
;
1582 assert_signedness(c
, locp
, src
->signedness
);
1583 res
= gen_tmp(c
, locp
, src
->bit_width
== 64 ? 64 : 32, src
->signedness
);
1584 src_m
= rvalue_materialize(c
, locp
, &src_m
);
1585 OUT(c
, locp
, "tcg_gen_ctpop_i", bit_suffix
,
1586 "(", &res
, ", ", &src_m
, ");\n");
1590 HexValue
gen_rotl(Context
*c
, YYLTYPE
*locp
, HexValue
*src
, HexValue
*width
)
1592 const char *suffix
= src
->bit_width
== 64 ? "i64" : "i32";
1593 HexValue amount
= *width
;
1595 assert_signedness(c
, locp
, src
->signedness
);
1596 res
= gen_tmp(c
, locp
, src
->bit_width
, src
->signedness
);
1597 if (amount
.bit_width
< src
->bit_width
) {
1598 amount
= gen_rvalue_extend(c
, locp
, &amount
);
1600 amount
= gen_rvalue_truncate(c
, locp
, &amount
);
1602 amount
= rvalue_materialize(c
, locp
, &amount
);
1603 OUT(c
, locp
, "tcg_gen_rotl_", suffix
, "(",
1604 &res
, ", ", src
, ", ", &amount
, ");\n");
1609 HexValue
gen_carry_from_add(Context
*c
,
1615 HexValue zero
= gen_constant(c
, locp
, "0", 64, UNSIGNED
);
1616 HexValue res
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1617 HexValue cf
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1618 HexValue op1_m
= rvalue_materialize(c
, locp
, op1
);
1619 HexValue op2_m
= rvalue_materialize(c
, locp
, op2
);
1620 HexValue op3_m
= rvalue_materialize(c
, locp
, op3
);
1621 op3_m
= gen_rvalue_extend(c
, locp
, &op3_m
);
1623 OUT(c
, locp
, "tcg_gen_add2_i64(", &res
, ", ", &cf
, ", ", &op1_m
, ", ",
1625 OUT(c
, locp
, ", ", &op3_m
, ", ", &zero
, ");\n");
1626 OUT(c
, locp
, "tcg_gen_add2_i64(", &res
, ", ", &cf
, ", ", &res
, ", ", &cf
);
1627 OUT(c
, locp
, ", ", &op2_m
, ", ", &zero
, ");\n");
1632 void gen_addsat64(Context
*c
,
1638 HexValue op1_m
= rvalue_materialize(c
, locp
, op1
);
1639 HexValue op2_m
= rvalue_materialize(c
, locp
, op2
);
1640 OUT(c
, locp
, "gen_add_sat_i64(ctx, ", dst
, ", ", &op1_m
, ", ",
1644 void gen_inst(Context
*c
, GString
*iname
)
1647 c
->inst
.name
= iname
;
1648 c
->inst
.allocated
= g_array_new(FALSE
, FALSE
, sizeof(Var
));
1649 c
->inst
.init_list
= g_array_new(FALSE
, FALSE
, sizeof(HexValue
));
1650 c
->inst
.strings
= g_array_new(FALSE
, FALSE
, sizeof(GString
*));
1651 EMIT_SIG(c
, "void emit_%s(DisasContext *ctx, Insn *insn, Packet *pkt",
1657 * Initialize declared but uninitialized registers, but only for
1658 * non-conditional instructions
1660 void gen_inst_init_args(Context
*c
, YYLTYPE
*locp
)
1662 if (!c
->inst
.init_list
) {
1666 for (unsigned i
= 0; i
< c
->inst
.init_list
->len
; i
++) {
1667 HexValue
*val
= &g_array_index(c
->inst
.init_list
, HexValue
, i
);
1668 if (val
->type
== REGISTER_ARG
) {
1669 /* Nothing to do here */
1670 } else if (val
->type
== PREDICATE
) {
1671 char suffix
= val
->is_dotnew
? 'N' : 'V';
1672 EMIT_HEAD(c
, "tcg_gen_movi_i%u(P%c%c, 0);\n", val
->bit_width
,
1673 val
->pred
.id
, suffix
);
1675 yyassert(c
, locp
, false, "Invalid arg type!");
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
;
1684 void gen_inst_code(Context
*c
, YYLTYPE
*locp
)
1686 if (c
->inst
.error_count
!= 0) {
1688 "Parsing of instruction %s generated %d errors!\n",
1690 c
->inst
.error_count
);
1692 c
->implemented_insn
++;
1693 fprintf(c
->enabled_file
, "%s\n", c
->inst
.name
->str
);
1697 free_instruction(c
);
1700 void gen_pred_assign(Context
*c
, YYLTYPE
*locp
, HexValue
*left_pred
,
1701 HexValue
*right_pred
)
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 */
1711 *left_pred
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1713 /* Extract first 8 bits, and store new predicate value */
1714 OUT(c
, locp
, "tcg_gen_andi_i32(", left_pred
, ", ", &r
, ", 0xff);\n");
1716 OUT(c
, locp
, "gen_log_pred_write(ctx, ", pred_id
, ", ", left_pred
,
1721 void gen_cancel(Context
*c
, YYLTYPE
*locp
)
1723 OUT(c
, locp
, "gen_cancel(insn->slot);\n");
1726 void gen_load_cancel(Context
*c
, YYLTYPE
*locp
)
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");
1734 void gen_load(Context
*c
, YYLTYPE
*locp
, HexValue
*width
,
1735 HexSignedness signedness
, HexValue
*ea
, HexValue
*dst
)
1737 unsigned dst_bit_width
;
1738 unsigned src_bit_width
;
1740 /* Memop width is specified in the load macro */
1741 assert_signedness(c
, locp
, signedness
);
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
);
1748 src_bit_width
= width
->imm
.value
* 8;
1749 dst_bit_width
= MAX(dst
->bit_width
, 32);
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");
1758 OUT(c
, locp
, "tcg_gen_qemu_ld_i", &dst_bit_width
);
1760 OUT(c
, locp
, dst
, ", ", ea
, ", ctx->mem_idx, MO_", &src_bit_width
);
1761 if (signedness
== SIGNED
) {
1762 OUT(c
, locp
, " | MO_SIGN");
1764 OUT(c
, locp
, " | MO_TE);\n");
1767 void gen_store(Context
*c
, YYLTYPE
*locp
, HexValue
*width
, HexValue
*ea
,
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
, "(cpu_env, ", ea
, ", ", &src_m
);
1777 OUT(c
, locp
, ", insn->slot);\n");
1780 void gen_sethalf(Context
*c
, YYLTYPE
*locp
, HexCast
*sh
, HexValue
*n
,
1781 HexValue
*dst
, HexValue
*value
)
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
);
1789 gen_deposit_op(c
, locp
, dst
, value
, n
, sh
);
1792 void gen_setbits(Context
*c
, YYLTYPE
*locp
, HexValue
*hi
, HexValue
*lo
,
1793 HexValue
*dst
, HexValue
*value
)
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");
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
,
1813 OUT(c
, locp
, lo
, ", ", &len
, ");\n");
1816 unsigned gen_if_cond(Context
*c
, YYLTYPE
*locp
, HexValue
*cond
)
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
++;
1829 unsigned gen_if_else(Context
*c
, YYLTYPE
*locp
, unsigned index
)
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");
1842 HexValue
gen_rvalue_pred(Context
*c
, YYLTYPE
*locp
, HexValue
*pred
)
1844 /* Predicted instructions need to zero out result args */
1845 gen_inst_init_args(c
, locp
);
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
);
1853 OUT(c
, locp
, "tcg_gen_mov_i32(", pred
,
1854 ", ctx->new_pred_value[");
1855 OUT(c
, locp
, pred_str
, "]);\n");
1857 OUT(c
, locp
, "gen_read_preg(", pred
, ", ", pred_str
, ");\n");
1864 HexValue
gen_rvalue_var(Context
*c
, YYLTYPE
*locp
, HexValue
*var
)
1866 find_variable(c
, locp
, var
, var
);
1870 HexValue
gen_rvalue_mpy(Context
*c
, YYLTYPE
*locp
, HexMpy
*mpy
,
1871 HexValue
*op1
, HexValue
*op2
)
1874 memset(&res
, 0, sizeof(HexValue
));
1876 assert_signedness(c
, locp
, mpy
->first_signedness
);
1877 assert_signedness(c
, locp
, mpy
->second_signedness
);
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
);
1885 *op2
= gen_cast_op(c
, locp
, op2
, mpy
->second_bit_width
* 2,
1886 mpy
->second_signedness
);
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
,
1901 static inline HexValue
gen_rvalue_simple_unary(Context
*c
, YYLTYPE
*locp
,
1904 const char *tcg_code
)
1906 unsigned bit_width
= (value
->bit_width
== 64) ? 64 : 32;
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");
1913 res
= gen_tmp(c
, locp
, bit_width
, value
->signedness
);
1914 OUT(c
, locp
, tcg_code
, "_i", &bit_width
, "(", &res
, ", ", value
,
1921 HexValue
gen_rvalue_not(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1923 return gen_rvalue_simple_unary(c
, locp
, value
, "~", "tcg_gen_not");
1926 HexValue
gen_rvalue_notl(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1928 unsigned bit_width
= (value
->bit_width
== 64) ? 64 : 32;
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");
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");
1945 HexValue
gen_rvalue_sat(Context
*c
, YYLTYPE
*locp
, HexSat
*sat
,
1946 HexValue
*width
, HexValue
*value
)
1948 const char *unsigned_str
;
1949 const char *bit_suffix
= (value
->bit_width
== 64) ? "i64" : "i32";
1953 * Note: all saturates are assumed to implicitly set overflow.
1954 * This assumption holds for the instructions currently parsed
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
);
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
,
1970 OUT(c
, locp
, "gen_set_usr_field_if(ctx, USR_OVF,", &ovfl
, ");\n");
1975 HexValue
gen_rvalue_fscr(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
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");
1988 HexValue
gen_rvalue_abs(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1990 return gen_rvalue_simple_unary(c
, locp
, value
, "abs", "tcg_gen_abs");
1993 HexValue
gen_rvalue_neg(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1995 return gen_rvalue_simple_unary(c
, locp
, value
, "-", "tcg_gen_neg");
1998 HexValue
gen_rvalue_brev(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
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");
2009 HexValue
gen_rvalue_ternary(Context
*c
, YYLTYPE
*locp
, HexValue
*cond
,
2010 HexValue
*true_branch
, HexValue
*false_branch
)
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
);
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
);
2023 *cond
= gen_rvalue_truncate(c
, locp
, cond
);
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
);
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");
2033 assert(c
->ternary
->len
> 0);
2034 g_array_remove_index(c
->ternary
, c
->ternary
->len
- 1);
2039 const char *cond_to_str(TCGCond cond
)
2042 case TCG_COND_NEVER
:
2043 return "TCG_COND_NEVER";
2044 case TCG_COND_ALWAYS
:
2045 return "TCG_COND_ALWAYS";
2047 return "TCG_COND_EQ";
2049 return "TCG_COND_NE";
2051 return "TCG_COND_LT";
2053 return "TCG_COND_GE";
2055 return "TCG_COND_LE";
2057 return "TCG_COND_GT";
2059 return "TCG_COND_LTU";
2061 return "TCG_COND_GEU";
2063 return "TCG_COND_LEU";
2065 return "TCG_COND_GTU";
2071 void emit_arg(Context
*c
, YYLTYPE
*locp
, HexValue
*arg
)
2073 switch (arg
->type
) {
2075 if (arg
->reg
.type
== DOTNEW
) {
2076 EMIT_SIG(c
, ", TCGv N%cN", arg
->reg
.id
);
2078 bool is64
= (arg
->bit_width
== 64);
2079 const char *type
= is64
? "TCGv_i64" : "TCGv_i32";
2081 reg_compose(c
, locp
, &(arg
->reg
), reg_id
);
2082 EMIT_SIG(c
, ", %s %s", type
, reg_id
);
2083 /* MuV register requires also MuN to provide its index */
2084 if (arg
->reg
.type
== MODIFIER
) {
2085 EMIT_SIG(c
, ", int MuN");
2091 char suffix
= arg
->is_dotnew
? 'N' : 'V';
2092 EMIT_SIG(c
, ", TCGv P%c%c", arg
->pred
.id
, suffix
);
2097 fprintf(stderr
, "emit_arg got unsupported argument!");
2103 void emit_footer(Context
*c
)
2109 void track_string(Context
*c
, GString
*s
)
2111 g_array_append_val(c
->inst
.strings
, s
);
2114 void free_instruction(Context
*c
)
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
);
2125 g_array_free(c
->inst
.strings
, TRUE
);
2126 /* Free INAME token value */
2127 g_string_free(c
->inst
.name
, TRUE
);
2128 /* Free variables and registers */
2129 g_array_free(c
->inst
.allocated
, TRUE
);
2130 /* Initialize instruction-specific portion of the context */
2131 memset(&(c
->inst
), 0, sizeof(Inst
));
2134 void assert_signedness(Context
*c
,
2136 HexSignedness signedness
)
2139 signedness
!= UNKNOWN_SIGNEDNESS
,
2140 "Unspecified signedness");