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
24static 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    return true;
46}
47
48static bool do_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store,
49                      MemOp mop)
50{
51    return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, mop);
52}
53
54static bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
55                          bool store, MemOp mop)
56{
57    arg_D d;
58    if (!resolve_PLS_D(ctx, &d, a)) {
59        return true;
60    }
61    return do_ldst_D(ctx, &d, update, store, mop);
62}
63
64static bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
65                      bool store, MemOp mop)
66{
67    return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop);
68}
69
70static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
71{
72#if defined(TARGET_PPC64)
73    TCGv ea;
74    TCGv_i64 lo, hi;
75    TCGv_i128 t16;
76
77    REQUIRE_INSNS_FLAGS(ctx, 64BX);
78
79    if (!prefixed && !(ctx->insns_flags2 & PPC2_LSQ_ISA207)) {
80        /* lq and stq were privileged prior to V. 2.07 */
81        REQUIRE_SV(ctx);
82
83        if (ctx->le_mode) {
84            gen_align_no_le(ctx);
85            return true;
86        }
87    }
88
89    if (!store && unlikely(a->ra == a->rt)) {
90        gen_invalid(ctx);
91        return true;
92    }
93
94    gen_set_access_type(ctx, ACCESS_INT);
95    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
96
97    if (ctx->le_mode && prefixed) {
98        lo = cpu_gpr[a->rt];
99        hi = cpu_gpr[a->rt + 1];
100    } else {
101        lo = cpu_gpr[a->rt + 1];
102        hi = cpu_gpr[a->rt];
103    }
104    t16 = tcg_temp_new_i128();
105
106    if (store) {
107        tcg_gen_concat_i64_i128(t16, lo, hi);
108        tcg_gen_qemu_st_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
109    } else {
110        tcg_gen_qemu_ld_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
111        tcg_gen_extr_i128_i64(lo, hi, t16);
112    }
113#else
114    qemu_build_not_reached();
115#endif
116
117    return true;
118}
119
120static bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
121{
122    arg_D d;
123    if (!resolve_PLS_D(ctx, &d, a)) {
124        return true;
125    }
126
127    return do_ldst_quad(ctx, &d, store, true);
128}
129
130/* Load Byte and Zero */
131TRANS(LBZ, do_ldst_D, false, false, MO_UB)
132TRANS(LBZX, do_ldst_X, false, false, MO_UB)
133TRANS(LBZU, do_ldst_D, true, false, MO_UB)
134TRANS(LBZUX, do_ldst_X, true, false, MO_UB)
135TRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
136
137/* Load Halfword and Zero */
138TRANS(LHZ, do_ldst_D, false, false, MO_UW)
139TRANS(LHZX, do_ldst_X, false, false, MO_UW)
140TRANS(LHZU, do_ldst_D, true, false, MO_UW)
141TRANS(LHZUX, do_ldst_X, true, false, MO_UW)
142TRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
143
144/* Load Halfword Algebraic */
145TRANS(LHA, do_ldst_D, false, false, MO_SW)
146TRANS(LHAX, do_ldst_X, false, false, MO_SW)
147TRANS(LHAU, do_ldst_D, true, false, MO_SW)
148TRANS(LHAXU, do_ldst_X, true, false, MO_SW)
149TRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
150
151/* Load Word and Zero */
152TRANS(LWZ, do_ldst_D, false, false, MO_UL)
153TRANS(LWZX, do_ldst_X, false, false, MO_UL)
154TRANS(LWZU, do_ldst_D, true, false, MO_UL)
155TRANS(LWZUX, do_ldst_X, true, false, MO_UL)
156TRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
157
158/* Load Word Algebraic */
159TRANS64(LWA, do_ldst_D, false, false, MO_SL)
160TRANS64(LWAX, do_ldst_X, false, false, MO_SL)
161TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
162TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
163
164/* Load Doubleword */
165TRANS64(LD, do_ldst_D, false, false, MO_UQ)
166TRANS64(LDX, do_ldst_X, false, false, MO_UQ)
167TRANS64(LDU, do_ldst_D, true, false, MO_UQ)
168TRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
169TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
170
171/* Load Quadword */
172TRANS64(LQ, do_ldst_quad, false, false);
173TRANS64(PLQ, do_ldst_quad_PLS_D, false);
174
175/* Store Byte */
176TRANS(STB, do_ldst_D, false, true, MO_UB)
177TRANS(STBX, do_ldst_X, false, true, MO_UB)
178TRANS(STBU, do_ldst_D, true, true, MO_UB)
179TRANS(STBUX, do_ldst_X, true, true, MO_UB)
180TRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
181
182/* Store Halfword */
183TRANS(STH, do_ldst_D, false, true, MO_UW)
184TRANS(STHX, do_ldst_X, false, true, MO_UW)
185TRANS(STHU, do_ldst_D, true, true, MO_UW)
186TRANS(STHUX, do_ldst_X, true, true, MO_UW)
187TRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
188
189/* Store Word */
190TRANS(STW, do_ldst_D, false, true, MO_UL)
191TRANS(STWX, do_ldst_X, false, true, MO_UL)
192TRANS(STWU, do_ldst_D, true, true, MO_UL)
193TRANS(STWUX, do_ldst_X, true, true, MO_UL)
194TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
195
196/* Store Doubleword */
197TRANS64(STD, do_ldst_D, false, true, MO_UQ)
198TRANS64(STDX, do_ldst_X, false, true, MO_UQ)
199TRANS64(STDU, do_ldst_D, true, true, MO_UQ)
200TRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
201TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
202
203/* Store Quadword */
204TRANS64(STQ, do_ldst_quad, true, false);
205TRANS64(PSTQ, do_ldst_quad_PLS_D, true);
206
207/*
208 * Fixed-Point Compare Instructions
209 */
210
211static bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s)
212{
213    if ((ctx->insns_flags & PPC_64B) == 0) {
214        /*
215         * For 32-bit implementations, The Programming Environments Manual says
216         * that "the L field must be cleared, otherwise the instruction form is
217         * invalid." It seems, however, that most 32-bit CPUs ignore invalid
218         * forms (e.g., section "Instruction Formats" of the 405 and 440
219         * manuals, "Integer Compare Instructions" of the 601 manual), with the
220         * notable exception of the e500 and e500mc, where L=1 was reported to
221         * cause an exception.
222         */
223        if (a->l) {
224            if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
225                /*
226                 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
227                 * generate an illegal instruction exception.
228                 */
229                return false;
230            } else {
231                qemu_log_mask(LOG_GUEST_ERROR,
232                        "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
233                        s ? "" : "L", ctx->cia);
234            }
235        }
236        gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
237        return true;
238    }
239
240    /* For 64-bit implementations, deal with bit L accordingly. */
241    if (a->l) {
242        gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
243    } else {
244        gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
245    }
246    return true;
247}
248
249static bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s)
250{
251    if ((ctx->insns_flags & PPC_64B) == 0) {
252        /*
253         * For 32-bit implementations, The Programming Environments Manual says
254         * that "the L field must be cleared, otherwise the instruction form is
255         * invalid." It seems, however, that most 32-bit CPUs ignore invalid
256         * forms (e.g., section "Instruction Formats" of the 405 and 440
257         * manuals, "Integer Compare Instructions" of the 601 manual), with the
258         * notable exception of the e500 and e500mc, where L=1 was reported to
259         * cause an exception.
260         */
261        if (a->l) {
262            if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
263                /*
264                 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
265                 * generate an illegal instruction exception.
266                 */
267                return false;
268            } else {
269                qemu_log_mask(LOG_GUEST_ERROR,
270                        "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
271                        s ? "I" : "LI", ctx->cia);
272            }
273        }
274        gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
275        return true;
276    }
277
278    /* For 64-bit implementations, deal with bit L accordingly. */
279    if (a->l) {
280        gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
281    } else {
282        gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
283    }
284    return true;
285}
286
287TRANS(CMP, do_cmp_X, true);
288TRANS(CMPL, do_cmp_X, false);
289TRANS(CMPI, do_cmp_D, true);
290TRANS(CMPLI, do_cmp_D, false);
291
292/*
293 * Fixed-Point Arithmetic Instructions
294 */
295
296static bool trans_ADDI(DisasContext *ctx, arg_D *a)
297{
298    if (a->ra) {
299        tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
300    } else {
301        tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
302    }
303    return true;
304}
305
306static bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
307{
308    arg_D d;
309    if (!resolve_PLS_D(ctx, &d, a)) {
310        return true;
311    }
312    return trans_ADDI(ctx, &d);
313}
314
315static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
316{
317    a->si <<= 16;
318    return trans_ADDI(ctx, a);
319}
320
321static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
322{
323    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
324    tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
325    return true;
326}
327
328static bool trans_ADDEX(DisasContext *ctx, arg_X *a)
329{
330    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
331    gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
332                     cpu_ov, cpu_ov32, true, true, false, false);
333    return true;
334}
335
336static bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca,
337                     bool compute_ov, bool compute_rc0)
338{
339    gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
340                     tcg_constant_tl(a->si), cpu_ca, cpu_ca32,
341                     add_ca, compute_ca, compute_ov, compute_rc0);
342    return true;
343}
344
345static bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
346                      bool compute_ca)
347{
348    gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
349                     cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
350    return true;
351}
352
353static bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
354                            bool add_ca, bool compute_ca)
355{
356    gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
357                     cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
358    return true;
359}
360
361TRANS(ADD, do_add_XO, false, false);
362TRANS(ADDC, do_add_XO, false, true);
363TRANS(ADDE, do_add_XO, true, true);
364TRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true);
365TRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true);
366TRANS(ADDIC, do_add_D, false, true, false, false);
367TRANS(ADDIC_, do_add_D, false, true, false, true);
368
369static bool trans_SUBFIC(DisasContext *ctx, arg_D *a)
370{
371    gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
372                      tcg_constant_tl(a->si), false, true, false, false);
373    return true;
374}
375
376static bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
377                       bool compute_ca)
378{
379    gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
380                      add_ca, compute_ca, a->oe, a->rc);
381    return true;
382}
383
384static bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
385                             bool add_ca, bool compute_ca)
386{
387    gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
388                      add_ca, compute_ca, a->oe, a->rc);
389    return true;
390}
391
392TRANS(SUBF, do_subf_XO, false, false)
393TRANS(SUBFC, do_subf_XO, false, true)
394TRANS(SUBFE, do_subf_XO, true, true)
395TRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true)
396TRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true)
397
398static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
399{
400    gen_invalid(ctx);
401    return true;
402}
403
404static bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
405{
406    return true;
407}
408
409static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
410{
411    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
412    uint32_t mask = 0x08 >> (a->bi & 0x03);
413    TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
414    TCGv temp = tcg_temp_new();
415    TCGv zero = tcg_constant_tl(0);
416
417    tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
418    tcg_gen_andi_tl(temp, temp, mask);
419    if (neg) {
420        tcg_gen_negsetcond_tl(cond, cpu_gpr[a->rt], temp, zero);
421    } else {
422        tcg_gen_setcond_tl(cond, cpu_gpr[a->rt], temp, zero);
423    }
424    return true;
425}
426
427TRANS(SETBC, do_set_bool_cond, false, false)
428TRANS(SETBCR, do_set_bool_cond, false, true)
429TRANS(SETNBC, do_set_bool_cond, true, false)
430TRANS(SETNBCR, do_set_bool_cond, true, true)
431
432static bool trans_CFUGED(DisasContext *ctx, arg_X *a)
433{
434    REQUIRE_64BIT(ctx);
435    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
436#if defined(TARGET_PPC64)
437    gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
438#else
439    qemu_build_not_reached();
440#endif
441    return true;
442}
443
444static void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail)
445{
446    TCGv_i64 t0, t1;
447
448    t0 = tcg_temp_new_i64();
449    t1 = tcg_temp_new_i64();
450
451    tcg_gen_and_i64(t0, src, mask);
452    if (trail) {
453        tcg_gen_ctzi_i64(t0, t0, -1);
454    } else {
455        tcg_gen_clzi_i64(t0, t0, -1);
456    }
457
458    tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1);
459    tcg_gen_andi_i64(t0, t0, 63);
460    tcg_gen_xori_i64(t0, t0, 63);
461    if (trail) {
462        tcg_gen_shl_i64(t0, mask, t0);
463        tcg_gen_shl_i64(t0, t0, t1);
464    } else {
465        tcg_gen_shr_i64(t0, mask, t0);
466        tcg_gen_shr_i64(t0, t0, t1);
467    }
468
469    tcg_gen_ctpop_i64(dst, t0);
470}
471
472static bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
473{
474    REQUIRE_64BIT(ctx);
475    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
476#if defined(TARGET_PPC64)
477    do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false);
478#else
479    qemu_build_not_reached();
480#endif
481    return true;
482}
483
484static bool trans_CNTTZDM(DisasContext *ctx, arg_X *a)
485{
486    REQUIRE_64BIT(ctx);
487    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
488#if defined(TARGET_PPC64)
489    do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true);
490#else
491    qemu_build_not_reached();
492#endif
493    return true;
494}
495
496static bool trans_PDEPD(DisasContext *ctx, arg_X *a)
497{
498    REQUIRE_64BIT(ctx);
499    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
500#if defined(TARGET_PPC64)
501    gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
502#else
503    qemu_build_not_reached();
504#endif
505    return true;
506}
507
508static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
509{
510    REQUIRE_64BIT(ctx);
511    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
512#if defined(TARGET_PPC64)
513    gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
514#else
515    qemu_build_not_reached();
516#endif
517    return true;
518}
519
520static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
521{
522    const target_ulong carry_bits = (target_ulong)-1 / 0xf;
523    TCGv in1, in2, carryl, carryh, tmp;
524    TCGv zero = tcg_constant_tl(0);
525
526    REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
527
528    in1 = cpu_gpr[a->ra];
529    in2 = cpu_gpr[a->rb];
530    tmp = tcg_temp_new();
531    carryl = tcg_temp_new();
532    carryh = tcg_temp_new();
533
534    /* Addition with carry. */
535    tcg_gen_add2_tl(carryl, carryh, in1, zero, in2, zero);
536    /* Addition without carry. */
537    tcg_gen_xor_tl(tmp, in1, in2);
538    /* Difference between the two is carry in to each bit. */
539    tcg_gen_xor_tl(carryl, carryl, tmp);
540
541    /*
542     * The carry-out that we're looking for is the carry-in to
543     * the next nibble.  Shift the double-word down one nibble,
544     * which puts all of the bits back into one word.
545     */
546    tcg_gen_extract2_tl(carryl, carryl, carryh, 4);
547
548    /* Invert, isolate the carry bits, and produce 6's. */
549    tcg_gen_andc_tl(carryl, tcg_constant_tl(carry_bits), carryl);
550    tcg_gen_muli_tl(cpu_gpr[a->rt], carryl, 6);
551    return true;
552}
553
554static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
555{
556    REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
557    gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
558    return true;
559}
560
561static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
562{
563    REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
564    gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
565    return true;
566}
567
568static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
569    void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
570{
571    TCGv ea;
572
573    if (!(ctx->insns_flags2 & PPC2_ISA310)) {
574        /* if version is before v3.1, this operation is a nop */
575        return true;
576    }
577
578    if (priv) {
579        /* if instruction is privileged but the context is in user space */
580        REQUIRE_SV(ctx);
581    }
582
583    if (unlikely(a->ra == 0)) {
584        /* if RA=0, the instruction form is invalid */
585        gen_invalid(ctx);
586        return true;
587    }
588
589    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
590    helper(tcg_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
591    return true;
592}
593
594TRANS(HASHST, do_hash, false, gen_helper_HASHST)
595TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
596TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
597TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)
598