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 return true; 44 } 45 46 static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) 47 { 48 TCGv t0, t1; 49 50 if (a->rt == 0) { 51 /* nop */ 52 return true; 53 } 54 55 t0 = tcg_temp_new(); 56 t1 = tcg_temp_new(); 57 gen_load_gpr(t0, a->rs); 58 gen_load_gpr(t1, a->rt); 59 60 tcg_gen_add_tl(t0, t0, t1); 61 tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff); 62 return true; 63 } 64 65 static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) 66 { 67 TCGv t0, t1; 68 69 if (a->rt == 0) { 70 /* nop */ 71 return true; 72 } 73 74 t0 = tcg_temp_new(); 75 t1 = tcg_temp_new(); 76 gen_load_gpr(t0, a->rs); 77 gen_load_gpr(t1, a->rt); 78 79 tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1); 80 return true; 81 } 82 83 static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a) 84 { 85 TCGv t0; 86 87 if (a->rt == 0) { 88 /* nop */ 89 return true; 90 } 91 92 t0 = tcg_temp_new(); 93 gen_load_gpr(t0, a->rs); 94 tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1); 95 gen_store_gpr(t0, a->rt); 96 return true; 97 } 98 99 static bool trans_CINS(DisasContext *ctx, arg_CINS *a) 100 { 101 TCGv t0; 102 103 if (a->rt == 0) { 104 /* nop */ 105 return true; 106 } 107 108 t0 = tcg_temp_new(); 109 gen_load_gpr(t0, a->rs); 110 tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1); 111 gen_store_gpr(t0, a->rt); 112 return true; 113 } 114 115 static bool trans_POP(DisasContext *ctx, arg_POP *a) 116 { 117 TCGv t0; 118 119 if (a->rd == 0) { 120 /* nop */ 121 return true; 122 } 123 124 t0 = tcg_temp_new(); 125 gen_load_gpr(t0, a->rs); 126 if (!a->dw) { 127 tcg_gen_andi_i64(t0, t0, 0xffffffff); 128 } 129 tcg_gen_ctpop_tl(t0, t0); 130 gen_store_gpr(t0, a->rd); 131 return true; 132 } 133 134 static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a) 135 { 136 TCGv t0, t1; 137 138 if (a->rd == 0) { 139 /* nop */ 140 return true; 141 } 142 143 t0 = tcg_temp_new(); 144 t1 = tcg_temp_new(); 145 146 gen_load_gpr(t0, a->rs); 147 gen_load_gpr(t1, a->rt); 148 149 if (a->ne) { 150 tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0); 151 } else { 152 tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0); 153 } 154 return true; 155 } 156 157 static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a) 158 { 159 TCGv t0; 160 161 if (a->rt == 0) { 162 /* nop */ 163 return true; 164 } 165 166 t0 = tcg_temp_new(); 167 168 gen_load_gpr(t0, a->rs); 169 170 /* Sign-extend to 64 bit value */ 171 target_ulong imm = a->imm; 172 if (a->ne) { 173 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); 174 } else { 175 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm); 176 } 177 return true; 178 } 179