On Thu, 24 Jun 2021 03:55:35 +0000 Taylor Simpson <tsimp...@quicinc.com> wrote:
> > + | rvalue '[' rvalue ']' > > + { > > + @1.last_column = @4.last_column; > > + if ($3.type == IMMEDIATE) { > > + $$ = gen_tmp(c, &@1, $1.bit_width); > > + OUT(c, &@1, "tcg_gen_extract_i", &$$.bit_width, > > "("); > > + OUT(c, &@1, &$$, ", ", &$1, ", ", &$3, ", 1);\n"); > > + } else { > > + HexValue one = gen_imm_value(c, &@1, 1, > > $3.bit_width); > > + HexValue tmp = gen_bin_op(c, &@1, ASR_OP, &$1, > > &$3); > > + $$ = gen_bin_op(c, &@1, ANDB_OP, &tmp, &one); > > Can this be done with a tcg_gen_extract_tl or tcg_gen_sextract_tl? Those require translation-time constants as offsets while we need TCGv: tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, unsigned int ofs, unsigned int len); > Do you need to worry about signed-ness? `gen_bin_op` should take care of that. On Thu, 24 Jun 2021 03:55:35 +0000 Taylor Simpson <tsimp...@quicinc.com> wrote: > > +void imm_print(Context *c, YYLTYPE *locp, HexImm *imm) > > +{ > > + switch (imm->type) { > > + case I: > > + EMIT(c, "i"); > > + break; > > + case VARIABLE: > > + EMIT(c, "%ciV", imm->id); > > + break; > > + case VALUE: > > + EMIT(c, "((int64_t)%" PRIu64 "ULL)", (int64_t)imm->value); > > + break; > > + case QEMU_TMP: > > + EMIT(c, "qemu_tmp_%" PRIu64, imm->index); > > + break; > > + case IMM_PC: > > + EMIT(c, "ctx->base.pc_next"); > > + break; > > + case IMM_NPC: > > + EMIT(c, "ctx->npc"); > > + break; > > + case IMM_CONSTEXT: > > + EMIT(c, "insn->extension_valid"); > > The extension_valid field is a bool indicating if the instruction has > a constant extender. Don't you want the actual value here? No, this maps to Constant_extended: #define fREAD_GP() (Constant_extended ? (0) : GP) Constant extensions is handle for us externally. On Thu, 24 Jun 2021 03:55:35 +0000 Taylor Simpson <tsimp...@quicinc.com> wrote: > > + if (dest->bit_width != res.bit_width) { > > + res = rvalue_truncate(c, locp, &res); > > + } > > + > > + HexValue zero = gen_tmp_value(c, locp, "0", res.bit_width); > > + OUT(c, locp, "tcg_gen_movcond_i", &res.bit_width, > > "(TCG_COND_NE, ", dest); > > + OUT(c, locp, ", ", &width_orig, ", ", &zero, ", ", &res, ", ", > > dest, > > + ");\n"); > > + > > + rvalue_free(c, locp, &zero); > > + rvalue_free(c, locp, width); > > + rvalue_free(c, locp, &res); > > +} > > + > > +void gen_deposit_op(Context *c, > > + YYLTYPE *locp, > > + HexValue *dest, > > + HexValue *value, > > + HexValue *index, > > + HexCast *cast) > > What's the difference between this and the gen_rdeposit_op above? `gen_rdeposit_op` is general purpose, it takes start and width of the deposit. `gen_deposit_op` is more tailored to handle `fINSERT_BITS`. We will improve `gen_rdeposit_op` in order to handle the immediate case efficiently and then implement `gen_deposit_op` with `gen_rdeposit_op`. -- Alessandro Di Federico rev.ng