| /* |
| * Octeon-specific instructions translation routines |
| * |
| * Copyright (c) 2022 Pavel Dovgalyuk |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "tcg/tcg-op.h" |
| #include "tcg/tcg-op-gvec.h" |
| #include "exec/helper-gen.h" |
| #include "translate.h" |
| |
| /* Include the auto-generated decoder. */ |
| #include "decode-octeon.c.inc" |
| |
| static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) |
| { |
| TCGv p; |
| |
| if (ctx->hflags & MIPS_HFLAG_BMASK) { |
| LOG_DISAS("Branch in delay / forbidden slot at PC 0x" |
| TARGET_FMT_lx "\n", ctx->base.pc_next); |
| generate_exception_end(ctx, EXCP_RI); |
| return true; |
| } |
| |
| /* Load needed operands */ |
| TCGv t0 = tcg_temp_new(); |
| gen_load_gpr(t0, a->rs); |
| |
| p = tcg_constant_tl(1ULL << a->p); |
| if (a->set) { |
| tcg_gen_and_tl(bcond, p, t0); |
| } else { |
| tcg_gen_andc_tl(bcond, p, t0); |
| } |
| |
| ctx->hflags |= MIPS_HFLAG_BC; |
| ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4; |
| ctx->hflags |= MIPS_HFLAG_BDS32; |
| |
| tcg_temp_free(t0); |
| return true; |
| } |
| |
| static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) |
| { |
| TCGv t0, t1; |
| |
| if (a->rt == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| t1 = tcg_temp_new(); |
| gen_load_gpr(t0, a->rs); |
| gen_load_gpr(t1, a->rt); |
| |
| tcg_gen_add_tl(t0, t0, t1); |
| tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff); |
| |
| tcg_temp_free(t0); |
| tcg_temp_free(t1); |
| |
| return true; |
| } |
| |
| static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) |
| { |
| TCGv t0, t1; |
| |
| if (a->rt == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| t1 = tcg_temp_new(); |
| gen_load_gpr(t0, a->rs); |
| gen_load_gpr(t1, a->rt); |
| |
| tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1); |
| |
| tcg_temp_free(t0); |
| tcg_temp_free(t1); |
| |
| return true; |
| } |
| |
| static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a) |
| { |
| TCGv t0; |
| |
| if (a->rt == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| gen_load_gpr(t0, a->rs); |
| tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1); |
| gen_store_gpr(t0, a->rt); |
| tcg_temp_free(t0); |
| |
| return true; |
| } |
| |
| static bool trans_CINS(DisasContext *ctx, arg_CINS *a) |
| { |
| TCGv t0; |
| |
| if (a->rt == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| gen_load_gpr(t0, a->rs); |
| tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1); |
| gen_store_gpr(t0, a->rt); |
| tcg_temp_free(t0); |
| |
| return true; |
| } |
| |
| static bool trans_POP(DisasContext *ctx, arg_POP *a) |
| { |
| TCGv t0; |
| |
| if (a->rd == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| gen_load_gpr(t0, a->rs); |
| if (!a->dw) { |
| tcg_gen_andi_i64(t0, t0, 0xffffffff); |
| } |
| tcg_gen_ctpop_tl(t0, t0); |
| gen_store_gpr(t0, a->rd); |
| tcg_temp_free(t0); |
| |
| return true; |
| } |
| |
| static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a) |
| { |
| TCGv t0, t1; |
| |
| if (a->rd == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| t1 = tcg_temp_new(); |
| |
| gen_load_gpr(t0, a->rs); |
| gen_load_gpr(t1, a->rt); |
| |
| if (a->ne) { |
| tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0); |
| } else { |
| tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0); |
| } |
| |
| tcg_temp_free(t0); |
| tcg_temp_free(t1); |
| |
| return true; |
| } |
| |
| static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a) |
| { |
| TCGv t0; |
| |
| if (a->rt == 0) { |
| /* nop */ |
| return true; |
| } |
| |
| t0 = tcg_temp_new(); |
| |
| gen_load_gpr(t0, a->rs); |
| |
| /* Sign-extend to 64 bit value */ |
| target_ulong imm = a->imm; |
| if (a->ne) { |
| tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); |
| } else { |
| tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm); |
| } |
| |
| tcg_temp_free(t0); |
| |
| return true; |
| } |