1 /* 2 * Octeon-specific instructions translation routines 3 * 4 * Copyright (c) 2022 Pavel Dovgalyuk 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "translate.h" 11 #include "tcg/tcg-op-gvec.h" 12 13 /* Include the auto-generated decoder. */ 14 #include "decode-octeon.c.inc" 15 16 static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) 17 { 18 TCGv p; 19 20 if (ctx->hflags & MIPS_HFLAG_BMASK) { 21 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" 22 TARGET_FMT_lx "\n", ctx->base.pc_next); 23 generate_exception_end(ctx, EXCP_RI); 24 return true; 25 } 26 27 /* Load needed operands */ 28 TCGv t0 = tcg_temp_new(); 29 gen_load_gpr(t0, a->rs); 30 31 p = tcg_constant_tl(1ULL << a->p); 32 if (a->set) { 33 tcg_gen_and_tl(bcond, p, t0); 34 } else { 35 tcg_gen_andc_tl(bcond, p, t0); 36 } 37 38 ctx->hflags |= MIPS_HFLAG_BC; 39 ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4; 40 ctx->hflags |= MIPS_HFLAG_BDS32; 41 return true; 42 } 43 44 static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) 45 { 46 TCGv t0, t1; 47 48 if (a->rt == 0) { 49 /* nop */ 50 return true; 51 } 52 53 t0 = tcg_temp_new(); 54 t1 = tcg_temp_new(); 55 gen_load_gpr(t0, a->rs); 56 gen_load_gpr(t1, a->rt); 57 58 tcg_gen_add_tl(t0, t0, t1); 59 tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff); 60 return true; 61 } 62 63 static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) 64 { 65 TCGv t0, t1; 66 67 if (a->rt == 0) { 68 /* nop */ 69 return true; 70 } 71 72 t0 = tcg_temp_new(); 73 t1 = tcg_temp_new(); 74 gen_load_gpr(t0, a->rs); 75 gen_load_gpr(t1, a->rt); 76 77 tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1); 78 return true; 79 } 80 81 static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a) 82 { 83 TCGv t0; 84 85 if (a->rt == 0) { 86 /* nop */ 87 return true; 88 } 89 90 t0 = tcg_temp_new(); 91 gen_load_gpr(t0, a->rs); 92 tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1); 93 gen_store_gpr(t0, a->rt); 94 return true; 95 } 96 97 static bool trans_CINS(DisasContext *ctx, arg_CINS *a) 98 { 99 TCGv t0; 100 101 if (a->rt == 0) { 102 /* nop */ 103 return true; 104 } 105 106 t0 = tcg_temp_new(); 107 gen_load_gpr(t0, a->rs); 108 tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1); 109 gen_store_gpr(t0, a->rt); 110 return true; 111 } 112 113 static bool trans_POP(DisasContext *ctx, arg_POP *a) 114 { 115 TCGv t0; 116 117 if (a->rd == 0) { 118 /* nop */ 119 return true; 120 } 121 122 t0 = tcg_temp_new(); 123 gen_load_gpr(t0, a->rs); 124 if (!a->dw) { 125 tcg_gen_andi_i64(t0, t0, 0xffffffff); 126 } 127 tcg_gen_ctpop_tl(t0, t0); 128 gen_store_gpr(t0, a->rd); 129 return true; 130 } 131 132 static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a) 133 { 134 TCGv t0, t1; 135 136 if (a->rd == 0) { 137 /* nop */ 138 return true; 139 } 140 141 t0 = tcg_temp_new(); 142 t1 = tcg_temp_new(); 143 144 gen_load_gpr(t0, a->rs); 145 gen_load_gpr(t1, a->rt); 146 147 if (a->ne) { 148 tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0); 149 } else { 150 tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0); 151 } 152 return true; 153 } 154 155 static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a) 156 { 157 TCGv t0; 158 159 if (a->rt == 0) { 160 /* nop */ 161 return true; 162 } 163 164 t0 = tcg_temp_new(); 165 166 gen_load_gpr(t0, a->rs); 167 168 /* Sign-extend to 64 bit value */ 169 target_ulong imm = a->imm; 170 if (a->ne) { 171 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); 172 } else { 173 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm); 174 } 175 return true; 176 } 177