172d680e4SPavel Dovgalyuk /* 272d680e4SPavel Dovgalyuk * Octeon-specific instructions translation routines 372d680e4SPavel Dovgalyuk * 472d680e4SPavel Dovgalyuk * Copyright (c) 2022 Pavel Dovgalyuk 572d680e4SPavel Dovgalyuk * 672d680e4SPavel Dovgalyuk * SPDX-License-Identifier: GPL-2.0-or-later 772d680e4SPavel Dovgalyuk */ 872d680e4SPavel Dovgalyuk 972d680e4SPavel Dovgalyuk #include "qemu/osdep.h" 1072d680e4SPavel Dovgalyuk #include "translate.h" 118cab4157SRichard Henderson #include "tcg/tcg-op-gvec.h" 1272d680e4SPavel Dovgalyuk 1372d680e4SPavel Dovgalyuk /* Include the auto-generated decoder. */ 1472d680e4SPavel Dovgalyuk #include "decode-octeon.c.inc" 155e806fb0SPavel Dovgalyuk 165e806fb0SPavel Dovgalyuk static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) 175e806fb0SPavel Dovgalyuk { 185e806fb0SPavel Dovgalyuk TCGv p; 195e806fb0SPavel Dovgalyuk 205e806fb0SPavel Dovgalyuk if (ctx->hflags & MIPS_HFLAG_BMASK) { 21*a630055dSRichard Henderson LOG_DISAS("Branch in delay / forbidden slot at PC 0x%" VADDR_PRIx "\n", 22*a630055dSRichard Henderson ctx->base.pc_next); 235e806fb0SPavel Dovgalyuk generate_exception_end(ctx, EXCP_RI); 245e806fb0SPavel Dovgalyuk return true; 255e806fb0SPavel Dovgalyuk } 265e806fb0SPavel Dovgalyuk 275e806fb0SPavel Dovgalyuk /* Load needed operands */ 285e806fb0SPavel Dovgalyuk TCGv t0 = tcg_temp_new(); 295e806fb0SPavel Dovgalyuk gen_load_gpr(t0, a->rs); 305e806fb0SPavel Dovgalyuk 315e806fb0SPavel Dovgalyuk p = tcg_constant_tl(1ULL << a->p); 325e806fb0SPavel Dovgalyuk if (a->set) { 335e806fb0SPavel Dovgalyuk tcg_gen_and_tl(bcond, p, t0); 345e806fb0SPavel Dovgalyuk } else { 355e806fb0SPavel Dovgalyuk tcg_gen_andc_tl(bcond, p, t0); 365e806fb0SPavel Dovgalyuk } 375e806fb0SPavel Dovgalyuk 385e806fb0SPavel Dovgalyuk ctx->hflags |= MIPS_HFLAG_BC; 395e806fb0SPavel Dovgalyuk ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4; 405e806fb0SPavel Dovgalyuk ctx->hflags |= MIPS_HFLAG_BDS32; 415e806fb0SPavel Dovgalyuk return true; 425e806fb0SPavel Dovgalyuk } 43dadd071aSPavel Dovgalyuk 44dadd071aSPavel Dovgalyuk static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) 45dadd071aSPavel Dovgalyuk { 46dadd071aSPavel Dovgalyuk TCGv t0, t1; 47dadd071aSPavel Dovgalyuk 48dadd071aSPavel Dovgalyuk if (a->rt == 0) { 49dadd071aSPavel Dovgalyuk /* nop */ 50dadd071aSPavel Dovgalyuk return true; 51dadd071aSPavel Dovgalyuk } 52dadd071aSPavel Dovgalyuk 53dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 54dadd071aSPavel Dovgalyuk t1 = tcg_temp_new(); 55dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 56dadd071aSPavel Dovgalyuk gen_load_gpr(t1, a->rt); 57dadd071aSPavel Dovgalyuk 58dadd071aSPavel Dovgalyuk tcg_gen_add_tl(t0, t0, t1); 59dadd071aSPavel Dovgalyuk tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff); 60dadd071aSPavel Dovgalyuk return true; 61dadd071aSPavel Dovgalyuk } 62dadd071aSPavel Dovgalyuk 63dadd071aSPavel Dovgalyuk static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) 64dadd071aSPavel Dovgalyuk { 65dadd071aSPavel Dovgalyuk TCGv t0, t1; 66dadd071aSPavel Dovgalyuk 67dadd071aSPavel Dovgalyuk if (a->rt == 0) { 68dadd071aSPavel Dovgalyuk /* nop */ 69dadd071aSPavel Dovgalyuk return true; 70dadd071aSPavel Dovgalyuk } 71dadd071aSPavel Dovgalyuk 72dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 73dadd071aSPavel Dovgalyuk t1 = tcg_temp_new(); 74dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 75dadd071aSPavel Dovgalyuk gen_load_gpr(t1, a->rt); 76dadd071aSPavel Dovgalyuk 77dadd071aSPavel Dovgalyuk tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1); 78dadd071aSPavel Dovgalyuk return true; 79dadd071aSPavel Dovgalyuk } 80dadd071aSPavel Dovgalyuk 81dadd071aSPavel Dovgalyuk static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a) 82dadd071aSPavel Dovgalyuk { 83dadd071aSPavel Dovgalyuk TCGv t0; 84dadd071aSPavel Dovgalyuk 85dadd071aSPavel Dovgalyuk if (a->rt == 0) { 86dadd071aSPavel Dovgalyuk /* nop */ 87dadd071aSPavel Dovgalyuk return true; 88dadd071aSPavel Dovgalyuk } 89dadd071aSPavel Dovgalyuk 90dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 91dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 92dadd071aSPavel Dovgalyuk tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1); 93dadd071aSPavel Dovgalyuk gen_store_gpr(t0, a->rt); 94dadd071aSPavel Dovgalyuk return true; 95dadd071aSPavel Dovgalyuk } 96dadd071aSPavel Dovgalyuk 97dadd071aSPavel Dovgalyuk static bool trans_CINS(DisasContext *ctx, arg_CINS *a) 98dadd071aSPavel Dovgalyuk { 99dadd071aSPavel Dovgalyuk TCGv t0; 100dadd071aSPavel Dovgalyuk 101dadd071aSPavel Dovgalyuk if (a->rt == 0) { 102dadd071aSPavel Dovgalyuk /* nop */ 103dadd071aSPavel Dovgalyuk return true; 104dadd071aSPavel Dovgalyuk } 105dadd071aSPavel Dovgalyuk 106dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 107dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 108dadd071aSPavel Dovgalyuk tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1); 109dadd071aSPavel Dovgalyuk gen_store_gpr(t0, a->rt); 110dadd071aSPavel Dovgalyuk return true; 111dadd071aSPavel Dovgalyuk } 112dadd071aSPavel Dovgalyuk 113dadd071aSPavel Dovgalyuk static bool trans_POP(DisasContext *ctx, arg_POP *a) 114dadd071aSPavel Dovgalyuk { 115dadd071aSPavel Dovgalyuk TCGv t0; 116dadd071aSPavel Dovgalyuk 117dadd071aSPavel Dovgalyuk if (a->rd == 0) { 118dadd071aSPavel Dovgalyuk /* nop */ 119dadd071aSPavel Dovgalyuk return true; 120dadd071aSPavel Dovgalyuk } 121dadd071aSPavel Dovgalyuk 122dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 123dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 124dadd071aSPavel Dovgalyuk if (!a->dw) { 125dadd071aSPavel Dovgalyuk tcg_gen_andi_i64(t0, t0, 0xffffffff); 126dadd071aSPavel Dovgalyuk } 127dadd071aSPavel Dovgalyuk tcg_gen_ctpop_tl(t0, t0); 128dadd071aSPavel Dovgalyuk gen_store_gpr(t0, a->rd); 129dadd071aSPavel Dovgalyuk return true; 130dadd071aSPavel Dovgalyuk } 131dadd071aSPavel Dovgalyuk 132dadd071aSPavel Dovgalyuk static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a) 133dadd071aSPavel Dovgalyuk { 134dadd071aSPavel Dovgalyuk TCGv t0, t1; 135dadd071aSPavel Dovgalyuk 136dadd071aSPavel Dovgalyuk if (a->rd == 0) { 137dadd071aSPavel Dovgalyuk /* nop */ 138dadd071aSPavel Dovgalyuk return true; 139dadd071aSPavel Dovgalyuk } 140dadd071aSPavel Dovgalyuk 141dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 142dadd071aSPavel Dovgalyuk t1 = tcg_temp_new(); 143dadd071aSPavel Dovgalyuk 144dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 145dadd071aSPavel Dovgalyuk gen_load_gpr(t1, a->rt); 146dadd071aSPavel Dovgalyuk 147dadd071aSPavel Dovgalyuk if (a->ne) { 148dadd071aSPavel Dovgalyuk tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0); 149dadd071aSPavel Dovgalyuk } else { 150dadd071aSPavel Dovgalyuk tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0); 151dadd071aSPavel Dovgalyuk } 152dadd071aSPavel Dovgalyuk return true; 153dadd071aSPavel Dovgalyuk } 154dadd071aSPavel Dovgalyuk 155dadd071aSPavel Dovgalyuk static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a) 156dadd071aSPavel Dovgalyuk { 157dadd071aSPavel Dovgalyuk TCGv t0; 158dadd071aSPavel Dovgalyuk 159dadd071aSPavel Dovgalyuk if (a->rt == 0) { 160dadd071aSPavel Dovgalyuk /* nop */ 161dadd071aSPavel Dovgalyuk return true; 162dadd071aSPavel Dovgalyuk } 163dadd071aSPavel Dovgalyuk 164dadd071aSPavel Dovgalyuk t0 = tcg_temp_new(); 165dadd071aSPavel Dovgalyuk 166dadd071aSPavel Dovgalyuk gen_load_gpr(t0, a->rs); 167dadd071aSPavel Dovgalyuk 168dadd071aSPavel Dovgalyuk /* Sign-extend to 64 bit value */ 169dadd071aSPavel Dovgalyuk target_ulong imm = a->imm; 170dadd071aSPavel Dovgalyuk if (a->ne) { 171dadd071aSPavel Dovgalyuk tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); 172dadd071aSPavel Dovgalyuk } else { 173dadd071aSPavel Dovgalyuk tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm); 174dadd071aSPavel Dovgalyuk } 175dadd071aSPavel Dovgalyuk return true; 176dadd071aSPavel Dovgalyuk } 177