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