xref: /openbmc/qemu/target/ppc/translate/fixedpoint-impl.c.inc (revision 82be6e02b480b2c7427b0ab91f2c297717d3cfa6)
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        if (ctx->pr) {
83e10271e1SMatheus Ferst            /* lq and stq were privileged prior to V. 2.07 */
84e10271e1SMatheus Ferst            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
85e10271e1SMatheus Ferst            return true;
86e10271e1SMatheus Ferst        }
87e10271e1SMatheus Ferst
88e10271e1SMatheus Ferst        if (ctx->le_mode) {
89e10271e1SMatheus Ferst            gen_align_no_le(ctx);
90e10271e1SMatheus Ferst            return true;
91e10271e1SMatheus Ferst        }
92e10271e1SMatheus Ferst    }
93e10271e1SMatheus Ferst
94e10271e1SMatheus Ferst    if (!store && unlikely(a->ra == a->rt)) {
95e10271e1SMatheus Ferst        gen_invalid(ctx);
96e10271e1SMatheus Ferst        return true;
97e10271e1SMatheus Ferst    }
98e10271e1SMatheus Ferst
99e10271e1SMatheus Ferst    gen_set_access_type(ctx, ACCESS_INT);
100e10271e1SMatheus Ferst    ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
101e10271e1SMatheus Ferst
102e10271e1SMatheus Ferst    if (prefixed || !ctx->le_mode) {
103e10271e1SMatheus Ferst        low_addr_gpr = cpu_gpr[a->rt];
104e10271e1SMatheus Ferst        high_addr_gpr = cpu_gpr[a->rt + 1];
105e10271e1SMatheus Ferst    } else {
106e10271e1SMatheus Ferst        low_addr_gpr = cpu_gpr[a->rt + 1];
107e10271e1SMatheus Ferst        high_addr_gpr = cpu_gpr[a->rt];
108e10271e1SMatheus Ferst    }
109e10271e1SMatheus Ferst
110e10271e1SMatheus Ferst    if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
111e10271e1SMatheus Ferst        if (HAVE_ATOMIC128) {
112e10271e1SMatheus Ferst            mop = DEF_MEMOP(MO_128);
113e10271e1SMatheus Ferst            TCGv_i32 oi = tcg_constant_i32(make_memop_idx(mop, ctx->mem_idx));
114e10271e1SMatheus Ferst            if (store) {
115e10271e1SMatheus Ferst                if (ctx->le_mode) {
116e10271e1SMatheus Ferst                    gen_helper_stq_le_parallel(cpu_env, ea, low_addr_gpr,
117e10271e1SMatheus Ferst                                               high_addr_gpr, oi);
118e10271e1SMatheus Ferst                } else {
119e10271e1SMatheus Ferst                    gen_helper_stq_be_parallel(cpu_env, ea, high_addr_gpr,
120e10271e1SMatheus Ferst                                               low_addr_gpr, oi);
121e10271e1SMatheus Ferst
122e10271e1SMatheus Ferst                }
123e10271e1SMatheus Ferst            } else {
124e10271e1SMatheus Ferst                if (ctx->le_mode) {
125e10271e1SMatheus Ferst                    gen_helper_lq_le_parallel(low_addr_gpr, cpu_env, ea, oi);
126e10271e1SMatheus Ferst                    tcg_gen_ld_i64(high_addr_gpr, cpu_env,
127e10271e1SMatheus Ferst                                   offsetof(CPUPPCState, retxh));
128e10271e1SMatheus Ferst                } else {
129e10271e1SMatheus Ferst                    gen_helper_lq_be_parallel(high_addr_gpr, cpu_env, ea, oi);
130e10271e1SMatheus Ferst                    tcg_gen_ld_i64(low_addr_gpr, cpu_env,
131e10271e1SMatheus Ferst                                   offsetof(CPUPPCState, retxh));
132e10271e1SMatheus Ferst                }
133e10271e1SMatheus Ferst            }
134e10271e1SMatheus Ferst        } else {
135e10271e1SMatheus Ferst            /* Restart with exclusive lock.  */
136e10271e1SMatheus Ferst            gen_helper_exit_atomic(cpu_env);
137e10271e1SMatheus Ferst            ctx->base.is_jmp = DISAS_NORETURN;
138e10271e1SMatheus Ferst        }
139e10271e1SMatheus Ferst    } else {
140e10271e1SMatheus Ferst        mop = DEF_MEMOP(MO_Q);
141e10271e1SMatheus Ferst        if (store) {
142e10271e1SMatheus Ferst            tcg_gen_qemu_st_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
143e10271e1SMatheus Ferst        } else {
144e10271e1SMatheus Ferst            tcg_gen_qemu_ld_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
145e10271e1SMatheus Ferst        }
146e10271e1SMatheus Ferst
147e10271e1SMatheus Ferst        gen_addr_add(ctx, ea, ea, 8);
148e10271e1SMatheus Ferst
149e10271e1SMatheus Ferst        if (store) {
150e10271e1SMatheus Ferst            tcg_gen_qemu_st_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
151e10271e1SMatheus Ferst        } else {
152e10271e1SMatheus Ferst            tcg_gen_qemu_ld_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
153e10271e1SMatheus Ferst        }
154e10271e1SMatheus Ferst    }
155e10271e1SMatheus Ferst    tcg_temp_free(ea);
156e10271e1SMatheus Ferst#else
157e10271e1SMatheus Ferst    qemu_build_not_reached();
158e10271e1SMatheus Ferst#endif
159e10271e1SMatheus Ferst
160e10271e1SMatheus Ferst    return true;
161e10271e1SMatheus Ferst}
162e10271e1SMatheus Ferst
16349de0648SMatheus Ferststatic bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
16449de0648SMatheus Ferst{
16549de0648SMatheus Ferst    arg_D d;
16649de0648SMatheus Ferst    if (!resolve_PLS_D(ctx, &d, a)) {
16749de0648SMatheus Ferst        return true;
16849de0648SMatheus Ferst    }
16949de0648SMatheus Ferst
17049de0648SMatheus Ferst    return do_ldst_quad(ctx, &d, store, true);
17149de0648SMatheus Ferst}
17249de0648SMatheus Ferst
173f2aabda8SRichard Henderson/* Load Byte and Zero */
174f2aabda8SRichard HendersonTRANS(LBZ, do_ldst_D, false, false, MO_UB)
175f2aabda8SRichard HendersonTRANS(LBZX, do_ldst_X, false, false, MO_UB)
176f2aabda8SRichard HendersonTRANS(LBZU, do_ldst_D, true, false, MO_UB)
177f2aabda8SRichard HendersonTRANS(LBZUX, do_ldst_X, true, false, MO_UB)
17800e03265SRichard HendersonTRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
179f2aabda8SRichard Henderson
180f2aabda8SRichard Henderson/* Load Halfword and Zero */
181f2aabda8SRichard HendersonTRANS(LHZ, do_ldst_D, false, false, MO_UW)
182f2aabda8SRichard HendersonTRANS(LHZX, do_ldst_X, false, false, MO_UW)
183f2aabda8SRichard HendersonTRANS(LHZU, do_ldst_D, true, false, MO_UW)
184f2aabda8SRichard HendersonTRANS(LHZUX, do_ldst_X, true, false, MO_UW)
18500e03265SRichard HendersonTRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
186f2aabda8SRichard Henderson
187f2aabda8SRichard Henderson/* Load Halfword Algebraic */
188f2aabda8SRichard HendersonTRANS(LHA, do_ldst_D, false, false, MO_SW)
189f2aabda8SRichard HendersonTRANS(LHAX, do_ldst_X, false, false, MO_SW)
190f2aabda8SRichard HendersonTRANS(LHAU, do_ldst_D, true, false, MO_SW)
191f2aabda8SRichard HendersonTRANS(LHAXU, do_ldst_X, true, false, MO_SW)
19200e03265SRichard HendersonTRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
193f2aabda8SRichard Henderson
194f2aabda8SRichard Henderson/* Load Word and Zero */
195f2aabda8SRichard HendersonTRANS(LWZ, do_ldst_D, false, false, MO_UL)
196f2aabda8SRichard HendersonTRANS(LWZX, do_ldst_X, false, false, MO_UL)
197f2aabda8SRichard HendersonTRANS(LWZU, do_ldst_D, true, false, MO_UL)
198f2aabda8SRichard HendersonTRANS(LWZUX, do_ldst_X, true, false, MO_UL)
19900e03265SRichard HendersonTRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
200f2aabda8SRichard Henderson
201f2aabda8SRichard Henderson/* Load Word Algebraic */
202f2aabda8SRichard HendersonTRANS64(LWA, do_ldst_D, false, false, MO_SL)
203f2aabda8SRichard HendersonTRANS64(LWAX, do_ldst_X, false, false, MO_SL)
204f2aabda8SRichard HendersonTRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
20500e03265SRichard HendersonTRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
206f2aabda8SRichard Henderson
207f2aabda8SRichard Henderson/* Load Doubleword */
208f2aabda8SRichard HendersonTRANS64(LD, do_ldst_D, false, false, MO_Q)
209f2aabda8SRichard HendersonTRANS64(LDX, do_ldst_X, false, false, MO_Q)
210f2aabda8SRichard HendersonTRANS64(LDU, do_ldst_D, true, false, MO_Q)
211f2aabda8SRichard HendersonTRANS64(LDUX, do_ldst_X, true, false, MO_Q)
21200e03265SRichard HendersonTRANS64(PLD, do_ldst_PLS_D, false, false, MO_Q)
213f2aabda8SRichard Henderson
214e10271e1SMatheus Ferst/* Load Quadword */
215e10271e1SMatheus FerstTRANS64(LQ, do_ldst_quad, false, false);
21649de0648SMatheus FerstTRANS64(PLQ, do_ldst_quad_PLS_D, false);
217e10271e1SMatheus Ferst
218e8f4c8d6SRichard Henderson/* Store Byte */
219e8f4c8d6SRichard HendersonTRANS(STB, do_ldst_D, false, true, MO_UB)
220e8f4c8d6SRichard HendersonTRANS(STBX, do_ldst_X, false, true, MO_UB)
221e8f4c8d6SRichard HendersonTRANS(STBU, do_ldst_D, true, true, MO_UB)
222e8f4c8d6SRichard HendersonTRANS(STBUX, do_ldst_X, true, true, MO_UB)
223b0f7bebcSRichard HendersonTRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
224e8f4c8d6SRichard Henderson
225e8f4c8d6SRichard Henderson/* Store Halfword */
226e8f4c8d6SRichard HendersonTRANS(STH, do_ldst_D, false, true, MO_UW)
227e8f4c8d6SRichard HendersonTRANS(STHX, do_ldst_X, false, true, MO_UW)
228e8f4c8d6SRichard HendersonTRANS(STHU, do_ldst_D, true, true, MO_UW)
229e8f4c8d6SRichard HendersonTRANS(STHUX, do_ldst_X, true, true, MO_UW)
230b0f7bebcSRichard HendersonTRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
231e8f4c8d6SRichard Henderson
232e8f4c8d6SRichard Henderson/* Store Word */
233e8f4c8d6SRichard HendersonTRANS(STW, do_ldst_D, false, true, MO_UL)
234e8f4c8d6SRichard HendersonTRANS(STWX, do_ldst_X, false, true, MO_UL)
235e8f4c8d6SRichard HendersonTRANS(STWU, do_ldst_D, true, true, MO_UL)
236e8f4c8d6SRichard HendersonTRANS(STWUX, do_ldst_X, true, true, MO_UL)
237b0f7bebcSRichard HendersonTRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
238e8f4c8d6SRichard Henderson
239e8f4c8d6SRichard Henderson/* Store Doubleword */
240e8f4c8d6SRichard HendersonTRANS64(STD, do_ldst_D, false, true, MO_Q)
241e8f4c8d6SRichard HendersonTRANS64(STDX, do_ldst_X, false, true, MO_Q)
242e8f4c8d6SRichard HendersonTRANS64(STDU, do_ldst_D, true, true, MO_Q)
243e8f4c8d6SRichard HendersonTRANS64(STDUX, do_ldst_X, true, true, MO_Q)
244b0f7bebcSRichard HendersonTRANS64(PSTD, do_ldst_PLS_D, false, true, MO_Q)
245e8f4c8d6SRichard Henderson
246e10271e1SMatheus Ferst/* Store Quadword */
247e10271e1SMatheus FerstTRANS64(STQ, do_ldst_quad, true, false);
24849de0648SMatheus FerstTRANS64(PSTQ, do_ldst_quad_PLS_D, true);
249e10271e1SMatheus Ferst
250f2aabda8SRichard Henderson/*
2518f0a4b6aSMatheus Ferst * Fixed-Point Compare Instructions
2528f0a4b6aSMatheus Ferst */
2538f0a4b6aSMatheus Ferst
2548f0a4b6aSMatheus Ferststatic bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s)
2558f0a4b6aSMatheus Ferst{
2562d1154bdSMatheus Ferst    if ((ctx->insns_flags & PPC_64B) == 0) {
2572d1154bdSMatheus Ferst        /*
2582d1154bdSMatheus Ferst         * For 32-bit implementations, The Programming Environments Manual says
2592d1154bdSMatheus Ferst         * that "the L field must be cleared, otherwise the instruction form is
2602d1154bdSMatheus Ferst         * invalid." It seems, however, that most 32-bit CPUs ignore invalid
2612d1154bdSMatheus Ferst         * forms (e.g., section "Instruction Formats" of the 405 and 440
2622d1154bdSMatheus Ferst         * manuals, "Integer Compare Instructions" of the 601 manual), with the
2632d1154bdSMatheus Ferst         * notable exception of the e500 and e500mc, where L=1 was reported to
2642d1154bdSMatheus Ferst         * cause an exception.
2652d1154bdSMatheus Ferst         */
2668f0a4b6aSMatheus Ferst        if (a->l) {
2672d1154bdSMatheus Ferst            if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
2682d1154bdSMatheus Ferst                /*
2692d1154bdSMatheus Ferst                 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
2702d1154bdSMatheus Ferst                 * generate an illegal instruction exception.
2712d1154bdSMatheus Ferst                 */
2722d1154bdSMatheus Ferst                return false;
2732d1154bdSMatheus Ferst            } else {
2742d1154bdSMatheus Ferst                qemu_log_mask(LOG_GUEST_ERROR,
2752d1154bdSMatheus Ferst                        "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
2762d1154bdSMatheus Ferst                        s ? "" : "L", ctx->cia);
2772d1154bdSMatheus Ferst            }
2782d1154bdSMatheus Ferst        }
2792d1154bdSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
2802d1154bdSMatheus Ferst        return true;
2812d1154bdSMatheus Ferst    }
2822d1154bdSMatheus Ferst
2832d1154bdSMatheus Ferst    /* For 64-bit implementations, deal with bit L accordingly. */
2842d1154bdSMatheus Ferst    if (a->l) {
2858f0a4b6aSMatheus Ferst        gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
2868f0a4b6aSMatheus Ferst    } else {
2878f0a4b6aSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
2888f0a4b6aSMatheus Ferst    }
2898f0a4b6aSMatheus Ferst    return true;
2908f0a4b6aSMatheus Ferst}
2918f0a4b6aSMatheus Ferst
2928f0a4b6aSMatheus Ferststatic bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s)
2938f0a4b6aSMatheus Ferst{
2942d1154bdSMatheus Ferst    if ((ctx->insns_flags & PPC_64B) == 0) {
2952d1154bdSMatheus Ferst        /*
2962d1154bdSMatheus Ferst         * For 32-bit implementations, The Programming Environments Manual says
2972d1154bdSMatheus Ferst         * that "the L field must be cleared, otherwise the instruction form is
2982d1154bdSMatheus Ferst         * invalid." It seems, however, that most 32-bit CPUs ignore invalid
2992d1154bdSMatheus Ferst         * forms (e.g., section "Instruction Formats" of the 405 and 440
3002d1154bdSMatheus Ferst         * manuals, "Integer Compare Instructions" of the 601 manual), with the
3012d1154bdSMatheus Ferst         * notable exception of the e500 and e500mc, where L=1 was reported to
3022d1154bdSMatheus Ferst         * cause an exception.
3032d1154bdSMatheus Ferst         */
3048f0a4b6aSMatheus Ferst        if (a->l) {
3052d1154bdSMatheus Ferst            if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
3062d1154bdSMatheus Ferst                /*
3072d1154bdSMatheus Ferst                 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
3082d1154bdSMatheus Ferst                 * generate an illegal instruction exception.
3092d1154bdSMatheus Ferst                 */
3102d1154bdSMatheus Ferst                return false;
3112d1154bdSMatheus Ferst            } else {
3122d1154bdSMatheus Ferst                qemu_log_mask(LOG_GUEST_ERROR,
3132d1154bdSMatheus Ferst                        "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
3142d1154bdSMatheus Ferst                        s ? "I" : "LI", ctx->cia);
3152d1154bdSMatheus Ferst            }
3162d1154bdSMatheus Ferst        }
3172d1154bdSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
3182d1154bdSMatheus Ferst        return true;
3192d1154bdSMatheus Ferst    }
3202d1154bdSMatheus Ferst
3212d1154bdSMatheus Ferst    /* For 64-bit implementations, deal with bit L accordingly. */
3222d1154bdSMatheus Ferst    if (a->l) {
3238f0a4b6aSMatheus Ferst        gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
3248f0a4b6aSMatheus Ferst    } else {
3258f0a4b6aSMatheus Ferst        gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
3268f0a4b6aSMatheus Ferst    }
3278f0a4b6aSMatheus Ferst    return true;
3288f0a4b6aSMatheus Ferst}
3298f0a4b6aSMatheus Ferst
3308f0a4b6aSMatheus FerstTRANS(CMP, do_cmp_X, true);
3318f0a4b6aSMatheus FerstTRANS(CMPL, do_cmp_X, false);
3328f0a4b6aSMatheus FerstTRANS(CMPI, do_cmp_D, true);
3338f0a4b6aSMatheus FerstTRANS(CMPLI, do_cmp_D, false);
3348f0a4b6aSMatheus Ferst
3358f0a4b6aSMatheus Ferst/*
336f2aabda8SRichard Henderson * Fixed-Point Arithmetic Instructions
337f2aabda8SRichard Henderson */
338f2aabda8SRichard Henderson
3395e560864SRichard Hendersonstatic bool trans_ADDI(DisasContext *ctx, arg_D *a)
3405e560864SRichard Henderson{
3415e560864SRichard Henderson    if (a->ra) {
3425e560864SRichard Henderson        tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
3435e560864SRichard Henderson    } else {
3445e560864SRichard Henderson        tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
3455e560864SRichard Henderson    }
3465e560864SRichard Henderson    return true;
3475e560864SRichard Henderson}
3485e560864SRichard Henderson
3495e560864SRichard Hendersonstatic bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
3505e560864SRichard Henderson{
3515e560864SRichard Henderson    arg_D d;
3525e560864SRichard Henderson    if (!resolve_PLS_D(ctx, &d, a)) {
3535e560864SRichard Henderson        return true;
3545e560864SRichard Henderson    }
3555e560864SRichard Henderson    return trans_ADDI(ctx, &d);
3565e560864SRichard Henderson}
3575e560864SRichard Henderson
3585e560864SRichard Hendersonstatic bool trans_ADDIS(DisasContext *ctx, arg_D *a)
3595e560864SRichard Henderson{
3605e560864SRichard Henderson    a->si <<= 16;
3615e560864SRichard Henderson    return trans_ADDI(ctx, a);
3625e560864SRichard Henderson}
3630a11bb7aSRichard Henderson
364e7a5d578SMatheus Ferststatic bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
365e7a5d578SMatheus Ferst{
366e7a5d578SMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
367e7a5d578SMatheus Ferst    tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
368e7a5d578SMatheus Ferst    return true;
369e7a5d578SMatheus Ferst}
370e7a5d578SMatheus Ferst
3710a11bb7aSRichard Hendersonstatic bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
3720a11bb7aSRichard Henderson{
3730a11bb7aSRichard Henderson    gen_invalid(ctx);
3740a11bb7aSRichard Henderson    return true;
3750a11bb7aSRichard Henderson}
3760a11bb7aSRichard Henderson
3770a11bb7aSRichard Hendersonstatic bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
3780a11bb7aSRichard Henderson{
3790a11bb7aSRichard Henderson    return true;
3800a11bb7aSRichard Henderson}
3819a14365eSMatheus Ferst
3829a14365eSMatheus Ferststatic bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
3839a14365eSMatheus Ferst{
3849a14365eSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
3859a14365eSMatheus Ferst    uint32_t mask = 0x08 >> (a->bi & 0x03);
3869a14365eSMatheus Ferst    TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
3879a14365eSMatheus Ferst    TCGv temp = tcg_temp_new();
3889a14365eSMatheus Ferst
3899a14365eSMatheus Ferst    tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
3909a14365eSMatheus Ferst    tcg_gen_andi_tl(temp, temp, mask);
3919a14365eSMatheus Ferst    tcg_gen_setcondi_tl(cond, cpu_gpr[a->rt], temp, 0);
3929a14365eSMatheus Ferst    if (neg) {
3939a14365eSMatheus Ferst        tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->rt]);
3949a14365eSMatheus Ferst    }
3959a14365eSMatheus Ferst    tcg_temp_free(temp);
3969a14365eSMatheus Ferst
3979a14365eSMatheus Ferst    return true;
3989a14365eSMatheus Ferst}
3999a14365eSMatheus Ferst
4009a14365eSMatheus FerstTRANS(SETBC, do_set_bool_cond, false, false)
4019a14365eSMatheus FerstTRANS(SETBCR, do_set_bool_cond, false, true)
4029a14365eSMatheus FerstTRANS(SETNBC, do_set_bool_cond, true, false)
4039a14365eSMatheus FerstTRANS(SETNBCR, do_set_bool_cond, true, true)
40489ccd7dcSMatheus Ferst
40589ccd7dcSMatheus Ferststatic bool trans_CFUGED(DisasContext *ctx, arg_X *a)
40689ccd7dcSMatheus Ferst{
40789ccd7dcSMatheus Ferst    REQUIRE_64BIT(ctx);
40889ccd7dcSMatheus Ferst    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
40989ccd7dcSMatheus Ferst#if defined(TARGET_PPC64)
41089ccd7dcSMatheus Ferst    gen_helper_cfuged(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
41189ccd7dcSMatheus Ferst#else
41289ccd7dcSMatheus Ferst    qemu_build_not_reached();
41389ccd7dcSMatheus Ferst#endif
41489ccd7dcSMatheus Ferst    return true;
41589ccd7dcSMatheus Ferst}
416*82be6e02SLuis Pires
417*82be6e02SLuis Pires#if defined(TARGET_PPC64)
418*82be6e02SLuis Piresstatic void do_cntlzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask)
419*82be6e02SLuis Pires{
420*82be6e02SLuis Pires    TCGv_i64 tmp;
421*82be6e02SLuis Pires    TCGLabel *l1;
422*82be6e02SLuis Pires
423*82be6e02SLuis Pires    tmp = tcg_temp_local_new_i64();
424*82be6e02SLuis Pires    l1 = gen_new_label();
425*82be6e02SLuis Pires
426*82be6e02SLuis Pires    tcg_gen_and_i64(tmp, src, mask);
427*82be6e02SLuis Pires    tcg_gen_clzi_i64(tmp, tmp, 64);
428*82be6e02SLuis Pires
429*82be6e02SLuis Pires    tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1);
430*82be6e02SLuis Pires
431*82be6e02SLuis Pires    tcg_gen_subfi_i64(tmp, 64, tmp);
432*82be6e02SLuis Pires    tcg_gen_shr_i64(tmp, mask, tmp);
433*82be6e02SLuis Pires    tcg_gen_ctpop_i64(tmp, tmp);
434*82be6e02SLuis Pires
435*82be6e02SLuis Pires    gen_set_label(l1);
436*82be6e02SLuis Pires
437*82be6e02SLuis Pires    tcg_gen_mov_i64(dst, tmp);
438*82be6e02SLuis Pires}
439*82be6e02SLuis Pires#endif
440*82be6e02SLuis Pires
441*82be6e02SLuis Piresstatic bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
442*82be6e02SLuis Pires{
443*82be6e02SLuis Pires    REQUIRE_64BIT(ctx);
444*82be6e02SLuis Pires    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
445*82be6e02SLuis Pires#if defined(TARGET_PPC64)
446*82be6e02SLuis Pires    do_cntlzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
447*82be6e02SLuis Pires#else
448*82be6e02SLuis Pires    qemu_build_not_reached();
449*82be6e02SLuis Pires#endif
450*82be6e02SLuis Pires    return true;
451*82be6e02SLuis Pires}
452