qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

fixedpoint-impl.c.inc (16771B)


      1 /*
      2  * Power ISA decode for Fixed-Point Facility instructions
      3  *
      4  * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 /*
     21  * Fixed-Point Load/Store Instructions
     22  */
     23 
     24 static bool do_ldst(DisasContext *ctx, int rt, int ra, TCGv displ, bool update,
     25                     bool store, MemOp mop)
     26 {
     27     TCGv ea;
     28 
     29     if (update && (ra == 0 || (!store && ra == rt))) {
     30         gen_invalid(ctx);
     31         return true;
     32     }
     33     gen_set_access_type(ctx, ACCESS_INT);
     34 
     35     ea = do_ea_calc(ctx, ra, displ);
     36     mop ^= ctx->default_tcg_memop_mask;
     37     if (store) {
     38         tcg_gen_qemu_st_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
     39     } else {
     40         tcg_gen_qemu_ld_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
     41     }
     42     if (update) {
     43         tcg_gen_mov_tl(cpu_gpr[ra], ea);
     44     }
     45     tcg_temp_free(ea);
     46 
     47     return true;
     48 }
     49 
     50 static bool do_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store,
     51                       MemOp mop)
     52 {
     53     return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, mop);
     54 }
     55 
     56 static bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
     57                           bool store, MemOp mop)
     58 {
     59     arg_D d;
     60     if (!resolve_PLS_D(ctx, &d, a)) {
     61         return true;
     62     }
     63     return do_ldst_D(ctx, &d, update, store, mop);
     64 }
     65 
     66 static bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
     67                       bool store, MemOp mop)
     68 {
     69     return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop);
     70 }
     71 
     72 static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
     73 {
     74 #if defined(TARGET_PPC64)
     75     TCGv ea;
     76     TCGv_i64 low_addr_gpr, high_addr_gpr;
     77     MemOp mop;
     78 
     79     REQUIRE_INSNS_FLAGS(ctx, 64BX);
     80 
     81     if (!prefixed && !(ctx->insns_flags2 & PPC2_LSQ_ISA207)) {
     82         /* lq and stq were privileged prior to V. 2.07 */
     83         REQUIRE_SV(ctx);
     84 
     85         if (ctx->le_mode) {
     86             gen_align_no_le(ctx);
     87             return true;
     88         }
     89     }
     90 
     91     if (!store && unlikely(a->ra == a->rt)) {
     92         gen_invalid(ctx);
     93         return true;
     94     }
     95 
     96     gen_set_access_type(ctx, ACCESS_INT);
     97     ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
     98 
     99     if (prefixed || !ctx->le_mode) {
    100         low_addr_gpr = cpu_gpr[a->rt];
    101         high_addr_gpr = cpu_gpr[a->rt + 1];
    102     } else {
    103         low_addr_gpr = cpu_gpr[a->rt + 1];
    104         high_addr_gpr = cpu_gpr[a->rt];
    105     }
    106 
    107     if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
    108         if (HAVE_ATOMIC128) {
    109             mop = DEF_MEMOP(MO_128);
    110             TCGv_i32 oi = tcg_constant_i32(make_memop_idx(mop, ctx->mem_idx));
    111             if (store) {
    112                 if (ctx->le_mode) {
    113                     gen_helper_stq_le_parallel(cpu_env, ea, low_addr_gpr,
    114                                                high_addr_gpr, oi);
    115                 } else {
    116                     gen_helper_stq_be_parallel(cpu_env, ea, high_addr_gpr,
    117                                                low_addr_gpr, oi);
    118 
    119                 }
    120             } else {
    121                 if (ctx->le_mode) {
    122                     gen_helper_lq_le_parallel(low_addr_gpr, cpu_env, ea, oi);
    123                     tcg_gen_ld_i64(high_addr_gpr, cpu_env,
    124                                    offsetof(CPUPPCState, retxh));
    125                 } else {
    126                     gen_helper_lq_be_parallel(high_addr_gpr, cpu_env, ea, oi);
    127                     tcg_gen_ld_i64(low_addr_gpr, cpu_env,
    128                                    offsetof(CPUPPCState, retxh));
    129                 }
    130             }
    131         } else {
    132             /* Restart with exclusive lock.  */
    133             gen_helper_exit_atomic(cpu_env);
    134             ctx->base.is_jmp = DISAS_NORETURN;
    135         }
    136     } else {
    137         mop = DEF_MEMOP(MO_UQ);
    138         if (store) {
    139             tcg_gen_qemu_st_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
    140         } else {
    141             tcg_gen_qemu_ld_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
    142         }
    143 
    144         gen_addr_add(ctx, ea, ea, 8);
    145 
    146         if (store) {
    147             tcg_gen_qemu_st_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
    148         } else {
    149             tcg_gen_qemu_ld_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
    150         }
    151     }
    152     tcg_temp_free(ea);
    153 #else
    154     qemu_build_not_reached();
    155 #endif
    156 
    157     return true;
    158 }
    159 
    160 static bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
    161 {
    162     arg_D d;
    163     if (!resolve_PLS_D(ctx, &d, a)) {
    164         return true;
    165     }
    166 
    167     return do_ldst_quad(ctx, &d, store, true);
    168 }
    169 
    170 /* Load Byte and Zero */
    171 TRANS(LBZ, do_ldst_D, false, false, MO_UB)
    172 TRANS(LBZX, do_ldst_X, false, false, MO_UB)
    173 TRANS(LBZU, do_ldst_D, true, false, MO_UB)
    174 TRANS(LBZUX, do_ldst_X, true, false, MO_UB)
    175 TRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
    176 
    177 /* Load Halfword and Zero */
    178 TRANS(LHZ, do_ldst_D, false, false, MO_UW)
    179 TRANS(LHZX, do_ldst_X, false, false, MO_UW)
    180 TRANS(LHZU, do_ldst_D, true, false, MO_UW)
    181 TRANS(LHZUX, do_ldst_X, true, false, MO_UW)
    182 TRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
    183 
    184 /* Load Halfword Algebraic */
    185 TRANS(LHA, do_ldst_D, false, false, MO_SW)
    186 TRANS(LHAX, do_ldst_X, false, false, MO_SW)
    187 TRANS(LHAU, do_ldst_D, true, false, MO_SW)
    188 TRANS(LHAXU, do_ldst_X, true, false, MO_SW)
    189 TRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
    190 
    191 /* Load Word and Zero */
    192 TRANS(LWZ, do_ldst_D, false, false, MO_UL)
    193 TRANS(LWZX, do_ldst_X, false, false, MO_UL)
    194 TRANS(LWZU, do_ldst_D, true, false, MO_UL)
    195 TRANS(LWZUX, do_ldst_X, true, false, MO_UL)
    196 TRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
    197 
    198 /* Load Word Algebraic */
    199 TRANS64(LWA, do_ldst_D, false, false, MO_SL)
    200 TRANS64(LWAX, do_ldst_X, false, false, MO_SL)
    201 TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
    202 TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
    203 
    204 /* Load Doubleword */
    205 TRANS64(LD, do_ldst_D, false, false, MO_UQ)
    206 TRANS64(LDX, do_ldst_X, false, false, MO_UQ)
    207 TRANS64(LDU, do_ldst_D, true, false, MO_UQ)
    208 TRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
    209 TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
    210 
    211 /* Load Quadword */
    212 TRANS64(LQ, do_ldst_quad, false, false);
    213 TRANS64(PLQ, do_ldst_quad_PLS_D, false);
    214 
    215 /* Store Byte */
    216 TRANS(STB, do_ldst_D, false, true, MO_UB)
    217 TRANS(STBX, do_ldst_X, false, true, MO_UB)
    218 TRANS(STBU, do_ldst_D, true, true, MO_UB)
    219 TRANS(STBUX, do_ldst_X, true, true, MO_UB)
    220 TRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
    221 
    222 /* Store Halfword */
    223 TRANS(STH, do_ldst_D, false, true, MO_UW)
    224 TRANS(STHX, do_ldst_X, false, true, MO_UW)
    225 TRANS(STHU, do_ldst_D, true, true, MO_UW)
    226 TRANS(STHUX, do_ldst_X, true, true, MO_UW)
    227 TRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
    228 
    229 /* Store Word */
    230 TRANS(STW, do_ldst_D, false, true, MO_UL)
    231 TRANS(STWX, do_ldst_X, false, true, MO_UL)
    232 TRANS(STWU, do_ldst_D, true, true, MO_UL)
    233 TRANS(STWUX, do_ldst_X, true, true, MO_UL)
    234 TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
    235 
    236 /* Store Doubleword */
    237 TRANS64(STD, do_ldst_D, false, true, MO_UQ)
    238 TRANS64(STDX, do_ldst_X, false, true, MO_UQ)
    239 TRANS64(STDU, do_ldst_D, true, true, MO_UQ)
    240 TRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
    241 TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
    242 
    243 /* Store Quadword */
    244 TRANS64(STQ, do_ldst_quad, true, false);
    245 TRANS64(PSTQ, do_ldst_quad_PLS_D, true);
    246 
    247 /*
    248  * Fixed-Point Compare Instructions
    249  */
    250 
    251 static bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s)
    252 {
    253     if ((ctx->insns_flags & PPC_64B) == 0) {
    254         /*
    255          * For 32-bit implementations, The Programming Environments Manual says
    256          * that "the L field must be cleared, otherwise the instruction form is
    257          * invalid." It seems, however, that most 32-bit CPUs ignore invalid
    258          * forms (e.g., section "Instruction Formats" of the 405 and 440
    259          * manuals, "Integer Compare Instructions" of the 601 manual), with the
    260          * notable exception of the e500 and e500mc, where L=1 was reported to
    261          * cause an exception.
    262          */
    263         if (a->l) {
    264             if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
    265                 /*
    266                  * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
    267                  * generate an illegal instruction exception.
    268                  */
    269                 return false;
    270             } else {
    271                 qemu_log_mask(LOG_GUEST_ERROR,
    272                         "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
    273                         s ? "" : "L", ctx->cia);
    274             }
    275         }
    276         gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
    277         return true;
    278     }
    279 
    280     /* For 64-bit implementations, deal with bit L accordingly. */
    281     if (a->l) {
    282         gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
    283     } else {
    284         gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
    285     }
    286     return true;
    287 }
    288 
    289 static bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s)
    290 {
    291     if ((ctx->insns_flags & PPC_64B) == 0) {
    292         /*
    293          * For 32-bit implementations, The Programming Environments Manual says
    294          * that "the L field must be cleared, otherwise the instruction form is
    295          * invalid." It seems, however, that most 32-bit CPUs ignore invalid
    296          * forms (e.g., section "Instruction Formats" of the 405 and 440
    297          * manuals, "Integer Compare Instructions" of the 601 manual), with the
    298          * notable exception of the e500 and e500mc, where L=1 was reported to
    299          * cause an exception.
    300          */
    301         if (a->l) {
    302             if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
    303                 /*
    304                  * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
    305                  * generate an illegal instruction exception.
    306                  */
    307                 return false;
    308             } else {
    309                 qemu_log_mask(LOG_GUEST_ERROR,
    310                         "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
    311                         s ? "I" : "LI", ctx->cia);
    312             }
    313         }
    314         gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
    315         return true;
    316     }
    317 
    318     /* For 64-bit implementations, deal with bit L accordingly. */
    319     if (a->l) {
    320         gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
    321     } else {
    322         gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
    323     }
    324     return true;
    325 }
    326 
    327 TRANS(CMP, do_cmp_X, true);
    328 TRANS(CMPL, do_cmp_X, false);
    329 TRANS(CMPI, do_cmp_D, true);
    330 TRANS(CMPLI, do_cmp_D, false);
    331 
    332 /*
    333  * Fixed-Point Arithmetic Instructions
    334  */
    335 
    336 static bool trans_ADDI(DisasContext *ctx, arg_D *a)
    337 {
    338     if (a->ra) {
    339         tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
    340     } else {
    341         tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
    342     }
    343     return true;
    344 }
    345 
    346 static bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
    347 {
    348     arg_D d;
    349     if (!resolve_PLS_D(ctx, &d, a)) {
    350         return true;
    351     }
    352     return trans_ADDI(ctx, &d);
    353 }
    354 
    355 static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
    356 {
    357     a->si <<= 16;
    358     return trans_ADDI(ctx, a);
    359 }
    360 
    361 static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
    362 {
    363     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    364     tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
    365     return true;
    366 }
    367 
    368 static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
    369 {
    370     gen_invalid(ctx);
    371     return true;
    372 }
    373 
    374 static bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
    375 {
    376     return true;
    377 }
    378 
    379 static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
    380 {
    381     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    382     uint32_t mask = 0x08 >> (a->bi & 0x03);
    383     TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
    384     TCGv temp = tcg_temp_new();
    385 
    386     tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
    387     tcg_gen_andi_tl(temp, temp, mask);
    388     tcg_gen_setcondi_tl(cond, cpu_gpr[a->rt], temp, 0);
    389     if (neg) {
    390         tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->rt]);
    391     }
    392     tcg_temp_free(temp);
    393 
    394     return true;
    395 }
    396 
    397 TRANS(SETBC, do_set_bool_cond, false, false)
    398 TRANS(SETBCR, do_set_bool_cond, false, true)
    399 TRANS(SETNBC, do_set_bool_cond, true, false)
    400 TRANS(SETNBCR, do_set_bool_cond, true, true)
    401 
    402 static bool trans_CFUGED(DisasContext *ctx, arg_X *a)
    403 {
    404     REQUIRE_64BIT(ctx);
    405     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    406 #if defined(TARGET_PPC64)
    407     gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
    408 #else
    409     qemu_build_not_reached();
    410 #endif
    411     return true;
    412 }
    413 
    414 static void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail)
    415 {
    416     TCGv_i64 t0, t1;
    417 
    418     t0 = tcg_temp_new_i64();
    419     t1 = tcg_temp_new_i64();
    420 
    421     tcg_gen_and_i64(t0, src, mask);
    422     if (trail) {
    423         tcg_gen_ctzi_i64(t0, t0, -1);
    424     } else {
    425         tcg_gen_clzi_i64(t0, t0, -1);
    426     }
    427 
    428     tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1);
    429     tcg_gen_andi_i64(t0, t0, 63);
    430     tcg_gen_xori_i64(t0, t0, 63);
    431     if (trail) {
    432         tcg_gen_shl_i64(t0, mask, t0);
    433         tcg_gen_shl_i64(t0, t0, t1);
    434     } else {
    435         tcg_gen_shr_i64(t0, mask, t0);
    436         tcg_gen_shr_i64(t0, t0, t1);
    437     }
    438 
    439     tcg_gen_ctpop_i64(dst, t0);
    440 
    441     tcg_temp_free_i64(t0);
    442     tcg_temp_free_i64(t1);
    443 }
    444 
    445 static bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
    446 {
    447     REQUIRE_64BIT(ctx);
    448     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    449 #if defined(TARGET_PPC64)
    450     do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false);
    451 #else
    452     qemu_build_not_reached();
    453 #endif
    454     return true;
    455 }
    456 
    457 static bool trans_CNTTZDM(DisasContext *ctx, arg_X *a)
    458 {
    459     REQUIRE_64BIT(ctx);
    460     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    461 #if defined(TARGET_PPC64)
    462     do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true);
    463 #else
    464     qemu_build_not_reached();
    465 #endif
    466     return true;
    467 }
    468 
    469 static bool trans_PDEPD(DisasContext *ctx, arg_X *a)
    470 {
    471     REQUIRE_64BIT(ctx);
    472     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    473 #if defined(TARGET_PPC64)
    474     gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
    475 #else
    476     qemu_build_not_reached();
    477 #endif
    478     return true;
    479 }
    480 
    481 static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
    482 {
    483     REQUIRE_64BIT(ctx);
    484     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    485 #if defined(TARGET_PPC64)
    486     gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
    487 #else
    488     qemu_build_not_reached();
    489 #endif
    490     return true;
    491 }
    492 
    493 static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
    494 {
    495     const uint64_t carry_bits = 0x1111111111111111ULL;
    496     TCGv t0, t1, carry, zero = tcg_constant_tl(0);
    497 
    498     REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
    499 
    500     t0 = tcg_temp_new();
    501     t1 = tcg_const_tl(0);
    502     carry = tcg_const_tl(0);
    503 
    504     for (int i = 0; i < 16; i++) {
    505         tcg_gen_shri_tl(t0, cpu_gpr[a->ra], i * 4);
    506         tcg_gen_andi_tl(t0, t0, 0xf);
    507         tcg_gen_add_tl(t1, t1, t0);
    508 
    509         tcg_gen_shri_tl(t0, cpu_gpr[a->rb], i * 4);
    510         tcg_gen_andi_tl(t0, t0, 0xf);
    511         tcg_gen_add_tl(t1, t1, t0);
    512 
    513         tcg_gen_andi_tl(t1, t1, 0x10);
    514         tcg_gen_setcond_tl(TCG_COND_NE, t1, t1, zero);
    515 
    516         tcg_gen_shli_tl(t0, t1, i * 4);
    517         tcg_gen_or_tl(carry, carry, t0);
    518     }
    519 
    520     tcg_gen_xori_tl(carry, carry, (target_long)carry_bits);
    521     tcg_gen_muli_tl(cpu_gpr[a->rt], carry, 6);
    522 
    523     tcg_temp_free(t0);
    524     tcg_temp_free(t1);
    525     tcg_temp_free(carry);
    526 
    527     return true;
    528 }
    529 
    530 static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
    531 {
    532     REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
    533     gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
    534     return true;
    535 }
    536 
    537 static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
    538 {
    539     REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
    540     gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
    541     return true;
    542 }
    543 
    544 static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
    545     void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
    546 {
    547     TCGv ea;
    548 
    549     if (!(ctx->insns_flags2 & PPC2_ISA310)) {
    550         /* if version is before v3.1, this operation is a nop */
    551         return true;
    552     }
    553 
    554     if (priv) {
    555         /* if instruction is privileged but the context is in user space */
    556         REQUIRE_SV(ctx);
    557     }
    558 
    559     if (unlikely(a->ra == 0)) {
    560         /* if RA=0, the instruction form is invalid */
    561         gen_invalid(ctx);
    562         return true;
    563     }
    564 
    565     ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
    566     helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
    567 
    568     tcg_temp_free(ea);
    569 
    570     return true;
    571 }
    572 
    573 TRANS(HASHST, do_hash, false, gen_helper_HASHST)
    574 TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
    575 TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
    576 TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)