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