xref: /openbmc/qemu/target/ppc/translate/fixedpoint-impl.c.inc (revision 670f1da374d9e9a7d509ef6f03d871144284f8d6)
199082815SRichard Henderson/*
299082815SRichard Henderson * Power ISA decode for Fixed-Point Facility instructions
399082815SRichard Henderson *
499082815SRichard Henderson * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
599082815SRichard Henderson *
699082815SRichard Henderson * This library is free software; you can redistribute it and/or
799082815SRichard Henderson * modify it under the terms of the GNU Lesser General Public
899082815SRichard Henderson * License as published by the Free Software Foundation; either
999082815SRichard Henderson * version 2.1 of the License, or (at your option) any later version.
1099082815SRichard Henderson *
1199082815SRichard Henderson * This library is distributed in the hope that it will be useful,
1299082815SRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of
1399082815SRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1499082815SRichard Henderson * Lesser General Public License for more details.
1599082815SRichard Henderson *
1699082815SRichard Henderson * You should have received a copy of the GNU Lesser General Public
1799082815SRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1899082815SRichard Henderson */
195e560864SRichard Henderson
205e560864SRichard Henderson/*
21f2aabda8SRichard Henderson * Fixed-Point Load/Store Instructions
22f2aabda8SRichard Henderson */
23f2aabda8SRichard Henderson
24f2aabda8SRichard Hendersonstatic bool do_ldst(DisasContext *ctx, int rt, int ra, TCGv displ, bool update,
25f2aabda8SRichard Henderson                    bool store, MemOp mop)
26f2aabda8SRichard Henderson{
27f2aabda8SRichard Henderson    TCGv ea;
28f2aabda8SRichard Henderson
29f2aabda8SRichard Henderson    if (update && (ra == 0 || (!store && ra == rt))) {
30f2aabda8SRichard Henderson        gen_invalid(ctx);
31f2aabda8SRichard Henderson        return true;
32f2aabda8SRichard Henderson    }
33f2aabda8SRichard Henderson    gen_set_access_type(ctx, ACCESS_INT);
34f2aabda8SRichard Henderson
35eb63efd9SFernando Eckhardt Valle    ea = do_ea_calc(ctx, ra, displ);
36f2aabda8SRichard Henderson    mop ^= ctx->default_tcg_memop_mask;
37f2aabda8SRichard Henderson    if (store) {
38f2aabda8SRichard Henderson        tcg_gen_qemu_st_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
39f2aabda8SRichard Henderson    } else {
40f2aabda8SRichard Henderson        tcg_gen_qemu_ld_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
41f2aabda8SRichard Henderson    }
42f2aabda8SRichard Henderson    if (update) {
43f2aabda8SRichard Henderson        tcg_gen_mov_tl(cpu_gpr[ra], ea);
44f2aabda8SRichard Henderson    }
45f2aabda8SRichard Henderson    tcg_temp_free(ea);
46f2aabda8SRichard Henderson
47f2aabda8SRichard Henderson    return true;
48f2aabda8SRichard Henderson}
49f2aabda8SRichard Henderson
50f2aabda8SRichard Hendersonstatic bool do_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store,
51f2aabda8SRichard Henderson                      MemOp mop)
52f2aabda8SRichard Henderson{
53f2aabda8SRichard Henderson    return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, mop);
54f2aabda8SRichard Henderson}
55f2aabda8SRichard Henderson
5600e03265SRichard Hendersonstatic bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
5700e03265SRichard Henderson                          bool store, MemOp mop)
5800e03265SRichard Henderson{
5900e03265SRichard Henderson    arg_D d;
6000e03265SRichard Henderson    if (!resolve_PLS_D(ctx, &d, a)) {
6100e03265SRichard Henderson        return true;
6200e03265SRichard Henderson    }
6300e03265SRichard Henderson    return do_ldst_D(ctx, &d, update, store, mop);
6400e03265SRichard Henderson}
6500e03265SRichard Henderson
66f2aabda8SRichard Hendersonstatic bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
67f2aabda8SRichard Henderson                      bool store, MemOp mop)
68f2aabda8SRichard Henderson{
69f2aabda8SRichard Henderson    return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop);
70f2aabda8SRichard Henderson}
71f2aabda8SRichard Henderson
72e10271e1SMatheus Ferststatic bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
73e10271e1SMatheus Ferst{
74e10271e1SMatheus Ferst#if defined(TARGET_PPC64)
75e10271e1SMatheus Ferst    TCGv ea;
76e10271e1SMatheus Ferst    TCGv_i64 low_addr_gpr, high_addr_gpr;
77e10271e1SMatheus Ferst    MemOp mop;
78e10271e1SMatheus Ferst
79e10271e1SMatheus Ferst    REQUIRE_INSNS_FLAGS(ctx, 64BX);
80e10271e1SMatheus Ferst
81e10271e1SMatheus Ferst    if (!prefixed && !(ctx->insns_flags2 & PPC2_LSQ_ISA207)) {
82e10271e1SMatheus Ferst        /* lq and stq were privileged prior to V. 2.07 */
83fc34e81aSMatheus Ferst        REQUIRE_SV(ctx);
84e10271e1SMatheus Ferst
85e10271e1SMatheus Ferst        if (ctx->le_mode) {
86e10271e1SMatheus Ferst            gen_align_no_le(ctx);
87e10271e1SMatheus Ferst            return true;
88e10271e1SMatheus Ferst        }
89e10271e1SMatheus Ferst    }
90e10271e1SMatheus Ferst
91e10271e1SMatheus Ferst    if (!store && unlikely(a->ra == a->rt)) {
92e10271e1SMatheus Ferst        gen_invalid(ctx);
93e10271e1SMatheus Ferst        return true;
94e10271e1SMatheus Ferst    }
95e10271e1SMatheus Ferst
96e10271e1SMatheus Ferst    gen_set_access_type(ctx, ACCESS_INT);
97e10271e1SMatheus Ferst    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
98e10271e1SMatheus Ferst
99e10271e1SMatheus Ferst    if (prefixed || !ctx->le_mode) {
100e10271e1SMatheus Ferst        low_addr_gpr = cpu_gpr[a->rt];
101e10271e1SMatheus Ferst        high_addr_gpr = cpu_gpr[a->rt + 1];
102e10271e1SMatheus Ferst    } else {
103e10271e1SMatheus Ferst        low_addr_gpr = cpu_gpr[a->rt + 1];
104e10271e1SMatheus Ferst        high_addr_gpr = cpu_gpr[a->rt];
105e10271e1SMatheus Ferst    }
106e10271e1SMatheus Ferst
107e10271e1SMatheus Ferst    if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
108e10271e1SMatheus Ferst        if (HAVE_ATOMIC128) {
109e10271e1SMatheus Ferst            mop = DEF_MEMOP(MO_128);
110e10271e1SMatheus Ferst            TCGv_i32 oi = tcg_constant_i32(make_memop_idx(mop, ctx->mem_idx));
111e10271e1SMatheus Ferst            if (store) {
112e10271e1SMatheus Ferst                if (ctx->le_mode) {
113e10271e1SMatheus Ferst                    gen_helper_stq_le_parallel(cpu_env, ea, low_addr_gpr,
114e10271e1SMatheus Ferst                                               high_addr_gpr, oi);
115e10271e1SMatheus Ferst                } else {
116e10271e1SMatheus Ferst                    gen_helper_stq_be_parallel(cpu_env, ea, high_addr_gpr,
117e10271e1SMatheus Ferst                                               low_addr_gpr, oi);
118e10271e1SMatheus Ferst
119e10271e1SMatheus Ferst                }
120e10271e1SMatheus Ferst            } else {
121e10271e1SMatheus Ferst                if (ctx->le_mode) {
122e10271e1SMatheus Ferst                    gen_helper_lq_le_parallel(low_addr_gpr, cpu_env, ea, oi);
123e10271e1SMatheus Ferst                    tcg_gen_ld_i64(high_addr_gpr, cpu_env,
124e10271e1SMatheus Ferst                                   offsetof(CPUPPCState, retxh));
125e10271e1SMatheus Ferst                } else {
126e10271e1SMatheus Ferst                    gen_helper_lq_be_parallel(high_addr_gpr, cpu_env, ea, oi);
127e10271e1SMatheus Ferst                    tcg_gen_ld_i64(low_addr_gpr, cpu_env,
128e10271e1SMatheus Ferst                                   offsetof(CPUPPCState, retxh));
129e10271e1SMatheus Ferst                }
130e10271e1SMatheus Ferst            }
131e10271e1SMatheus Ferst        } else {
132e10271e1SMatheus Ferst            /* Restart with exclusive lock.  */
133e10271e1SMatheus Ferst            gen_helper_exit_atomic(cpu_env);
134e10271e1SMatheus Ferst            ctx->base.is_jmp = DISAS_NORETURN;
135e10271e1SMatheus Ferst        }
136e10271e1SMatheus Ferst    } else {
137fc313c64SFrédéric Pétrot        mop = DEF_MEMOP(MO_UQ);
138e10271e1SMatheus Ferst        if (store) {
139e10271e1SMatheus Ferst            tcg_gen_qemu_st_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
140e10271e1SMatheus Ferst        } else {
141e10271e1SMatheus Ferst            tcg_gen_qemu_ld_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
142e10271e1SMatheus Ferst        }
143e10271e1SMatheus Ferst
144e10271e1SMatheus Ferst        gen_addr_add(ctx, ea, ea, 8);
145e10271e1SMatheus Ferst
146e10271e1SMatheus Ferst        if (store) {
147e10271e1SMatheus Ferst            tcg_gen_qemu_st_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
148e10271e1SMatheus Ferst        } else {
149e10271e1SMatheus Ferst            tcg_gen_qemu_ld_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
150e10271e1SMatheus Ferst        }
151e10271e1SMatheus Ferst    }
152e10271e1SMatheus Ferst    tcg_temp_free(ea);
153e10271e1SMatheus Ferst#else
154e10271e1SMatheus Ferst    qemu_build_not_reached();
155e10271e1SMatheus Ferst#endif
156e10271e1SMatheus Ferst
157e10271e1SMatheus Ferst    return true;
158e10271e1SMatheus Ferst}
159e10271e1SMatheus Ferst
16049de0648SMatheus Ferststatic bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
16149de0648SMatheus Ferst{
16249de0648SMatheus Ferst    arg_D d;
16349de0648SMatheus Ferst    if (!resolve_PLS_D(ctx, &d, a)) {
16449de0648SMatheus Ferst        return true;
16549de0648SMatheus Ferst    }
16649de0648SMatheus Ferst
16749de0648SMatheus Ferst    return do_ldst_quad(ctx, &d, store, true);
16849de0648SMatheus Ferst}
16949de0648SMatheus Ferst
170f2aabda8SRichard Henderson/* Load Byte and Zero */
171f2aabda8SRichard HendersonTRANS(LBZ, do_ldst_D, false, false, MO_UB)
172f2aabda8SRichard HendersonTRANS(LBZX, do_ldst_X, false, false, MO_UB)
173f2aabda8SRichard HendersonTRANS(LBZU, do_ldst_D, true, false, MO_UB)
174f2aabda8SRichard HendersonTRANS(LBZUX, do_ldst_X, true, false, MO_UB)
17500e03265SRichard HendersonTRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
176f2aabda8SRichard Henderson
177f2aabda8SRichard Henderson/* Load Halfword and Zero */
178f2aabda8SRichard HendersonTRANS(LHZ, do_ldst_D, false, false, MO_UW)
179f2aabda8SRichard HendersonTRANS(LHZX, do_ldst_X, false, false, MO_UW)
180f2aabda8SRichard HendersonTRANS(LHZU, do_ldst_D, true, false, MO_UW)
181f2aabda8SRichard HendersonTRANS(LHZUX, do_ldst_X, true, false, MO_UW)
18200e03265SRichard HendersonTRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
183f2aabda8SRichard Henderson
184f2aabda8SRichard Henderson/* Load Halfword Algebraic */
185f2aabda8SRichard HendersonTRANS(LHA, do_ldst_D, false, false, MO_SW)
186f2aabda8SRichard HendersonTRANS(LHAX, do_ldst_X, false, false, MO_SW)
187f2aabda8SRichard HendersonTRANS(LHAU, do_ldst_D, true, false, MO_SW)
188f2aabda8SRichard HendersonTRANS(LHAXU, do_ldst_X, true, false, MO_SW)
18900e03265SRichard HendersonTRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
190f2aabda8SRichard Henderson
191f2aabda8SRichard Henderson/* Load Word and Zero */
192f2aabda8SRichard HendersonTRANS(LWZ, do_ldst_D, false, false, MO_UL)
193f2aabda8SRichard HendersonTRANS(LWZX, do_ldst_X, false, false, MO_UL)
194f2aabda8SRichard HendersonTRANS(LWZU, do_ldst_D, true, false, MO_UL)
195f2aabda8SRichard HendersonTRANS(LWZUX, do_ldst_X, true, false, MO_UL)
19600e03265SRichard HendersonTRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
197f2aabda8SRichard Henderson
198f2aabda8SRichard Henderson/* Load Word Algebraic */
199f2aabda8SRichard HendersonTRANS64(LWA, do_ldst_D, false, false, MO_SL)
200f2aabda8SRichard HendersonTRANS64(LWAX, do_ldst_X, false, false, MO_SL)
201f2aabda8SRichard HendersonTRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
20200e03265SRichard HendersonTRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
203f2aabda8SRichard Henderson
204f2aabda8SRichard Henderson/* Load Doubleword */
205fc313c64SFrédéric PétrotTRANS64(LD, do_ldst_D, false, false, MO_UQ)
206fc313c64SFrédéric PétrotTRANS64(LDX, do_ldst_X, false, false, MO_UQ)
207fc313c64SFrédéric PétrotTRANS64(LDU, do_ldst_D, true, false, MO_UQ)
208fc313c64SFrédéric PétrotTRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
209fc313c64SFrédéric PétrotTRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
210f2aabda8SRichard Henderson
211e10271e1SMatheus Ferst/* Load Quadword */
212e10271e1SMatheus FerstTRANS64(LQ, do_ldst_quad, false, false);
21349de0648SMatheus FerstTRANS64(PLQ, do_ldst_quad_PLS_D, false);
214e10271e1SMatheus Ferst
215e8f4c8d6SRichard Henderson/* Store Byte */
216e8f4c8d6SRichard HendersonTRANS(STB, do_ldst_D, false, true, MO_UB)
217e8f4c8d6SRichard HendersonTRANS(STBX, do_ldst_X, false, true, MO_UB)
218e8f4c8d6SRichard HendersonTRANS(STBU, do_ldst_D, true, true, MO_UB)
219e8f4c8d6SRichard HendersonTRANS(STBUX, do_ldst_X, true, true, MO_UB)
220b0f7bebcSRichard HendersonTRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
221e8f4c8d6SRichard Henderson
222e8f4c8d6SRichard Henderson/* Store Halfword */
223e8f4c8d6SRichard HendersonTRANS(STH, do_ldst_D, false, true, MO_UW)
224e8f4c8d6SRichard HendersonTRANS(STHX, do_ldst_X, false, true, MO_UW)
225e8f4c8d6SRichard HendersonTRANS(STHU, do_ldst_D, true, true, MO_UW)
226e8f4c8d6SRichard HendersonTRANS(STHUX, do_ldst_X, true, true, MO_UW)
227b0f7bebcSRichard HendersonTRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
228e8f4c8d6SRichard Henderson
229e8f4c8d6SRichard Henderson/* Store Word */
230e8f4c8d6SRichard HendersonTRANS(STW, do_ldst_D, false, true, MO_UL)
231e8f4c8d6SRichard HendersonTRANS(STWX, do_ldst_X, false, true, MO_UL)
232e8f4c8d6SRichard HendersonTRANS(STWU, do_ldst_D, true, true, MO_UL)
233e8f4c8d6SRichard HendersonTRANS(STWUX, do_ldst_X, true, true, MO_UL)
234b0f7bebcSRichard HendersonTRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
235e8f4c8d6SRichard Henderson
236e8f4c8d6SRichard Henderson/* Store Doubleword */
237fc313c64SFrédéric PétrotTRANS64(STD, do_ldst_D, false, true, MO_UQ)
238fc313c64SFrédéric PétrotTRANS64(STDX, do_ldst_X, false, true, MO_UQ)
239fc313c64SFrédéric PétrotTRANS64(STDU, do_ldst_D, true, true, MO_UQ)
240fc313c64SFrédéric PétrotTRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
241fc313c64SFrédéric PétrotTRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
242e8f4c8d6SRichard Henderson
243e10271e1SMatheus Ferst/* Store Quadword */
244e10271e1SMatheus FerstTRANS64(STQ, do_ldst_quad, true, false);
24549de0648SMatheus FerstTRANS64(PSTQ, do_ldst_quad_PLS_D, true);
246e10271e1SMatheus Ferst
247f2aabda8SRichard Henderson/*
2488f0a4b6aSMatheus Ferst * Fixed-Point Compare Instructions
2498f0a4b6aSMatheus Ferst */
2508f0a4b6aSMatheus Ferst
2518f0a4b6aSMatheus Ferststatic bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s)
2528f0a4b6aSMatheus Ferst{
2532d1154bdSMatheus Ferst    if ((ctx->insns_flags & PPC_64B) == 0) {
2542d1154bdSMatheus Ferst        /*
2552d1154bdSMatheus Ferst         * For 32-bit implementations, The Programming Environments Manual says
2562d1154bdSMatheus Ferst         * that "the L field must be cleared, otherwise the instruction form is
2572d1154bdSMatheus Ferst         * invalid." It seems, however, that most 32-bit CPUs ignore invalid
2582d1154bdSMatheus Ferst         * forms (e.g., section "Instruction Formats" of the 405 and 440
2592d1154bdSMatheus Ferst         * manuals, "Integer Compare Instructions" of the 601 manual), with the
2602d1154bdSMatheus Ferst         * notable exception of the e500 and e500mc, where L=1 was reported to
2612d1154bdSMatheus Ferst         * cause an exception.
2622d1154bdSMatheus Ferst         */
2638f0a4b6aSMatheus Ferst        if (a->l) {
2642d1154bdSMatheus Ferst            if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
2652d1154bdSMatheus Ferst                /*
2662d1154bdSMatheus Ferst                 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
2672d1154bdSMatheus Ferst                 * generate an illegal instruction exception.
2682d1154bdSMatheus Ferst                 */
2692d1154bdSMatheus Ferst                return false;
2702d1154bdSMatheus Ferst            } else {
2712d1154bdSMatheus Ferst                qemu_log_mask(LOG_GUEST_ERROR,
2722d1154bdSMatheus Ferst                        "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
2732d1154bdSMatheus Ferst                        s ? "" : "L", ctx->cia);
2742d1154bdSMatheus Ferst            }
2752d1154bdSMatheus Ferst        }
2762d1154bdSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
2772d1154bdSMatheus Ferst        return true;
2782d1154bdSMatheus Ferst    }
2792d1154bdSMatheus Ferst
2802d1154bdSMatheus Ferst    /* For 64-bit implementations, deal with bit L accordingly. */
2812d1154bdSMatheus Ferst    if (a->l) {
2828f0a4b6aSMatheus Ferst        gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
2838f0a4b6aSMatheus Ferst    } else {
2848f0a4b6aSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
2858f0a4b6aSMatheus Ferst    }
2868f0a4b6aSMatheus Ferst    return true;
2878f0a4b6aSMatheus Ferst}
2888f0a4b6aSMatheus Ferst
2898f0a4b6aSMatheus Ferststatic bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s)
2908f0a4b6aSMatheus Ferst{
2912d1154bdSMatheus Ferst    if ((ctx->insns_flags & PPC_64B) == 0) {
2922d1154bdSMatheus Ferst        /*
2932d1154bdSMatheus Ferst         * For 32-bit implementations, The Programming Environments Manual says
2942d1154bdSMatheus Ferst         * that "the L field must be cleared, otherwise the instruction form is
2952d1154bdSMatheus Ferst         * invalid." It seems, however, that most 32-bit CPUs ignore invalid
2962d1154bdSMatheus Ferst         * forms (e.g., section "Instruction Formats" of the 405 and 440
2972d1154bdSMatheus Ferst         * manuals, "Integer Compare Instructions" of the 601 manual), with the
2982d1154bdSMatheus Ferst         * notable exception of the e500 and e500mc, where L=1 was reported to
2992d1154bdSMatheus Ferst         * cause an exception.
3002d1154bdSMatheus Ferst         */
3018f0a4b6aSMatheus Ferst        if (a->l) {
3022d1154bdSMatheus Ferst            if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
3032d1154bdSMatheus Ferst                /*
3042d1154bdSMatheus Ferst                 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
3052d1154bdSMatheus Ferst                 * generate an illegal instruction exception.
3062d1154bdSMatheus Ferst                 */
3072d1154bdSMatheus Ferst                return false;
3082d1154bdSMatheus Ferst            } else {
3092d1154bdSMatheus Ferst                qemu_log_mask(LOG_GUEST_ERROR,
3102d1154bdSMatheus Ferst                        "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
3112d1154bdSMatheus Ferst                        s ? "I" : "LI", ctx->cia);
3122d1154bdSMatheus Ferst            }
3132d1154bdSMatheus Ferst        }
3142d1154bdSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
3152d1154bdSMatheus Ferst        return true;
3162d1154bdSMatheus Ferst    }
3172d1154bdSMatheus Ferst
3182d1154bdSMatheus Ferst    /* For 64-bit implementations, deal with bit L accordingly. */
3192d1154bdSMatheus Ferst    if (a->l) {
3208f0a4b6aSMatheus Ferst        gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
3218f0a4b6aSMatheus Ferst    } else {
3228f0a4b6aSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
3238f0a4b6aSMatheus Ferst    }
3248f0a4b6aSMatheus Ferst    return true;
3258f0a4b6aSMatheus Ferst}
3268f0a4b6aSMatheus Ferst
3278f0a4b6aSMatheus FerstTRANS(CMP, do_cmp_X, true);
3288f0a4b6aSMatheus FerstTRANS(CMPL, do_cmp_X, false);
3298f0a4b6aSMatheus FerstTRANS(CMPI, do_cmp_D, true);
3308f0a4b6aSMatheus FerstTRANS(CMPLI, do_cmp_D, false);
3318f0a4b6aSMatheus Ferst
3328f0a4b6aSMatheus Ferst/*
333f2aabda8SRichard Henderson * Fixed-Point Arithmetic Instructions
334f2aabda8SRichard Henderson */
335f2aabda8SRichard Henderson
3365e560864SRichard Hendersonstatic bool trans_ADDI(DisasContext *ctx, arg_D *a)
3375e560864SRichard Henderson{
3385e560864SRichard Henderson    if (a->ra) {
3395e560864SRichard Henderson        tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
3405e560864SRichard Henderson    } else {
3415e560864SRichard Henderson        tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
3425e560864SRichard Henderson    }
3435e560864SRichard Henderson    return true;
3445e560864SRichard Henderson}
3455e560864SRichard Henderson
3465e560864SRichard Hendersonstatic bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
3475e560864SRichard Henderson{
3485e560864SRichard Henderson    arg_D d;
3495e560864SRichard Henderson    if (!resolve_PLS_D(ctx, &d, a)) {
3505e560864SRichard Henderson        return true;
3515e560864SRichard Henderson    }
3525e560864SRichard Henderson    return trans_ADDI(ctx, &d);
3535e560864SRichard Henderson}
3545e560864SRichard Henderson
3555e560864SRichard Hendersonstatic bool trans_ADDIS(DisasContext *ctx, arg_D *a)
3565e560864SRichard Henderson{
3575e560864SRichard Henderson    a->si <<= 16;
3585e560864SRichard Henderson    return trans_ADDI(ctx, a);
3595e560864SRichard Henderson}
3600a11bb7aSRichard Henderson
361e7a5d578SMatheus Ferststatic bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
362e7a5d578SMatheus Ferst{
363e7a5d578SMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
364e7a5d578SMatheus Ferst    tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
365e7a5d578SMatheus Ferst    return true;
366e7a5d578SMatheus Ferst}
367e7a5d578SMatheus Ferst
3680a11bb7aSRichard Hendersonstatic bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
3690a11bb7aSRichard Henderson{
3700a11bb7aSRichard Henderson    gen_invalid(ctx);
3710a11bb7aSRichard Henderson    return true;
3720a11bb7aSRichard Henderson}
3730a11bb7aSRichard Henderson
3740a11bb7aSRichard Hendersonstatic bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
3750a11bb7aSRichard Henderson{
3760a11bb7aSRichard Henderson    return true;
3770a11bb7aSRichard Henderson}
3789a14365eSMatheus Ferst
3799a14365eSMatheus Ferststatic bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
3809a14365eSMatheus Ferst{
3819a14365eSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
3829a14365eSMatheus Ferst    uint32_t mask = 0x08 >> (a->bi & 0x03);
3839a14365eSMatheus Ferst    TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
3849a14365eSMatheus Ferst    TCGv temp = tcg_temp_new();
3859a14365eSMatheus Ferst
3869a14365eSMatheus Ferst    tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
3879a14365eSMatheus Ferst    tcg_gen_andi_tl(temp, temp, mask);
3889a14365eSMatheus Ferst    tcg_gen_setcondi_tl(cond, cpu_gpr[a->rt], temp, 0);
3899a14365eSMatheus Ferst    if (neg) {
3909a14365eSMatheus Ferst        tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->rt]);
3919a14365eSMatheus Ferst    }
3929a14365eSMatheus Ferst    tcg_temp_free(temp);
3939a14365eSMatheus Ferst
3949a14365eSMatheus Ferst    return true;
3959a14365eSMatheus Ferst}
3969a14365eSMatheus Ferst
3979a14365eSMatheus FerstTRANS(SETBC, do_set_bool_cond, false, false)
3989a14365eSMatheus FerstTRANS(SETBCR, do_set_bool_cond, false, true)
3999a14365eSMatheus FerstTRANS(SETNBC, do_set_bool_cond, true, false)
4009a14365eSMatheus FerstTRANS(SETNBCR, do_set_bool_cond, true, true)
40189ccd7dcSMatheus Ferst
40289ccd7dcSMatheus Ferststatic bool trans_CFUGED(DisasContext *ctx, arg_X *a)
40389ccd7dcSMatheus Ferst{
40489ccd7dcSMatheus Ferst    REQUIRE_64BIT(ctx);
40589ccd7dcSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
40689ccd7dcSMatheus Ferst#if defined(TARGET_PPC64)
4076e0bbc40SMatheus Ferst    gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
40889ccd7dcSMatheus Ferst#else
40989ccd7dcSMatheus Ferst    qemu_build_not_reached();
41089ccd7dcSMatheus Ferst#endif
41189ccd7dcSMatheus Ferst    return true;
41289ccd7dcSMatheus Ferst}
41382be6e02SLuis Pires
414a2c975e1SMatheus Ferststatic void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail)
41582be6e02SLuis Pires{
416ab1e25adSMatheus Ferst    TCGv_i64 t0, t1;
41782be6e02SLuis Pires
418ab1e25adSMatheus Ferst    t0 = tcg_temp_new_i64();
419ab1e25adSMatheus Ferst    t1 = tcg_temp_new_i64();
42082be6e02SLuis Pires
421ab1e25adSMatheus Ferst    tcg_gen_and_i64(t0, src, mask);
422f356b3baSLuis Pires    if (trail) {
423ab1e25adSMatheus Ferst        tcg_gen_ctzi_i64(t0, t0, -1);
424f356b3baSLuis Pires    } else {
425ab1e25adSMatheus Ferst        tcg_gen_clzi_i64(t0, t0, -1);
426f356b3baSLuis Pires    }
42782be6e02SLuis Pires
428ab1e25adSMatheus Ferst    tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1);
429ab1e25adSMatheus Ferst    tcg_gen_andi_i64(t0, t0, 63);
430ab1e25adSMatheus Ferst    tcg_gen_xori_i64(t0, t0, 63);
431f356b3baSLuis Pires    if (trail) {
432ab1e25adSMatheus Ferst        tcg_gen_shl_i64(t0, mask, t0);
433ab1e25adSMatheus Ferst        tcg_gen_shl_i64(t0, t0, t1);
434f356b3baSLuis Pires    } else {
435ab1e25adSMatheus Ferst        tcg_gen_shr_i64(t0, mask, t0);
436ab1e25adSMatheus Ferst        tcg_gen_shr_i64(t0, t0, t1);
437f356b3baSLuis Pires    }
43882be6e02SLuis Pires
439ab1e25adSMatheus Ferst    tcg_gen_ctpop_i64(dst, t0);
44082be6e02SLuis Pires
441ab1e25adSMatheus Ferst    tcg_temp_free_i64(t0);
442ab1e25adSMatheus Ferst    tcg_temp_free_i64(t1);
44382be6e02SLuis Pires}
44482be6e02SLuis Pires
44582be6e02SLuis Piresstatic bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
44682be6e02SLuis Pires{
44782be6e02SLuis Pires    REQUIRE_64BIT(ctx);
44882be6e02SLuis Pires    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
44982be6e02SLuis Pires#if defined(TARGET_PPC64)
450f356b3baSLuis Pires    do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false);
451f356b3baSLuis Pires#else
452f356b3baSLuis Pires    qemu_build_not_reached();
453f356b3baSLuis Pires#endif
454f356b3baSLuis Pires    return true;
455f356b3baSLuis Pires}
456f356b3baSLuis Pires
457f356b3baSLuis Piresstatic bool trans_CNTTZDM(DisasContext *ctx, arg_X *a)
458f356b3baSLuis Pires{
459f356b3baSLuis Pires    REQUIRE_64BIT(ctx);
460f356b3baSLuis Pires    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
461f356b3baSLuis Pires#if defined(TARGET_PPC64)
462f356b3baSLuis Pires    do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true);
46382be6e02SLuis Pires#else
46482be6e02SLuis Pires    qemu_build_not_reached();
46582be6e02SLuis Pires#endif
46682be6e02SLuis Pires    return true;
46782be6e02SLuis Pires}
46821ba6e58SMatheus Ferst
46921ba6e58SMatheus Ferststatic bool trans_PDEPD(DisasContext *ctx, arg_X *a)
47021ba6e58SMatheus Ferst{
47121ba6e58SMatheus Ferst    REQUIRE_64BIT(ctx);
47221ba6e58SMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
47321ba6e58SMatheus Ferst#if defined(TARGET_PPC64)
47421ba6e58SMatheus Ferst    gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
47521ba6e58SMatheus Ferst#else
47621ba6e58SMatheus Ferst    qemu_build_not_reached();
47721ba6e58SMatheus Ferst#endif
47821ba6e58SMatheus Ferst    return true;
47921ba6e58SMatheus Ferst}
4808bdb7606SMatheus Ferst
4818bdb7606SMatheus Ferststatic bool trans_PEXTD(DisasContext *ctx, arg_X *a)
4828bdb7606SMatheus Ferst{
4838bdb7606SMatheus Ferst    REQUIRE_64BIT(ctx);
4848bdb7606SMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
4858bdb7606SMatheus Ferst#if defined(TARGET_PPC64)
4868bdb7606SMatheus Ferst    gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
4878bdb7606SMatheus Ferst#else
4888bdb7606SMatheus Ferst    qemu_build_not_reached();
4898bdb7606SMatheus Ferst#endif
4908bdb7606SMatheus Ferst    return true;
4918bdb7606SMatheus Ferst}
4926addef4dSMatheus Ferst
4936addef4dSMatheus Ferststatic bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
4946addef4dSMatheus Ferst{
4956addef4dSMatheus Ferst    const uint64_t carry_bits = 0x1111111111111111ULL;
4966addef4dSMatheus Ferst    TCGv t0, t1, carry, zero = tcg_constant_tl(0);
4976addef4dSMatheus Ferst
4986addef4dSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
4996addef4dSMatheus Ferst
5006addef4dSMatheus Ferst    t0 = tcg_temp_new();
5016addef4dSMatheus Ferst    t1 = tcg_const_tl(0);
5026addef4dSMatheus Ferst    carry = tcg_const_tl(0);
5036addef4dSMatheus Ferst
5046addef4dSMatheus Ferst    for (int i = 0; i < 16; i++) {
5056addef4dSMatheus Ferst        tcg_gen_shri_tl(t0, cpu_gpr[a->ra], i * 4);
5066addef4dSMatheus Ferst        tcg_gen_andi_tl(t0, t0, 0xf);
5076addef4dSMatheus Ferst        tcg_gen_add_tl(t1, t1, t0);
5086addef4dSMatheus Ferst
5096addef4dSMatheus Ferst        tcg_gen_shri_tl(t0, cpu_gpr[a->rb], i * 4);
5106addef4dSMatheus Ferst        tcg_gen_andi_tl(t0, t0, 0xf);
5116addef4dSMatheus Ferst        tcg_gen_add_tl(t1, t1, t0);
5126addef4dSMatheus Ferst
5136addef4dSMatheus Ferst        tcg_gen_andi_tl(t1, t1, 0x10);
5146addef4dSMatheus Ferst        tcg_gen_setcond_tl(TCG_COND_NE, t1, t1, zero);
5156addef4dSMatheus Ferst
5166addef4dSMatheus Ferst        tcg_gen_shli_tl(t0, t1, i * 4);
5176addef4dSMatheus Ferst        tcg_gen_or_tl(carry, carry, t0);
5186addef4dSMatheus Ferst    }
5196addef4dSMatheus Ferst
5206addef4dSMatheus Ferst    tcg_gen_xori_tl(carry, carry, (target_long)carry_bits);
5216addef4dSMatheus Ferst    tcg_gen_muli_tl(cpu_gpr[a->rt], carry, 6);
5226addef4dSMatheus Ferst
5236addef4dSMatheus Ferst    tcg_temp_free(t0);
5246addef4dSMatheus Ferst    tcg_temp_free(t1);
5256addef4dSMatheus Ferst    tcg_temp_free(carry);
5266addef4dSMatheus Ferst
5276addef4dSMatheus Ferst    return true;
5286addef4dSMatheus Ferst}
52938d3690bSMatheus Ferst
5306b924d4aSMatheus Ferststatic bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
5316b924d4aSMatheus Ferst{
5326b924d4aSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
5336b924d4aSMatheus Ferst    gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
5346b924d4aSMatheus Ferst    return true;
5356b924d4aSMatheus Ferst}
5366b924d4aSMatheus Ferst
53738d3690bSMatheus Ferststatic bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
53838d3690bSMatheus Ferst{
53938d3690bSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
54038d3690bSMatheus Ferst    gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
54138d3690bSMatheus Ferst    return true;
54238d3690bSMatheus Ferst}
543*670f1da3SVíctor Colombo
544*670f1da3SVíctor Colombostatic bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
545*670f1da3SVíctor Colombo    void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
546*670f1da3SVíctor Colombo{
547*670f1da3SVíctor Colombo    TCGv ea;
548*670f1da3SVíctor Colombo
549*670f1da3SVíctor Colombo    if (!(ctx->insns_flags2 & PPC2_ISA310)) {
550*670f1da3SVíctor Colombo        /* if version is before v3.1, this operation is a nop */
551*670f1da3SVíctor Colombo        return true;
552*670f1da3SVíctor Colombo    }
553*670f1da3SVíctor Colombo
554*670f1da3SVíctor Colombo    if (priv) {
555*670f1da3SVíctor Colombo        /* if instruction is privileged but the context is in user space */
556*670f1da3SVíctor Colombo        REQUIRE_SV(ctx);
557*670f1da3SVíctor Colombo    }
558*670f1da3SVíctor Colombo
559*670f1da3SVíctor Colombo    if (unlikely(a->ra == 0)) {
560*670f1da3SVíctor Colombo        /* if RA=0, the instruction form is invalid */
561*670f1da3SVíctor Colombo        gen_invalid(ctx);
562*670f1da3SVíctor Colombo        return true;
563*670f1da3SVíctor Colombo    }
564*670f1da3SVíctor Colombo
565*670f1da3SVíctor Colombo    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
566*670f1da3SVíctor Colombo    helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
567*670f1da3SVíctor Colombo
568*670f1da3SVíctor Colombo    tcg_temp_free(ea);
569*670f1da3SVíctor Colombo
570*670f1da3SVíctor Colombo    return true;
571*670f1da3SVíctor Colombo}
572*670f1da3SVíctor Colombo
573*670f1da3SVíctor ColomboTRANS(HASHST, do_hash, false, gen_helper_HASHST)
574*670f1da3SVíctor ColomboTRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
575