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
, 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");
189 EMIT(c
, "insn->extension_valid");
192 yyassert(c
, locp
, false, "Cannot print this expression!");
196 void var_print(Context
*c
, YYLTYPE
*locp
, HexVar
*var
)
199 EMIT(c
, "%s", var
->name
->str
);
202 void rvalue_print(Context
*c
, YYLTYPE
*locp
, void *pointer
)
204 HexValue
*rvalue
= (HexValue
*) pointer
;
205 switch (rvalue
->type
) {
207 reg_print(c
, locp
, &rvalue
->reg
);
210 reg_arg_print(c
, locp
, &rvalue
->reg
);
213 tmp_print(c
, locp
, &rvalue
->tmp
);
216 imm_print(c
, locp
, &rvalue
->imm
);
219 var_print(c
, locp
, &rvalue
->var
);
222 pred_print(c
, locp
, &rvalue
->pred
, rvalue
->is_dotnew
);
225 yyassert(c
, locp
, false, "Cannot print this expression!");
229 void out_assert(Context
*c
, YYLTYPE
*locp
,
230 void *dummy
__attribute__((unused
)))
232 yyassert(c
, locp
, false, "Unhandled print type!");
235 /* Copy output code buffer */
236 void commit(Context
*c
)
238 /* Emit instruction pseudocode */
239 EMIT_SIG(c
, "\n" START_COMMENT
" ");
240 for (char *x
= c
->inst
.code_begin
; x
< c
->inst
.code_end
; x
++) {
241 EMIT_SIG(c
, "%c", *x
);
243 EMIT_SIG(c
, " " END_COMMENT
"\n");
245 /* Commit instruction code to output file */
246 fwrite(c
->signature_str
->str
, sizeof(char), c
->signature_str
->len
,
248 fwrite(c
->header_str
->str
, sizeof(char), c
->header_str
->len
,
250 fwrite(c
->out_str
->str
, sizeof(char), c
->out_str
->len
,
253 fwrite(c
->signature_str
->str
, sizeof(char), c
->signature_str
->len
,
255 fprintf(c
->defines_file
, ";\n");
258 static void gen_c_int_type(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
259 HexSignedness signedness
)
261 const char *signstr
= (signedness
== UNSIGNED
) ? "u" : "";
262 OUT(c
, locp
, signstr
, "int", &bit_width
, "_t");
265 static HexValue
gen_constant(Context
*c
,
269 HexSignedness signedness
)
272 assert(bit_width
== 32 || bit_width
== 64);
273 memset(&rvalue
, 0, sizeof(HexValue
));
275 rvalue
.bit_width
= bit_width
;
276 rvalue
.signedness
= signedness
;
277 rvalue
.is_dotnew
= false;
278 rvalue
.tmp
.index
= c
->inst
.tmp_count
;
279 OUT(c
, locp
, "TCGv_i", &bit_width
, " tmp_", &c
->inst
.tmp_count
,
280 " = tcg_constant_i", &bit_width
, "(", value
, ");\n");
285 /* Temporary values creation */
286 HexValue
gen_tmp(Context
*c
,
289 HexSignedness signedness
)
292 assert(bit_width
== 32 || bit_width
== 64);
293 memset(&rvalue
, 0, sizeof(HexValue
));
295 rvalue
.bit_width
= bit_width
;
296 rvalue
.signedness
= signedness
;
297 rvalue
.is_dotnew
= false;
298 rvalue
.tmp
.index
= c
->inst
.tmp_count
;
299 OUT(c
, locp
, "TCGv_i", &bit_width
, " tmp_", &c
->inst
.tmp_count
,
300 " = tcg_temp_new_i", &bit_width
, "();\n");
305 static HexValue
gen_constant_from_imm(Context
*c
,
310 assert(value
->type
== IMMEDIATE
);
311 memset(&rvalue
, 0, sizeof(HexValue
));
313 rvalue
.bit_width
= value
->bit_width
;
314 rvalue
.signedness
= value
->signedness
;
315 rvalue
.is_dotnew
= false;
316 rvalue
.tmp
.index
= c
->inst
.tmp_count
;
318 * Here we output the call to `tcg_constant_i<width>` in
319 * order to create the temporary value. Note, that we
322 * `tcg_constant_i<width>`((int<width>_t) ...)`
324 * This cast is required to avoid implicit integer
325 * conversion warnings since all immediates are
326 * output as `((int64_t) 123ULL)`, even if the
329 OUT(c
, locp
, "TCGv_i", &rvalue
.bit_width
, " tmp_", &c
->inst
.tmp_count
);
330 OUT(c
, locp
, " = tcg_constant_i", &rvalue
.bit_width
,
331 "((int", &rvalue
.bit_width
, "_t) (", value
, "));\n");
337 HexValue
gen_imm_value(Context
*c
__attribute__((unused
)),
341 HexSignedness signedness
)
345 assert(bit_width
== 32 || bit_width
== 64);
346 memset(&rvalue
, 0, sizeof(HexValue
));
347 rvalue
.type
= IMMEDIATE
;
348 rvalue
.bit_width
= bit_width
;
349 rvalue
.signedness
= signedness
;
350 rvalue
.is_dotnew
= false;
351 rvalue
.imm
.type
= VALUE
;
352 rvalue
.imm
.value
= value
;
356 HexValue
gen_imm_qemu_tmp(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
357 HexSignedness signedness
)
361 assert(bit_width
== 32 || bit_width
== 64);
362 memset(&rvalue
, 0, sizeof(HexValue
));
363 rvalue
.type
= IMMEDIATE
;
364 rvalue
.is_dotnew
= false;
365 rvalue
.bit_width
= bit_width
;
366 rvalue
.signedness
= signedness
;
367 rvalue
.imm
.type
= QEMU_TMP
;
368 rvalue
.imm
.index
= c
->inst
.qemu_tmp_count
++;
372 HexValue
rvalue_materialize(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
374 if (rvalue
->type
== IMMEDIATE
) {
375 return gen_constant_from_imm(c
, locp
, rvalue
);
380 HexValue
gen_rvalue_extend(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
382 assert_signedness(c
, locp
, rvalue
->signedness
);
383 if (rvalue
->bit_width
> 32) {
387 if (rvalue
->type
== IMMEDIATE
) {
388 HexValue res
= gen_imm_qemu_tmp(c
, locp
, 64, rvalue
->signedness
);
389 bool is_unsigned
= (rvalue
->signedness
== UNSIGNED
);
390 const char *sign_suffix
= is_unsigned
? "u" : "";
391 gen_c_int_type(c
, locp
, 64, rvalue
->signedness
);
392 OUT(c
, locp
, " ", &res
, " = ");
393 OUT(c
, locp
, "(", sign_suffix
, "int64_t) ");
394 OUT(c
, locp
, "(", sign_suffix
, "int32_t) ");
395 OUT(c
, locp
, rvalue
, ";\n");
398 HexValue res
= gen_tmp(c
, locp
, 64, rvalue
->signedness
);
399 bool is_unsigned
= (rvalue
->signedness
== UNSIGNED
);
400 const char *sign_suffix
= is_unsigned
? "u" : "";
401 OUT(c
, locp
, "tcg_gen_ext", sign_suffix
,
402 "_i32_i64(", &res
, ", ", rvalue
, ");\n");
407 HexValue
gen_rvalue_truncate(Context
*c
, YYLTYPE
*locp
, HexValue
*rvalue
)
409 if (rvalue
->type
== IMMEDIATE
) {
410 HexValue res
= *rvalue
;
414 if (rvalue
->bit_width
== 64) {
415 HexValue res
= gen_tmp(c
, locp
, 32, rvalue
->signedness
);
416 OUT(c
, locp
, "tcg_gen_trunc_i64_tl(", &res
, ", ", rvalue
, ");\n");
424 * Attempts to lookup the `Var` struct associated with the given `varid`.
425 * The `dst` argument is populated with the found name, bit_width, and
426 * signedness, given that `dst` is non-NULL. Returns true if the lookup
427 * succeeded and false otherwise.
429 static bool try_find_variable(Context
*c
, YYLTYPE
*locp
,
433 yyassert(c
, locp
, varid
, "varid to lookup is NULL");
434 yyassert(c
, locp
, varid
->type
== VARID
,
435 "Can only lookup variables by varid");
436 for (unsigned i
= 0; i
< c
->inst
.allocated
->len
; i
++) {
437 Var
*curr
= &g_array_index(c
->inst
.allocated
, Var
, i
);
438 if (g_string_equal(varid
->var
.name
, curr
->name
)) {
440 dst
->var
.name
= curr
->name
;
441 dst
->bit_width
= curr
->bit_width
;
442 dst
->signedness
= curr
->signedness
;
450 /* Calls `try_find_variable` and asserts succcess. */
451 static void find_variable(Context
*c
, YYLTYPE
*locp
,
455 bool found
= try_find_variable(c
, locp
, dst
, varid
);
456 yyassert(c
, locp
, found
, "Use of undeclared variable!\n");
459 /* Handle signedness, if both unsigned -> result is unsigned, else signed */
460 static inline HexSignedness
bin_op_signedness(Context
*c
, YYLTYPE
*locp
,
464 assert_signedness(c
, locp
, sign1
);
465 assert_signedness(c
, locp
, sign2
);
466 return (sign1
== UNSIGNED
&& sign2
== UNSIGNED
) ? UNSIGNED
: SIGNED
;
469 void gen_varid_allocate(Context
*c
,
473 HexSignedness signedness
)
475 const char *bit_suffix
= (bit_width
== 64) ? "i64" : "i32";
476 bool found
= try_find_variable(c
, locp
, NULL
, varid
);
479 memset(&new_var
, 0, sizeof(Var
));
481 yyassert(c
, locp
, !found
, "Redeclaration of variables not allowed!");
482 assert_signedness(c
, locp
, signedness
);
484 /* `varid` only carries name information */
485 new_var
.name
= varid
->var
.name
;
486 new_var
.bit_width
= bit_width
;
487 new_var
.signedness
= signedness
;
489 EMIT_HEAD(c
, "TCGv_%s %s", bit_suffix
, varid
->var
.name
->str
);
490 EMIT_HEAD(c
, " = tcg_temp_new_%s();\n", bit_suffix
);
491 g_array_append_val(c
->inst
.allocated
, new_var
);
501 HexValue
gen_bin_cmp(Context
*c
,
507 HexValue op1_m
= *op1
;
508 HexValue op2_m
= *op2
;
509 enum OpTypes op_types
= (op1_m
.type
!= IMMEDIATE
) << 1
510 | (op2_m
.type
!= IMMEDIATE
);
512 bool op_is64bit
= op1_m
.bit_width
== 64 || op2_m
.bit_width
== 64;
513 const char *bit_suffix
= op_is64bit
? "i64" : "i32";
514 unsigned bit_width
= (op_is64bit
) ? 64 : 32;
515 HexValue res
= gen_tmp(c
, locp
, bit_width
, UNSIGNED
);
517 /* Extend to 64-bits, if required */
519 op1_m
= gen_rvalue_extend(c
, locp
, &op1_m
);
520 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
526 yyassert(c
, locp
, false, "Binary comparisons between IMM op IMM and"
527 "IMM op REG not handled!");
530 OUT(c
, locp
, "tcg_gen_setcondi_", bit_suffix
, "(");
531 OUT(c
, locp
, cond_to_str(type
), ", ", &res
, ", ", &op1_m
, ", ", &op2_m
,
535 OUT(c
, locp
, "tcg_gen_setcond_", bit_suffix
, "(");
536 OUT(c
, locp
, cond_to_str(type
), ", ", &res
, ", ", &op1_m
, ", ", &op2_m
,
540 fprintf(stderr
, "Error in evalutating immediateness!");
546 static void gen_simple_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
547 const char *bit_suffix
, HexValue
*res
,
548 enum OpTypes op_types
,
558 HexSignedness signedness
= bin_op_signedness(c
, locp
,
561 gen_c_int_type(c
, locp
, bit_width
, signedness
);
562 OUT(c
, locp
, " ", res
,
563 " = ", op1
, imm_imm
, op2
, ";\n");
566 OUT(c
, locp
, imm_reg
, bit_suffix
,
567 "(", res
, ", ", op2
, ", ", op1
, ");\n");
570 OUT(c
, locp
, reg_imm
, bit_suffix
,
571 "(", res
, ", ", op1
, ", ", op2
, ");\n");
574 OUT(c
, locp
, reg_reg
, bit_suffix
,
575 "(", res
, ", ", op1
, ", ", op2
, ");\n");
580 static void gen_sub_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
581 const char *bit_suffix
, HexValue
*res
,
582 enum OpTypes op_types
, HexValue
*op1
,
587 HexSignedness signedness
= bin_op_signedness(c
, locp
,
590 gen_c_int_type(c
, locp
, bit_width
, signedness
);
591 OUT(c
, locp
, " ", res
,
592 " = ", op1
, " - ", op2
, ";\n");
595 OUT(c
, locp
, "tcg_gen_subfi_", bit_suffix
,
596 "(", res
, ", ", op1
, ", ", op2
, ");\n");
599 OUT(c
, locp
, "tcg_gen_subi_", bit_suffix
,
600 "(", res
, ", ", op1
, ", ", op2
, ");\n");
603 OUT(c
, locp
, "tcg_gen_sub_", bit_suffix
,
604 "(", res
, ", ", op1
, ", ", op2
, ");\n");
609 static void gen_asl_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
610 bool op_is64bit
, const char *bit_suffix
,
611 HexValue
*res
, enum OpTypes op_types
,
612 HexValue
*op1
, HexValue
*op2
)
614 HexValue op1_m
= *op1
;
615 HexValue op2_m
= *op2
;
618 HexSignedness signedness
= bin_op_signedness(c
, locp
,
621 gen_c_int_type(c
, locp
, bit_width
, signedness
);
622 OUT(c
, locp
, " ", res
,
623 " = ", op1
, " << ", op2
, ";\n");
626 OUT(c
, locp
, "if (", op2
, " >= ", &bit_width
, ") {\n");
627 OUT(c
, locp
, "tcg_gen_movi_", bit_suffix
, "(", res
, ", 0);\n");
628 OUT(c
, locp
, "} else {\n");
629 OUT(c
, locp
, "tcg_gen_shli_", bit_suffix
,
630 "(", res
, ", ", op1
, ", ", op2
, ");\n");
634 op1_m
.bit_width
= bit_width
;
635 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
638 OUT(c
, locp
, "tcg_gen_shl_", bit_suffix
,
639 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
642 if (op_types
== IMM_REG
|| op_types
== REG_REG
) {
644 * Handle left shift by 64/32 which hexagon-sim expects to clear out
647 HexValue zero
= gen_constant(c
, locp
, "0", bit_width
, UNSIGNED
);
648 HexValue edge
= gen_imm_value(c
, locp
, bit_width
, bit_width
, UNSIGNED
);
649 edge
= rvalue_materialize(c
, locp
, &edge
);
651 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
653 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
654 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
655 OUT(c
, locp
, "tcg_gen_movcond_i", &bit_width
);
656 OUT(c
, locp
, "(TCG_COND_GEU, ", res
, ", ", &op2_m
, ", ", &edge
);
657 OUT(c
, locp
, ", ", &zero
, ", ", res
, ");\n");
661 static void gen_asr_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
662 bool op_is64bit
, const char *bit_suffix
,
663 HexValue
*res
, enum OpTypes op_types
,
664 HexValue
*op1
, HexValue
*op2
)
666 HexValue op1_m
= *op1
;
667 HexValue op2_m
= *op2
;
671 yyassert(c
, locp
, false, "ASR between IMM op IMM, and IMM op REG"
675 HexSignedness signedness
= bin_op_signedness(c
, locp
,
679 gen_c_int_type(c
, locp
, bit_width
, signedness
);
680 OUT(c
, locp
, " shift = ", op2
, ";\n");
681 OUT(c
, locp
, "if (", op2
, " >= ", &bit_width
, ") {\n");
682 OUT(c
, locp
, " shift = ", &bit_width
, " - 1;\n");
684 OUT(c
, locp
, "tcg_gen_sari_", bit_suffix
,
685 "(", res
, ", ", op1
, ", shift);\n}\n");
688 OUT(c
, locp
, "tcg_gen_sar_", bit_suffix
,
689 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
692 if (op_types
== REG_REG
) {
693 /* Handle right shift by values >= bit_width */
694 const char *offset
= op_is64bit
? "63" : "31";
695 HexValue tmp
= gen_tmp(c
, locp
, bit_width
, SIGNED
);
696 HexValue zero
= gen_constant(c
, locp
, "0", bit_width
, SIGNED
);
697 HexValue edge
= gen_imm_value(c
, locp
, bit_width
, bit_width
, UNSIGNED
);
699 edge
= rvalue_materialize(c
, locp
, &edge
);
701 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
703 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
704 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
706 OUT(c
, locp
, "tcg_gen_extract_", bit_suffix
, "(",
707 &tmp
, ", ", &op1_m
, ", ", offset
, ", 1);\n");
708 OUT(c
, locp
, "tcg_gen_sub_", bit_suffix
, "(",
709 &tmp
, ", ", &zero
, ", ", &tmp
, ");\n");
710 OUT(c
, locp
, "tcg_gen_movcond_i", &bit_width
);
711 OUT(c
, locp
, "(TCG_COND_GEU, ", res
, ", ", &op2_m
, ", ", &edge
);
712 OUT(c
, locp
, ", ", &tmp
, ", ", res
, ");\n");
716 static void gen_lsr_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
717 bool op_is64bit
, const char *bit_suffix
,
718 HexValue
*res
, enum OpTypes op_types
,
719 HexValue
*op1
, HexValue
*op2
)
721 HexValue op1_m
= *op1
;
722 HexValue op2_m
= *op2
;
726 yyassert(c
, locp
, false, "LSR between IMM op IMM, and IMM op REG"
730 OUT(c
, locp
, "if (", op2
, " >= ", &bit_width
, ") {\n");
731 OUT(c
, locp
, "tcg_gen_movi_", bit_suffix
, "(", res
, ", 0);\n");
732 OUT(c
, locp
, "} else {\n");
733 OUT(c
, locp
, "tcg_gen_shri_", bit_suffix
,
734 "(", res
, ", ", op1
, ", ", op2
, ");\n");
738 OUT(c
, locp
, "tcg_gen_shr_", bit_suffix
,
739 "(", res
, ", ", &op1_m
, ", ", op2
, ");\n");
742 if (op_types
== REG_REG
) {
743 /* Handle right shift by values >= bit_width */
744 HexValue zero
= gen_constant(c
, locp
, "0", bit_width
, UNSIGNED
);
745 HexValue edge
= gen_imm_value(c
, locp
, bit_width
, bit_width
, UNSIGNED
);
746 edge
= rvalue_materialize(c
, locp
, &edge
);
748 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
750 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
751 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
752 OUT(c
, locp
, "tcg_gen_movcond_i", &bit_width
);
753 OUT(c
, locp
, "(TCG_COND_GEU, ", res
, ", ", &op2_m
, ", ", &edge
);
754 OUT(c
, locp
, ", ", &zero
, ", ", res
, ");\n");
759 * Note: This implementation of logical `and` does not mirror that in C.
760 * We do not short-circuit logical expressions!
762 static void gen_andl_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
763 const char *bit_suffix
, HexValue
*res
,
764 enum OpTypes op_types
, HexValue
*op1
,
769 HexValue zero
= gen_constant(c
, locp
, "0", 32, UNSIGNED
);
770 memset(&tmp1
, 0, sizeof(HexValue
));
771 memset(&tmp2
, 0, sizeof(HexValue
));
776 yyassert(c
, locp
, false, "ANDL between IMM op IMM, IMM op REG, and"
777 " REG op IMM, not handled!");
780 tmp1
= gen_bin_cmp(c
, locp
, TCG_COND_NE
, op1
, &zero
);
781 tmp2
= gen_bin_cmp(c
, locp
, TCG_COND_NE
, op2
, &zero
);
782 OUT(c
, locp
, "tcg_gen_and_", bit_suffix
,
783 "(", res
, ", ", &tmp1
, ", ", &tmp2
, ");\n");
788 static void gen_minmax_op(Context
*c
, YYLTYPE
*locp
, unsigned bit_width
,
789 HexValue
*res
, enum OpTypes op_types
,
790 HexValue
*op1
, HexValue
*op2
, bool minmax
)
793 HexValue op1_m
= *op1
;
794 HexValue op2_m
= *op2
;
797 assert_signedness(c
, locp
, res
->signedness
);
798 is_unsigned
= res
->signedness
== UNSIGNED
;
802 mm
= is_unsigned
? "tcg_gen_umax" : "tcg_gen_smax";
805 mm
= is_unsigned
? "tcg_gen_umin" : "tcg_gen_smin";
809 yyassert(c
, locp
, false, "MINMAX between IMM op IMM, not handled!");
812 op1_m
.bit_width
= bit_width
;
813 op1_m
= rvalue_materialize(c
, locp
, &op1_m
);
814 OUT(c
, locp
, mm
, "_i", &bit_width
, "(");
815 OUT(c
, locp
, res
, ", ", &op1_m
, ", ", op2
, ");\n");
818 op2_m
.bit_width
= bit_width
;
819 op2_m
= rvalue_materialize(c
, locp
, &op2_m
);
822 OUT(c
, locp
, mm
, "_i", &bit_width
, "(");
823 OUT(c
, locp
, res
, ", ", op1
, ", ", &op2_m
, ");\n");
828 /* Code generation functions */
829 HexValue
gen_bin_op(Context
*c
,
835 /* Replicate operands to avoid side effects */
836 HexValue op1_m
= *op1
;
837 HexValue op2_m
= *op2
;
838 enum OpTypes op_types
;
840 HexSignedness signedness
;
842 const char *bit_suffix
;
845 memset(&res
, 0, sizeof(HexValue
));
848 * If the operands are VARID's we need to look up the
851 if (op1_m
.type
== VARID
) {
852 find_variable(c
, locp
, &op1_m
, &op1_m
);
854 if (op2_m
.type
== VARID
) {
855 find_variable(c
, locp
, &op2_m
, &op2_m
);
858 op_types
= (op1_m
.type
!= IMMEDIATE
) << 1
859 | (op2_m
.type
!= IMMEDIATE
);
860 op_is64bit
= op1_m
.bit_width
== 64 || op2_m
.bit_width
== 64;
861 /* Shift greater than 32 are 64 bits wide */
863 if (type
== ASL_OP
&& op2_m
.type
== IMMEDIATE
&&
864 op2_m
.imm
.type
== VALUE
&& op2_m
.imm
.value
>= 32) {
868 bit_width
= (op_is64bit
) ? 64 : 32;
869 bit_suffix
= op_is64bit
? "i64" : "i32";
871 /* Extend to 64-bits, if required */
873 op1_m
= gen_rvalue_extend(c
, locp
, &op1_m
);
874 op2_m
= gen_rvalue_extend(c
, locp
, &op2_m
);
877 signedness
= bin_op_signedness(c
, locp
, op1_m
.signedness
, op2_m
.signedness
);
878 if (op_types
!= IMM_IMM
) {
879 res
= gen_tmp(c
, locp
, bit_width
, signedness
);
881 res
= gen_imm_qemu_tmp(c
, locp
, bit_width
, signedness
);
886 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
887 op_types
, &op1_m
, &op2_m
,
894 gen_sub_op(c
, locp
, bit_width
, bit_suffix
, &res
, op_types
,
898 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
899 op_types
, &op1_m
, &op2_m
,
906 gen_asl_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
910 gen_asr_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
914 gen_lsr_op(c
, locp
, bit_width
, op_is64bit
, bit_suffix
, &res
, op_types
,
918 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
919 op_types
, &op1_m
, &op2_m
,
926 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
927 op_types
, &op1_m
, &op2_m
,
934 gen_simple_op(c
, locp
, bit_width
, bit_suffix
, &res
,
935 op_types
, &op1_m
, &op2_m
,
942 gen_andl_op(c
, locp
, bit_width
, bit_suffix
, &res
, op_types
, &op1_m
,
946 gen_minmax_op(c
, locp
, bit_width
, &res
, op_types
, &op1_m
, &op2_m
,
950 gen_minmax_op(c
, locp
, bit_width
, &res
, op_types
, &op1_m
, &op2_m
, true);
956 HexValue
gen_cast_op(Context
*c
,
959 unsigned target_width
,
960 HexSignedness signedness
)
962 assert_signedness(c
, locp
, src
->signedness
);
963 if (src
->bit_width
== target_width
) {
965 } else if (src
->type
== IMMEDIATE
) {
967 res
.bit_width
= target_width
;
968 res
.signedness
= signedness
;
971 HexValue res
= gen_tmp(c
, locp
, target_width
, signedness
);
973 if (src
->bit_width
> target_width
) {
974 OUT(c
, locp
, "tcg_gen_trunc_i64_tl(", &res
, ", ", src
, ");\n");
976 assert_signedness(c
, locp
, src
->signedness
);
977 if (src
->signedness
== UNSIGNED
) {
978 /* Extend unsigned */
979 OUT(c
, locp
, "tcg_gen_extu_i32_i64(",
980 &res
, ", ", src
, ");\n");
983 OUT(c
, locp
, "tcg_gen_ext_i32_i64(",
984 &res
, ", ", src
, ");\n");
993 * Implements an extension when the `src_width` is an immediate.
994 * If the `value` to extend is also an immediate we use `extract/sextract`
995 * from QEMU `bitops.h`. If `value` is a TCGv then we rely on
996 * `tcg_gen_extract/tcg_gen_sextract`.
998 static HexValue
gen_extend_imm_width_op(Context
*c
,
1000 HexValue
*src_width
,
1003 HexSignedness signedness
)
1006 * If the source width is not an immediate value, we need to guard
1007 * our extend op with if statements to handle the case where
1008 * `src_width_m` is 0.
1010 const char *sign_prefix
;
1013 assert_signedness(c
, locp
, signedness
);
1014 assert(dst_width
== 64 || dst_width
== 32);
1015 assert(src_width
->type
== IMMEDIATE
);
1017 sign_prefix
= (signedness
== UNSIGNED
) ? "" : "s";
1018 need_guarding
= (src_width
->imm
.type
!= VALUE
);
1020 if (src_width
->imm
.type
== VALUE
&&
1021 src_width
->imm
.value
== 0) {
1023 * We can bail out early if the source width is known to be zero
1024 * at translation time.
1026 return gen_imm_value(c
, locp
, 0, dst_width
, signedness
);
1029 if (value
->type
== IMMEDIATE
) {
1031 * If both the value and source width are immediates,
1032 * we can perform the extension at translation time
1033 * using QEMUs bitops.
1035 HexValue res
= gen_imm_qemu_tmp(c
, locp
, dst_width
, signedness
);
1036 gen_c_int_type(c
, locp
, dst_width
, signedness
);
1037 OUT(c
, locp
, " ", &res
, " = 0;\n");
1038 if (need_guarding
) {
1039 OUT(c
, locp
, "if (", src_width
, " != 0) {\n");
1041 OUT(c
, locp
, &res
, " = ", sign_prefix
, "extract", &dst_width
);
1042 OUT(c
, locp
, "(", value
, ", 0, ", src_width
, ");\n");
1043 if (need_guarding
) {
1044 OUT(c
, locp
, "}\n");
1049 * If the source width is an immediate and the value to
1050 * extend is a TCGv, then use tcg_gen_extract/tcg_gen_sextract
1052 HexValue res
= gen_tmp(c
, locp
, dst_width
, signedness
);
1055 * If the width is an immediate value we know it is non-zero
1056 * at this point, otherwise we need an if-statement
1058 if (need_guarding
) {
1059 OUT(c
, locp
, "if (", src_width
, " != 0) {\n");
1061 OUT(c
, locp
, "tcg_gen_", sign_prefix
, "extract_i", &dst_width
);
1062 OUT(c
, locp
, "(", &res
, ", ", value
, ", 0, ", src_width
,
1064 if (need_guarding
) {
1065 OUT(c
, locp
, "} else {\n");
1066 OUT(c
, locp
, "tcg_gen_movi_i", &dst_width
, "(", &res
,
1068 OUT(c
, locp
, "}\n");
1075 * Implements an extension when the `src_width` is given by
1076 * a TCGv. Here we need to reimplement the behaviour of
1077 * `tcg_gen_extract` and the like using shifts and masks.
1079 static HexValue
gen_extend_tcg_width_op(Context
*c
,
1081 HexValue
*src_width
,
1084 HexSignedness signedness
)
1086 HexValue src_width_m
= rvalue_materialize(c
, locp
, src_width
);
1087 HexValue zero
= gen_constant(c
, locp
, "0", dst_width
, UNSIGNED
);
1088 HexValue shift
= gen_tmp(c
, locp
, dst_width
, UNSIGNED
);
1091 assert_signedness(c
, locp
, signedness
);
1092 assert(dst_width
== 64 || dst_width
== 32);
1093 assert(src_width
->type
!= IMMEDIATE
);
1095 res
= gen_tmp(c
, locp
, dst_width
, signedness
);
1097 OUT(c
, locp
, "tcg_gen_subfi_i", &dst_width
);
1098 OUT(c
, locp
, "(", &shift
, ", ", &dst_width
, ", ", &src_width_m
, ");\n");
1099 if (signedness
== UNSIGNED
) {
1100 HexValue mask
= gen_constant(c
, locp
, "-1", dst_width
, UNSIGNED
);
1101 OUT(c
, locp
, "tcg_gen_shr_i", &dst_width
, "(",
1102 &res
, ", ", &mask
, ", ", &shift
, ");\n");
1103 OUT(c
, locp
, "tcg_gen_and_i", &dst_width
, "(",
1104 &res
, ", ", &res
, ", ", value
, ");\n");
1106 OUT(c
, locp
, "tcg_gen_shl_i", &dst_width
, "(",
1107 &res
, ", ", value
, ", ", &shift
, ");\n");
1108 OUT(c
, locp
, "tcg_gen_sar_i", &dst_width
, "(",
1109 &res
, ", ", &res
, ", ", &shift
, ");\n");
1111 OUT(c
, locp
, "tcg_gen_movcond_i", &dst_width
, "(TCG_COND_EQ, ", &res
,
1113 OUT(c
, locp
, &src_width_m
, ", ", &zero
, ", ", &zero
, ", ", &res
,
1119 HexValue
gen_extend_op(Context
*c
,
1121 HexValue
*src_width
,
1124 HexSignedness signedness
)
1126 unsigned bit_width
= (dst_width
= 64) ? 64 : 32;
1127 HexValue value_m
= *value
;
1128 HexValue src_width_m
= *src_width
;
1130 assert_signedness(c
, locp
, signedness
);
1131 yyassert(c
, locp
, value_m
.bit_width
<= bit_width
&&
1132 src_width_m
.bit_width
<= bit_width
,
1133 "Extending to a size smaller than the current size"
1136 if (value_m
.bit_width
< bit_width
) {
1137 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1140 if (src_width_m
.bit_width
< bit_width
) {
1141 src_width_m
= gen_rvalue_extend(c
, locp
, &src_width_m
);
1144 if (src_width_m
.type
== IMMEDIATE
) {
1145 return gen_extend_imm_width_op(c
, locp
, &src_width_m
, bit_width
,
1146 &value_m
, signedness
);
1148 return gen_extend_tcg_width_op(c
, locp
, &src_width_m
, bit_width
,
1149 &value_m
, signedness
);
1154 * Implements `rdeposit` for the special case where `width`
1155 * is of TCGv type. In this case we need to reimplement the behaviour
1156 * of `tcg_gen_deposit*` using binary operations and masks/shifts.
1158 * Note: this is the only type of `rdeposit` that occurs, meaning the
1159 * `width` is _NEVER_ of IMMEDIATE type.
1161 void gen_rdeposit_op(Context
*c
,
1169 * Otherwise if the width is not known, we fallback on reimplementing
1172 HexValue begin_m
= *begin
;
1173 HexValue value_m
= *value
;
1174 HexValue width_m
= *width
;
1175 const char *mask_str
= (dst
->bit_width
== 32)
1177 : "0xffffffffffffffffUL";
1178 HexValue mask
= gen_constant(c
, locp
, mask_str
, dst
->bit_width
,
1180 const char *dst_width_str
= (dst
->bit_width
== 32) ? "32" : "64";
1181 HexValue k64
= gen_constant(c
, locp
, dst_width_str
, dst
->bit_width
,
1186 assert(dst
->bit_width
>= value
->bit_width
);
1187 assert(begin
->type
== IMMEDIATE
&& begin
->imm
.type
== VALUE
);
1188 assert(dst
->type
== REGISTER_ARG
);
1190 yyassert(c
, locp
, width
->type
!= IMMEDIATE
,
1191 "Immediate index to rdeposit not handled!");
1193 yyassert(c
, locp
, value_m
.bit_width
== dst
->bit_width
&&
1194 begin_m
.bit_width
== dst
->bit_width
&&
1195 width_m
.bit_width
== dst
->bit_width
,
1196 "Extension/truncation should be taken care of"
1197 " before rdeposit!");
1199 width_m
= rvalue_materialize(c
, locp
, &width_m
);
1202 * mask = 0xffffffffffffffff >> (64 - width)
1203 * mask = mask << begin
1204 * value = (value << begin) & mask
1207 * dst = (width != 0) ? res : dst
1209 k64
= gen_bin_op(c
, locp
, SUB_OP
, &k64
, &width_m
);
1210 mask
= gen_bin_op(c
, locp
, LSR_OP
, &mask
, &k64
);
1211 mask
= gen_bin_op(c
, locp
, ASL_OP
, &mask
, &begin_m
);
1212 value_m
= gen_bin_op(c
, locp
, ASL_OP
, &value_m
, &begin_m
);
1213 value_m
= gen_bin_op(c
, locp
, ANDB_OP
, &value_m
, &mask
);
1215 OUT(c
, locp
, "tcg_gen_not_i", &dst
->bit_width
, "(", &mask
, ", ",
1217 res
= gen_bin_op(c
, locp
, ANDB_OP
, dst
, &mask
);
1218 res
= gen_bin_op(c
, locp
, ORB_OP
, &res
, &value_m
);
1221 * We don't need to truncate `res` here, since all operations involved use
1222 * the same bit width.
1225 /* If the width is zero, then return the identity dst = dst */
1226 zero
= gen_constant(c
, locp
, "0", res
.bit_width
, UNSIGNED
);
1227 OUT(c
, locp
, "tcg_gen_movcond_i", &res
.bit_width
, "(TCG_COND_NE, ",
1229 OUT(c
, locp
, ", ", &width_m
, ", ", &zero
, ", ", &res
, ", ", dst
,
1233 void gen_deposit_op(Context
*c
,
1240 HexValue value_m
= *value
;
1241 unsigned bit_width
= (dst
->bit_width
== 64) ? 64 : 32;
1242 unsigned width
= cast
->bit_width
;
1244 yyassert(c
, locp
, index
->type
== IMMEDIATE
,
1245 "Deposit index must be immediate!\n");
1248 * Using tcg_gen_deposit_i**(dst, dst, ...) requires dst to be
1251 gen_inst_init_args(c
, locp
);
1253 /* If the destination value is 32, truncate the value, otherwise extend */
1254 if (dst
->bit_width
!= value
->bit_width
) {
1255 if (bit_width
== 32) {
1256 value_m
= gen_rvalue_truncate(c
, locp
, &value_m
);
1258 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1261 value_m
= rvalue_materialize(c
, locp
, &value_m
);
1262 OUT(c
, locp
, "tcg_gen_deposit_i", &bit_width
, "(", dst
, ", ", dst
, ", ");
1263 OUT(c
, locp
, &value_m
, ", ", index
, " * ", &width
, ", ", &width
, ");\n");
1266 HexValue
gen_rextract_op(Context
*c
,
1272 unsigned bit_width
= (src
->bit_width
== 64) ? 64 : 32;
1273 HexValue res
= gen_tmp(c
, locp
, bit_width
, UNSIGNED
);
1274 OUT(c
, locp
, "tcg_gen_extract_i", &bit_width
, "(", &res
);
1275 OUT(c
, locp
, ", ", src
, ", ", &begin
, ", ", &width
, ");\n");
1279 HexValue
gen_extract_op(Context
*c
,
1283 HexExtract
*extract
)
1285 unsigned bit_width
= (src
->bit_width
== 64) ? 64 : 32;
1286 unsigned width
= extract
->bit_width
;
1287 const char *sign_prefix
;
1290 yyassert(c
, locp
, index
->type
== IMMEDIATE
,
1291 "Extract index must be immediate!\n");
1292 assert_signedness(c
, locp
, extract
->signedness
);
1294 sign_prefix
= (extract
->signedness
== UNSIGNED
) ? "" : "s";
1295 res
= gen_tmp(c
, locp
, bit_width
, extract
->signedness
);
1297 OUT(c
, locp
, "tcg_gen_", sign_prefix
, "extract_i", &bit_width
,
1298 "(", &res
, ", ", src
);
1299 OUT(c
, locp
, ", ", index
, " * ", &width
, ", ", &width
, ");\n");
1301 /* Some extract operations have bit_width != storage_bit_width */
1302 if (extract
->storage_bit_width
> bit_width
) {
1303 HexValue tmp
= gen_tmp(c
, locp
, extract
->storage_bit_width
,
1304 extract
->signedness
);
1305 const char *sign_suffix
= (extract
->signedness
== UNSIGNED
) ? "u" : "";
1306 OUT(c
, locp
, "tcg_gen_ext", sign_suffix
, "_i32_i64(",
1307 &tmp
, ", ", &res
, ");\n");
1313 void gen_write_reg(Context
*c
, YYLTYPE
*locp
, HexValue
*reg
, HexValue
*value
)
1315 HexValue value_m
= *value
;
1316 yyassert(c
, locp
, reg
->type
== REGISTER
, "reg must be a register!");
1317 value_m
= gen_rvalue_truncate(c
, locp
, &value_m
);
1318 value_m
= rvalue_materialize(c
, locp
, &value_m
);
1321 "gen_log_reg_write(", ®
->reg
.id
, ", ",
1325 void gen_assign(Context
*c
,
1330 HexValue value_m
= *value
;
1333 yyassert(c
, locp
, !is_inside_ternary(c
),
1334 "Assign in ternary not allowed!");
1336 if (dst
->type
== REGISTER
) {
1337 gen_write_reg(c
, locp
, dst
, &value_m
);
1341 if (dst
->type
== VARID
) {
1342 find_variable(c
, locp
, dst
, dst
);
1344 bit_width
= dst
->bit_width
== 64 ? 64 : 32;
1346 if (bit_width
!= value_m
.bit_width
) {
1347 if (bit_width
== 64) {
1348 value_m
= gen_rvalue_extend(c
, locp
, &value_m
);
1350 value_m
= gen_rvalue_truncate(c
, locp
, &value_m
);
1354 const char *imm_suffix
= (value_m
.type
== IMMEDIATE
) ? "i" : "";
1355 OUT(c
, locp
, "tcg_gen_mov", imm_suffix
, "_i", &bit_width
,
1356 "(", dst
, ", ", &value_m
, ");\n");
1359 HexValue
gen_convround(Context
*c
,
1363 HexValue src_m
= *src
;
1364 unsigned bit_width
= src_m
.bit_width
;
1365 const char *size
= (bit_width
== 32) ? "32" : "64";
1366 HexValue res
= gen_tmp(c
, locp
, bit_width
, src
->signedness
);
1367 HexValue mask
= gen_constant(c
, locp
, "0x3", bit_width
, UNSIGNED
);
1368 HexValue one
= gen_constant(c
, locp
, "1", bit_width
, UNSIGNED
);
1372 and = gen_bin_op(c
, locp
, ANDB_OP
, &src_m
, &mask
);
1373 src_p1
= gen_bin_op(c
, locp
, ADD_OP
, &src_m
, &one
);
1375 OUT(c
, locp
, "tcg_gen_movcond_i", size
, "(TCG_COND_EQ, ", &res
);
1376 OUT(c
, locp
, ", ", &and, ", ", &mask
, ", ");
1377 OUT(c
, locp
, &src_p1
, ", ", &src_m
, ");\n");
1382 static HexValue
gen_convround_n_b(Context
*c
,
1387 HexValue one
= gen_constant(c
, locp
, "1", 32, UNSIGNED
);
1388 HexValue res
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1389 HexValue tmp
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1390 HexValue tmp_64
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1392 assert(n
->type
!= IMMEDIATE
);
1393 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &res
, ", ", a
, ");\n");
1394 OUT(c
, locp
, "tcg_gen_shl_i32(", &tmp
);
1395 OUT(c
, locp
, ", ", &one
, ", ", n
, ");\n");
1396 OUT(c
, locp
, "tcg_gen_and_i32(", &tmp
);
1397 OUT(c
, locp
, ", ", &tmp
, ", ", a
, ");\n");
1398 OUT(c
, locp
, "tcg_gen_shri_i32(", &tmp
);
1399 OUT(c
, locp
, ", ", &tmp
, ", 1);\n");
1400 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &tmp_64
, ", ", &tmp
, ");\n");
1401 OUT(c
, locp
, "tcg_gen_add_i64(", &res
);
1402 OUT(c
, locp
, ", ", &res
, ", ", &tmp_64
, ");\n");
1407 static HexValue
gen_convround_n_c(Context
*c
,
1412 HexValue res
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1413 HexValue one
= gen_constant(c
, locp
, "1", 32, UNSIGNED
);
1414 HexValue tmp
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1415 HexValue tmp_64
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1417 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &res
, ", ", a
, ");\n");
1418 OUT(c
, locp
, "tcg_gen_subi_i32(", &tmp
);
1419 OUT(c
, locp
, ", ", n
, ", 1);\n");
1420 OUT(c
, locp
, "tcg_gen_shl_i32(", &tmp
);
1421 OUT(c
, locp
, ", ", &one
, ", ", &tmp
, ");\n");
1422 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &tmp_64
, ", ", &tmp
, ");\n");
1423 OUT(c
, locp
, "tcg_gen_add_i64(", &res
);
1424 OUT(c
, locp
, ", ", &res
, ", ", &tmp_64
, ");\n");
1429 HexValue
gen_convround_n(Context
*c
,
1434 HexValue zero
= gen_constant(c
, locp
, "0", 64, UNSIGNED
);
1435 HexValue l_32
= gen_constant(c
, locp
, "1", 32, UNSIGNED
);
1436 HexValue cond
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1437 HexValue cond_64
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1438 HexValue mask
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1439 HexValue n_64
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1440 HexValue res
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1441 /* If input is 64 bit cast it to 32 */
1442 HexValue src_casted
= gen_cast_op(c
, locp
, src
, 32, src
->signedness
);
1443 HexValue pos_casted
= gen_cast_op(c
, locp
, pos
, 32, pos
->signedness
);
1448 src_casted
= rvalue_materialize(c
, locp
, &src_casted
);
1449 pos_casted
= rvalue_materialize(c
, locp
, &pos_casted
);
1452 * r1, r2, and r3 represent the results of three different branches.
1453 * - r1 picked if pos_casted == 0
1454 * - r2 picked if (src_casted & ((1 << (pos_casted - 1)) - 1)) == 0),
1455 * that is if bits 0, ..., pos_casted-1 are all 0.
1456 * - r3 picked otherwise.
1458 r1
= gen_rvalue_extend(c
, locp
, &src_casted
);
1459 r2
= gen_convround_n_b(c
, locp
, &src_casted
, &pos_casted
);
1460 r3
= gen_convround_n_c(c
, locp
, &src_casted
, &pos_casted
);
1463 * Calculate the condition
1464 * (src_casted & ((1 << (pos_casted - 1)) - 1)) == 0),
1465 * which checks if the bits 0,...,pos-1 are all 0.
1467 OUT(c
, locp
, "tcg_gen_sub_i32(", &mask
);
1468 OUT(c
, locp
, ", ", &pos_casted
, ", ", &l_32
, ");\n");
1469 OUT(c
, locp
, "tcg_gen_shl_i32(", &mask
);
1470 OUT(c
, locp
, ", ", &l_32
, ", ", &mask
, ");\n");
1471 OUT(c
, locp
, "tcg_gen_sub_i32(", &mask
);
1472 OUT(c
, locp
, ", ", &mask
, ", ", &l_32
, ");\n");
1473 OUT(c
, locp
, "tcg_gen_and_i32(", &cond
);
1474 OUT(c
, locp
, ", ", &src_casted
, ", ", &mask
, ");\n");
1475 OUT(c
, locp
, "tcg_gen_extu_i32_i64(", &cond_64
, ", ", &cond
, ");\n");
1477 OUT(c
, locp
, "tcg_gen_ext_i32_i64(", &n_64
, ", ", &pos_casted
, ");\n");
1480 * if the bits 0, ..., pos_casted-1 are all 0, then pick r2 otherwise,
1483 OUT(c
, locp
, "tcg_gen_movcond_i64");
1484 OUT(c
, locp
, "(TCG_COND_EQ, ", &res
, ", ", &cond_64
, ", ", &zero
);
1485 OUT(c
, locp
, ", ", &r2
, ", ", &r3
, ");\n");
1487 /* Lastly, if the pos_casted == 0, then pick r1 */
1488 OUT(c
, locp
, "tcg_gen_movcond_i64");
1489 OUT(c
, locp
, "(TCG_COND_EQ, ", &res
, ", ", &n_64
, ", ", &zero
);
1490 OUT(c
, locp
, ", ", &r1
, ", ", &res
, ");\n");
1492 /* Finally shift back val >>= n */
1493 OUT(c
, locp
, "tcg_gen_shr_i64(", &res
);
1494 OUT(c
, locp
, ", ", &res
, ", ", &n_64
, ");\n");
1496 res
= gen_rvalue_truncate(c
, locp
, &res
);
1500 HexValue
gen_round(Context
*c
,
1505 HexValue zero
= gen_constant(c
, locp
, "0", 64, UNSIGNED
);
1506 HexValue one
= gen_constant(c
, locp
, "1", 64, UNSIGNED
);
1515 assert_signedness(c
, locp
, src
->signedness
);
1516 yyassert(c
, locp
, src
->bit_width
<= 32,
1517 "fRNDN not implemented for bit widths > 32!");
1519 res
= gen_tmp(c
, locp
, 64, src
->signedness
);
1521 src_width
= gen_imm_value(c
, locp
, src
->bit_width
, 32, UNSIGNED
);
1522 a
= gen_extend_op(c
, locp
, &src_width
, 64, src
, SIGNED
);
1523 a
= rvalue_materialize(c
, locp
, &a
);
1525 src_width
= gen_imm_value(c
, locp
, 5, 32, UNSIGNED
);
1526 b
= gen_extend_op(c
, locp
, &src_width
, 64, pos
, UNSIGNED
);
1527 b
= rvalue_materialize(c
, locp
, &b
);
1529 n_m1
= gen_bin_op(c
, locp
, SUB_OP
, &b
, &one
);
1530 shifted
= gen_bin_op(c
, locp
, ASL_OP
, &one
, &n_m1
);
1531 sum
= gen_bin_op(c
, locp
, ADD_OP
, &shifted
, &a
);
1533 OUT(c
, locp
, "tcg_gen_movcond_i64");
1534 OUT(c
, locp
, "(TCG_COND_EQ, ", &res
, ", ", &b
, ", ", &zero
);
1535 OUT(c
, locp
, ", ", &a
, ", ", &sum
, ");\n");
1540 /* Circular addressing mode with auto-increment */
1541 void gen_circ_op(Context
*c
,
1544 HexValue
*increment
,
1547 HexValue cs
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1548 HexValue increment_m
= *increment
;
1549 increment_m
= rvalue_materialize(c
, locp
, &increment_m
);
1550 OUT(c
, locp
, "gen_read_reg(", &cs
, ", HEX_REG_CS0 + MuN);\n");
1553 "gen_helper_fcircadd(",
1561 OUT(c
, locp
, ", ", &cs
, ");\n");
1564 HexValue
gen_locnt_op(Context
*c
, YYLTYPE
*locp
, HexValue
*src
)
1566 const char *bit_suffix
= src
->bit_width
== 64 ? "64" : "32";
1567 HexValue src_m
= *src
;
1570 assert_signedness(c
, locp
, src
->signedness
);
1571 res
= gen_tmp(c
, locp
, src
->bit_width
== 64 ? 64 : 32, src
->signedness
);
1572 src_m
= rvalue_materialize(c
, locp
, &src_m
);
1573 OUT(c
, locp
, "tcg_gen_not_i", bit_suffix
, "(",
1574 &res
, ", ", &src_m
, ");\n");
1575 OUT(c
, locp
, "tcg_gen_clzi_i", bit_suffix
, "(", &res
, ", ", &res
, ", ");
1576 OUT(c
, locp
, bit_suffix
, ");\n");
1580 HexValue
gen_ctpop_op(Context
*c
, YYLTYPE
*locp
, HexValue
*src
)
1582 const char *bit_suffix
= src
->bit_width
== 64 ? "64" : "32";
1583 HexValue src_m
= *src
;
1585 assert_signedness(c
, locp
, src
->signedness
);
1586 res
= gen_tmp(c
, locp
, src
->bit_width
== 64 ? 64 : 32, src
->signedness
);
1587 src_m
= rvalue_materialize(c
, locp
, &src_m
);
1588 OUT(c
, locp
, "tcg_gen_ctpop_i", bit_suffix
,
1589 "(", &res
, ", ", &src_m
, ");\n");
1593 HexValue
gen_rotl(Context
*c
, YYLTYPE
*locp
, HexValue
*src
, HexValue
*width
)
1595 const char *suffix
= src
->bit_width
== 64 ? "i64" : "i32";
1596 HexValue amount
= *width
;
1598 assert_signedness(c
, locp
, src
->signedness
);
1599 res
= gen_tmp(c
, locp
, src
->bit_width
, src
->signedness
);
1600 if (amount
.bit_width
< src
->bit_width
) {
1601 amount
= gen_rvalue_extend(c
, locp
, &amount
);
1603 amount
= gen_rvalue_truncate(c
, locp
, &amount
);
1605 amount
= rvalue_materialize(c
, locp
, &amount
);
1606 OUT(c
, locp
, "tcg_gen_rotl_", suffix
, "(",
1607 &res
, ", ", src
, ", ", &amount
, ");\n");
1612 HexValue
gen_carry_from_add(Context
*c
,
1618 HexValue zero
= gen_constant(c
, locp
, "0", 64, UNSIGNED
);
1619 HexValue res
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1620 HexValue cf
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1621 HexValue op1_m
= rvalue_materialize(c
, locp
, op1
);
1622 HexValue op2_m
= rvalue_materialize(c
, locp
, op2
);
1623 HexValue op3_m
= rvalue_materialize(c
, locp
, op3
);
1624 op3_m
= gen_rvalue_extend(c
, locp
, &op3_m
);
1626 OUT(c
, locp
, "tcg_gen_add2_i64(", &res
, ", ", &cf
, ", ", &op1_m
, ", ",
1628 OUT(c
, locp
, ", ", &op3_m
, ", ", &zero
, ");\n");
1629 OUT(c
, locp
, "tcg_gen_add2_i64(", &res
, ", ", &cf
, ", ", &res
, ", ", &cf
);
1630 OUT(c
, locp
, ", ", &op2_m
, ", ", &zero
, ");\n");
1635 void gen_addsat64(Context
*c
,
1641 HexValue op1_m
= rvalue_materialize(c
, locp
, op1
);
1642 HexValue op2_m
= rvalue_materialize(c
, locp
, op2
);
1643 OUT(c
, locp
, "gen_add_sat_i64(ctx, ", dst
, ", ", &op1_m
, ", ",
1647 void gen_inst(Context
*c
, GString
*iname
)
1650 c
->inst
.name
= iname
;
1651 c
->inst
.allocated
= g_array_new(FALSE
, FALSE
, sizeof(Var
));
1652 c
->inst
.init_list
= g_array_new(FALSE
, FALSE
, sizeof(HexValue
));
1653 c
->inst
.strings
= g_array_new(FALSE
, FALSE
, sizeof(GString
*));
1654 EMIT_SIG(c
, "void emit_%s(DisasContext *ctx, Insn *insn, Packet *pkt",
1660 * Initialize declared but uninitialized registers, but only for
1661 * non-conditional instructions
1663 void gen_inst_init_args(Context
*c
, YYLTYPE
*locp
)
1665 if (!c
->inst
.init_list
) {
1669 for (unsigned i
= 0; i
< c
->inst
.init_list
->len
; i
++) {
1670 HexValue
*val
= &g_array_index(c
->inst
.init_list
, HexValue
, i
);
1671 if (val
->type
== REGISTER_ARG
) {
1672 /* Nothing to do here */
1673 } else if (val
->type
== PREDICATE
) {
1674 char suffix
= val
->is_dotnew
? 'N' : 'V';
1675 EMIT_HEAD(c
, "tcg_gen_movi_i%u(P%c%c, 0);\n", val
->bit_width
,
1676 val
->pred
.id
, suffix
);
1678 yyassert(c
, locp
, false, "Invalid arg type!");
1682 /* Free argument init list once we have initialized everything */
1683 g_array_free(c
->inst
.init_list
, TRUE
);
1684 c
->inst
.init_list
= NULL
;
1687 void gen_inst_code(Context
*c
, YYLTYPE
*locp
)
1689 if (c
->inst
.error_count
!= 0) {
1691 "Parsing of instruction %s generated %d errors!\n",
1693 c
->inst
.error_count
);
1695 c
->implemented_insn
++;
1696 fprintf(c
->enabled_file
, "%s\n", c
->inst
.name
->str
);
1700 free_instruction(c
);
1703 void gen_pred_assign(Context
*c
, YYLTYPE
*locp
, HexValue
*left_pred
,
1704 HexValue
*right_pred
)
1706 char pred_id
[2] = {left_pred
->pred
.id
, 0};
1707 bool is_direct
= is_direct_predicate(left_pred
);
1708 HexValue r
= rvalue_materialize(c
, locp
, right_pred
);
1709 r
= gen_rvalue_truncate(c
, locp
, &r
);
1710 yyassert(c
, locp
, !is_inside_ternary(c
),
1711 "Predicate assign not allowed in ternary!");
1712 /* Extract predicate TCGv */
1714 *left_pred
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1716 /* Extract first 8 bits, and store new predicate value */
1717 OUT(c
, locp
, "tcg_gen_andi_i32(", left_pred
, ", ", &r
, ", 0xff);\n");
1719 OUT(c
, locp
, "gen_log_pred_write(ctx, ", pred_id
, ", ", left_pred
,
1724 void gen_cancel(Context
*c
, YYLTYPE
*locp
)
1726 OUT(c
, locp
, "gen_cancel(insn->slot);\n");
1729 void gen_load_cancel(Context
*c
, YYLTYPE
*locp
)
1731 OUT(c
, locp
, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n");
1732 OUT(c
, locp
, "ctx->s1_store_processed = false;\n");
1733 OUT(c
, locp
, "process_store(ctx, 1);\n");
1734 OUT(c
, locp
, "}\n");
1737 void gen_load(Context
*c
, YYLTYPE
*locp
, HexValue
*width
,
1738 HexSignedness signedness
, HexValue
*ea
, HexValue
*dst
)
1740 char size_suffix
[4] = {0};
1741 const char *sign_suffix
;
1742 /* Memop width is specified in the load macro */
1743 assert_signedness(c
, locp
, signedness
);
1744 sign_suffix
= (width
->imm
.value
> 4)
1746 : ((signedness
== UNSIGNED
) ? "u" : "s");
1747 /* If dst is a variable, assert that is declared and load the type info */
1748 if (dst
->type
== VARID
) {
1749 find_variable(c
, locp
, dst
, dst
);
1752 snprintf(size_suffix
, 4, "%" PRIu64
, width
->imm
.value
* 8);
1753 /* Lookup the effective address EA */
1754 find_variable(c
, locp
, ea
, ea
);
1755 OUT(c
, locp
, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n");
1756 OUT(c
, locp
, "probe_noshuf_load(", ea
, ", ", width
, ", ctx->mem_idx);\n");
1757 OUT(c
, locp
, "process_store(ctx, 1);\n");
1758 OUT(c
, locp
, "}\n");
1759 OUT(c
, locp
, "tcg_gen_qemu_ld", size_suffix
, sign_suffix
);
1761 if (dst
->bit_width
> width
->imm
.value
* 8) {
1763 * Cast to the correct TCG type if necessary, to avoid implict cast
1764 * warnings. This is needed when the width of the destination var is
1765 * larger than the size of the requested load.
1767 OUT(c
, locp
, "(TCGv) ");
1769 OUT(c
, locp
, dst
, ", ", ea
, ", ctx->mem_idx);\n");
1772 void gen_store(Context
*c
, YYLTYPE
*locp
, HexValue
*width
, HexValue
*ea
,
1775 HexValue src_m
= *src
;
1776 /* Memop width is specified in the store macro */
1777 unsigned mem_width
= width
->imm
.value
;
1778 /* Lookup the effective address EA */
1779 find_variable(c
, locp
, ea
, ea
);
1780 src_m
= rvalue_materialize(c
, locp
, &src_m
);
1781 OUT(c
, locp
, "gen_store", &mem_width
, "(cpu_env, ", ea
, ", ", &src_m
);
1782 OUT(c
, locp
, ", insn->slot);\n");
1785 void gen_sethalf(Context
*c
, YYLTYPE
*locp
, HexCast
*sh
, HexValue
*n
,
1786 HexValue
*dst
, HexValue
*value
)
1788 yyassert(c
, locp
, n
->type
== IMMEDIATE
,
1789 "Deposit index must be immediate!\n");
1790 if (dst
->type
== VARID
) {
1791 find_variable(c
, locp
, dst
, dst
);
1794 gen_deposit_op(c
, locp
, dst
, value
, n
, sh
);
1797 void gen_setbits(Context
*c
, YYLTYPE
*locp
, HexValue
*hi
, HexValue
*lo
,
1798 HexValue
*dst
, HexValue
*value
)
1803 yyassert(c
, locp
, hi
->type
== IMMEDIATE
&&
1804 hi
->imm
.type
== VALUE
&&
1805 lo
->type
== IMMEDIATE
&&
1806 lo
->imm
.type
== VALUE
,
1807 "Range deposit needs immediate values!\n");
1809 *value
= gen_rvalue_truncate(c
, locp
, value
);
1810 len
= hi
->imm
.value
+ 1 - lo
->imm
.value
;
1811 tmp
= gen_tmp(c
, locp
, 32, value
->signedness
);
1812 /* Emit an `and` to ensure `value` is either 0 or 1. */
1813 OUT(c
, locp
, "tcg_gen_andi_i32(", &tmp
, ", ", value
, ", 1);\n");
1814 /* Use `neg` to map 0 -> 0 and 1 -> 0xffff... */
1815 OUT(c
, locp
, "tcg_gen_neg_i32(", &tmp
, ", ", &tmp
, ");\n");
1816 OUT(c
, locp
, "tcg_gen_deposit_i32(", dst
, ", ", dst
,
1818 OUT(c
, locp
, lo
, ", ", &len
, ");\n");
1821 unsigned gen_if_cond(Context
*c
, YYLTYPE
*locp
, HexValue
*cond
)
1823 const char *bit_suffix
;
1824 /* Generate an end label, if false branch to that label */
1825 OUT(c
, locp
, "TCGLabel *if_label_", &c
->inst
.if_count
,
1826 " = gen_new_label();\n");
1827 *cond
= rvalue_materialize(c
, locp
, cond
);
1828 bit_suffix
= (cond
->bit_width
== 64) ? "i64" : "i32";
1829 OUT(c
, locp
, "tcg_gen_brcondi_", bit_suffix
, "(TCG_COND_EQ, ", cond
,
1830 ", 0, if_label_", &c
->inst
.if_count
, ");\n");
1831 return c
->inst
.if_count
++;
1834 unsigned gen_if_else(Context
*c
, YYLTYPE
*locp
, unsigned index
)
1836 unsigned if_index
= c
->inst
.if_count
++;
1837 /* Generate label to jump if else is not verified */
1838 OUT(c
, locp
, "TCGLabel *if_label_", &if_index
,
1839 " = gen_new_label();\n");
1840 /* Jump out of the else statement */
1841 OUT(c
, locp
, "tcg_gen_br(if_label_", &if_index
, ");\n");
1842 /* Fix the else label */
1843 OUT(c
, locp
, "gen_set_label(if_label_", &index
, ");\n");
1847 HexValue
gen_rvalue_pred(Context
*c
, YYLTYPE
*locp
, HexValue
*pred
)
1849 /* Predicted instructions need to zero out result args */
1850 gen_inst_init_args(c
, locp
);
1852 if (is_direct_predicate(pred
)) {
1853 bool is_dotnew
= pred
->is_dotnew
;
1854 char predicate_id
[2] = { pred
->pred
.id
, '\0' };
1855 char *pred_str
= (char *) &predicate_id
;
1856 *pred
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1858 OUT(c
, locp
, "tcg_gen_mov_i32(", pred
,
1859 ", hex_new_pred_value[");
1860 OUT(c
, locp
, pred_str
, "]);\n");
1862 OUT(c
, locp
, "gen_read_preg(", pred
, ", ", pred_str
, ");\n");
1869 HexValue
gen_rvalue_var(Context
*c
, YYLTYPE
*locp
, HexValue
*var
)
1871 find_variable(c
, locp
, var
, var
);
1875 HexValue
gen_rvalue_mpy(Context
*c
, YYLTYPE
*locp
, HexMpy
*mpy
,
1876 HexValue
*op1
, HexValue
*op2
)
1879 memset(&res
, 0, sizeof(HexValue
));
1881 assert_signedness(c
, locp
, mpy
->first_signedness
);
1882 assert_signedness(c
, locp
, mpy
->second_signedness
);
1884 *op1
= gen_cast_op(c
, locp
, op1
, mpy
->first_bit_width
* 2,
1885 mpy
->first_signedness
);
1886 /* Handle fMPTY3216.. */
1887 if (mpy
->first_bit_width
== 32) {
1888 *op2
= gen_cast_op(c
, locp
, op2
, 64, mpy
->second_signedness
);
1890 *op2
= gen_cast_op(c
, locp
, op2
, mpy
->second_bit_width
* 2,
1891 mpy
->second_signedness
);
1893 res
= gen_bin_op(c
, locp
, MUL_OP
, op1
, op2
);
1894 /* Handle special cases required by the language */
1895 if (mpy
->first_bit_width
== 16 && mpy
->second_bit_width
== 16) {
1896 HexValue src_width
= gen_imm_value(c
, locp
, 32, 32, UNSIGNED
);
1897 HexSignedness signedness
= bin_op_signedness(c
, locp
,
1898 mpy
->first_signedness
,
1899 mpy
->second_signedness
);
1900 res
= gen_extend_op(c
, locp
, &src_width
, 64, &res
,
1906 static inline HexValue
gen_rvalue_simple_unary(Context
*c
, YYLTYPE
*locp
,
1909 const char *tcg_code
)
1911 unsigned bit_width
= (value
->bit_width
== 64) ? 64 : 32;
1913 if (value
->type
== IMMEDIATE
) {
1914 res
= gen_imm_qemu_tmp(c
, locp
, bit_width
, value
->signedness
);
1915 gen_c_int_type(c
, locp
, value
->bit_width
, value
->signedness
);
1916 OUT(c
, locp
, " ", &res
, " = ", c_code
, "(", value
, ");\n");
1918 res
= gen_tmp(c
, locp
, bit_width
, value
->signedness
);
1919 OUT(c
, locp
, tcg_code
, "_i", &bit_width
, "(", &res
, ", ", value
,
1926 HexValue
gen_rvalue_not(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1928 return gen_rvalue_simple_unary(c
, locp
, value
, "~", "tcg_gen_not");
1931 HexValue
gen_rvalue_notl(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1933 unsigned bit_width
= (value
->bit_width
== 64) ? 64 : 32;
1935 if (value
->type
== IMMEDIATE
) {
1936 res
= gen_imm_qemu_tmp(c
, locp
, bit_width
, value
->signedness
);
1937 gen_c_int_type(c
, locp
, value
->bit_width
, value
->signedness
);
1938 OUT(c
, locp
, " ", &res
, " = !(", value
, ");\n");
1940 HexValue zero
= gen_constant(c
, locp
, "0", bit_width
, UNSIGNED
);
1941 HexValue one
= gen_constant(c
, locp
, "0xff", bit_width
, UNSIGNED
);
1942 res
= gen_tmp(c
, locp
, bit_width
, value
->signedness
);
1943 OUT(c
, locp
, "tcg_gen_movcond_i", &bit_width
);
1944 OUT(c
, locp
, "(TCG_COND_EQ, ", &res
, ", ", value
, ", ", &zero
);
1945 OUT(c
, locp
, ", ", &one
, ", ", &zero
, ");\n");
1950 HexValue
gen_rvalue_sat(Context
*c
, YYLTYPE
*locp
, HexSat
*sat
,
1951 HexValue
*width
, HexValue
*value
)
1953 const char *unsigned_str
;
1954 const char *bit_suffix
= (value
->bit_width
== 64) ? "i64" : "i32";
1958 * Note: all saturates are assumed to implicitly set overflow.
1959 * This assumption holds for the instructions currently parsed
1962 yyassert(c
, locp
, width
->imm
.value
< value
->bit_width
,
1963 "To compute overflow, source width must be greater than"
1964 " saturation width!");
1965 yyassert(c
, locp
, !is_inside_ternary(c
),
1966 "Saturating from within a ternary is not allowed!");
1967 assert_signedness(c
, locp
, sat
->signedness
);
1969 unsigned_str
= (sat
->signedness
== UNSIGNED
) ? "u" : "";
1970 res
= gen_tmp(c
, locp
, value
->bit_width
, sat
->signedness
);
1971 ovfl
= gen_tmp(c
, locp
, 32, sat
->signedness
);
1972 OUT(c
, locp
, "gen_sat", unsigned_str
, "_", bit_suffix
, "_ovfl(");
1973 OUT(c
, locp
, &ovfl
, ", ", &res
, ", ", value
, ", ", &width
->imm
.value
,
1975 OUT(c
, locp
, "gen_set_usr_field_if(ctx, USR_OVF,", &ovfl
, ");\n");
1980 HexValue
gen_rvalue_fscr(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1982 HexValue key
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1983 HexValue res
= gen_tmp(c
, locp
, 64, UNSIGNED
);
1984 HexValue frame_key
= gen_tmp(c
, locp
, 32, UNSIGNED
);
1985 *value
= gen_rvalue_extend(c
, locp
, value
);
1986 OUT(c
, locp
, "gen_read_reg(", &frame_key
, ", HEX_REG_FRAMEKEY);\n");
1987 OUT(c
, locp
, "tcg_gen_concat_i32_i64(",
1988 &key
, ", ", &frame_key
, ", ", &frame_key
, ");\n");
1989 OUT(c
, locp
, "tcg_gen_xor_i64(", &res
, ", ", value
, ", ", &key
, ");\n");
1993 HexValue
gen_rvalue_abs(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
1995 return gen_rvalue_simple_unary(c
, locp
, value
, "abs", "tcg_gen_abs");
1998 HexValue
gen_rvalue_neg(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
2000 return gen_rvalue_simple_unary(c
, locp
, value
, "-", "tcg_gen_neg");
2003 HexValue
gen_rvalue_brev(Context
*c
, YYLTYPE
*locp
, HexValue
*value
)
2006 yyassert(c
, locp
, value
->bit_width
<= 32,
2007 "fbrev not implemented for 64-bit integers!");
2008 res
= gen_tmp(c
, locp
, value
->bit_width
, value
->signedness
);
2009 *value
= rvalue_materialize(c
, locp
, value
);
2010 OUT(c
, locp
, "gen_helper_fbrev(", &res
, ", ", value
, ");\n");
2014 HexValue
gen_rvalue_ternary(Context
*c
, YYLTYPE
*locp
, HexValue
*cond
,
2015 HexValue
*true_branch
, HexValue
*false_branch
)
2017 bool is_64bit
= (true_branch
->bit_width
== 64) ||
2018 (false_branch
->bit_width
== 64);
2019 unsigned bit_width
= (is_64bit
) ? 64 : 32;
2020 HexValue zero
= gen_constant(c
, locp
, "0", bit_width
, UNSIGNED
);
2021 HexValue res
= gen_tmp(c
, locp
, bit_width
, UNSIGNED
);
2024 *cond
= gen_rvalue_extend(c
, locp
, cond
);
2025 *true_branch
= gen_rvalue_extend(c
, locp
, true_branch
);
2026 *false_branch
= gen_rvalue_extend(c
, locp
, false_branch
);
2028 *cond
= gen_rvalue_truncate(c
, locp
, cond
);
2030 *cond
= rvalue_materialize(c
, locp
, cond
);
2031 *true_branch
= rvalue_materialize(c
, locp
, true_branch
);
2032 *false_branch
= rvalue_materialize(c
, locp
, false_branch
);
2034 OUT(c
, locp
, "tcg_gen_movcond_i", &bit_width
);
2035 OUT(c
, locp
, "(TCG_COND_NE, ", &res
, ", ", cond
, ", ", &zero
);
2036 OUT(c
, locp
, ", ", true_branch
, ", ", false_branch
, ");\n");
2038 assert(c
->ternary
->len
> 0);
2039 g_array_remove_index(c
->ternary
, c
->ternary
->len
- 1);
2044 const char *cond_to_str(TCGCond cond
)
2047 case TCG_COND_NEVER
:
2048 return "TCG_COND_NEVER";
2049 case TCG_COND_ALWAYS
:
2050 return "TCG_COND_ALWAYS";
2052 return "TCG_COND_EQ";
2054 return "TCG_COND_NE";
2056 return "TCG_COND_LT";
2058 return "TCG_COND_GE";
2060 return "TCG_COND_LE";
2062 return "TCG_COND_GT";
2064 return "TCG_COND_LTU";
2066 return "TCG_COND_GEU";
2068 return "TCG_COND_LEU";
2070 return "TCG_COND_GTU";
2076 void emit_arg(Context
*c
, YYLTYPE
*locp
, HexValue
*arg
)
2078 switch (arg
->type
) {
2080 if (arg
->reg
.type
== DOTNEW
) {
2081 EMIT_SIG(c
, ", TCGv N%cN", arg
->reg
.id
);
2083 bool is64
= (arg
->bit_width
== 64);
2084 const char *type
= is64
? "TCGv_i64" : "TCGv_i32";
2086 reg_compose(c
, locp
, &(arg
->reg
), reg_id
);
2087 EMIT_SIG(c
, ", %s %s", type
, reg_id
);
2088 /* MuV register requires also MuN to provide its index */
2089 if (arg
->reg
.type
== MODIFIER
) {
2090 EMIT_SIG(c
, ", int MuN");
2096 char suffix
= arg
->is_dotnew
? 'N' : 'V';
2097 EMIT_SIG(c
, ", TCGv P%c%c", arg
->pred
.id
, suffix
);
2102 fprintf(stderr
, "emit_arg got unsupported argument!");
2108 void emit_footer(Context
*c
)
2114 void track_string(Context
*c
, GString
*s
)
2116 g_array_append_val(c
->inst
.strings
, s
);
2119 void free_instruction(Context
*c
)
2121 assert(!is_inside_ternary(c
));
2122 /* Free the strings */
2123 g_string_truncate(c
->signature_str
, 0);
2124 g_string_truncate(c
->out_str
, 0);
2125 g_string_truncate(c
->header_str
, 0);
2126 /* Free strings allocated by the instruction */
2127 for (unsigned i
= 0; i
< c
->inst
.strings
->len
; i
++) {
2128 g_string_free(g_array_index(c
->inst
.strings
, GString
*, i
), TRUE
);
2130 g_array_free(c
->inst
.strings
, TRUE
);
2131 /* Free INAME token value */
2132 g_string_free(c
->inst
.name
, TRUE
);
2133 /* Free variables and registers */
2134 g_array_free(c
->inst
.allocated
, TRUE
);
2135 /* Initialize instruction-specific portion of the context */
2136 memset(&(c
->inst
), 0, sizeof(Inst
));
2139 void assert_signedness(Context
*c
,
2141 HexSignedness signedness
)
2144 signedness
!= UNKNOWN_SIGNEDNESS
,
2145 "Unspecified signedness");