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 return true; 46f2aabda8SRichard Henderson} 47f2aabda8SRichard Henderson 48f2aabda8SRichard Hendersonstatic bool do_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store, 49f2aabda8SRichard Henderson MemOp mop) 50f2aabda8SRichard Henderson{ 51f2aabda8SRichard Henderson return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, mop); 52f2aabda8SRichard Henderson} 53f2aabda8SRichard Henderson 5400e03265SRichard Hendersonstatic bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update, 5500e03265SRichard Henderson bool store, MemOp mop) 5600e03265SRichard Henderson{ 5700e03265SRichard Henderson arg_D d; 5800e03265SRichard Henderson if (!resolve_PLS_D(ctx, &d, a)) { 5900e03265SRichard Henderson return true; 6000e03265SRichard Henderson } 6100e03265SRichard Henderson return do_ldst_D(ctx, &d, update, store, mop); 6200e03265SRichard Henderson} 6300e03265SRichard Henderson 64f2aabda8SRichard Hendersonstatic bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update, 65f2aabda8SRichard Henderson bool store, MemOp mop) 66f2aabda8SRichard Henderson{ 67f2aabda8SRichard Henderson return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop); 68f2aabda8SRichard Henderson} 69f2aabda8SRichard Henderson 70e10271e1SMatheus Ferststatic bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed) 71e10271e1SMatheus Ferst{ 72e10271e1SMatheus Ferst#if defined(TARGET_PPC64) 73e10271e1SMatheus Ferst TCGv ea; 7471820935SNicholas Piggin TCGv_i64 lo, hi; 7557b38ffdSRichard Henderson TCGv_i128 t16; 76e10271e1SMatheus Ferst 77e10271e1SMatheus Ferst REQUIRE_INSNS_FLAGS(ctx, 64BX); 78e10271e1SMatheus Ferst 79e10271e1SMatheus Ferst if (!prefixed && !(ctx->insns_flags2 & PPC2_LSQ_ISA207)) { 80e10271e1SMatheus Ferst /* lq and stq were privileged prior to V. 2.07 */ 81fc34e81aSMatheus Ferst REQUIRE_SV(ctx); 82e10271e1SMatheus Ferst 83e10271e1SMatheus Ferst if (ctx->le_mode) { 84e10271e1SMatheus Ferst gen_align_no_le(ctx); 85e10271e1SMatheus Ferst return true; 86e10271e1SMatheus Ferst } 87e10271e1SMatheus Ferst } 88e10271e1SMatheus Ferst 89e10271e1SMatheus Ferst if (!store && unlikely(a->ra == a->rt)) { 90e10271e1SMatheus Ferst gen_invalid(ctx); 91e10271e1SMatheus Ferst return true; 92e10271e1SMatheus Ferst } 93e10271e1SMatheus Ferst 94e10271e1SMatheus Ferst gen_set_access_type(ctx, ACCESS_INT); 95e10271e1SMatheus Ferst ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si)); 96e10271e1SMatheus Ferst 9771820935SNicholas Piggin if (ctx->le_mode && prefixed) { 9871820935SNicholas Piggin lo = cpu_gpr[a->rt]; 9971820935SNicholas Piggin hi = cpu_gpr[a->rt + 1]; 100e10271e1SMatheus Ferst } else { 10171820935SNicholas Piggin lo = cpu_gpr[a->rt + 1]; 10271820935SNicholas Piggin hi = cpu_gpr[a->rt]; 103e10271e1SMatheus Ferst } 10457b38ffdSRichard Henderson t16 = tcg_temp_new_i128(); 105e10271e1SMatheus Ferst 106e10271e1SMatheus Ferst if (store) { 10771820935SNicholas Piggin tcg_gen_concat_i64_i128(t16, lo, hi); 10857b38ffdSRichard Henderson tcg_gen_qemu_st_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128)); 109e10271e1SMatheus Ferst } else { 11057b38ffdSRichard Henderson tcg_gen_qemu_ld_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128)); 11171820935SNicholas Piggin tcg_gen_extr_i128_i64(lo, hi, t16); 112e10271e1SMatheus Ferst } 113e10271e1SMatheus Ferst#else 114e10271e1SMatheus Ferst qemu_build_not_reached(); 115e10271e1SMatheus Ferst#endif 116e10271e1SMatheus Ferst 117e10271e1SMatheus Ferst return true; 118e10271e1SMatheus Ferst} 119e10271e1SMatheus Ferst 12049de0648SMatheus Ferststatic bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store) 12149de0648SMatheus Ferst{ 12249de0648SMatheus Ferst arg_D d; 12349de0648SMatheus Ferst if (!resolve_PLS_D(ctx, &d, a)) { 12449de0648SMatheus Ferst return true; 12549de0648SMatheus Ferst } 12649de0648SMatheus Ferst 12749de0648SMatheus Ferst return do_ldst_quad(ctx, &d, store, true); 12849de0648SMatheus Ferst} 12949de0648SMatheus Ferst 130f2aabda8SRichard Henderson/* Load Byte and Zero */ 131f2aabda8SRichard HendersonTRANS(LBZ, do_ldst_D, false, false, MO_UB) 132f2aabda8SRichard HendersonTRANS(LBZX, do_ldst_X, false, false, MO_UB) 133f2aabda8SRichard HendersonTRANS(LBZU, do_ldst_D, true, false, MO_UB) 134f2aabda8SRichard HendersonTRANS(LBZUX, do_ldst_X, true, false, MO_UB) 13500e03265SRichard HendersonTRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB) 136f2aabda8SRichard Henderson 137f2aabda8SRichard Henderson/* Load Halfword and Zero */ 138f2aabda8SRichard HendersonTRANS(LHZ, do_ldst_D, false, false, MO_UW) 139f2aabda8SRichard HendersonTRANS(LHZX, do_ldst_X, false, false, MO_UW) 140f2aabda8SRichard HendersonTRANS(LHZU, do_ldst_D, true, false, MO_UW) 141f2aabda8SRichard HendersonTRANS(LHZUX, do_ldst_X, true, false, MO_UW) 14200e03265SRichard HendersonTRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW) 143f2aabda8SRichard Henderson 144f2aabda8SRichard Henderson/* Load Halfword Algebraic */ 145f2aabda8SRichard HendersonTRANS(LHA, do_ldst_D, false, false, MO_SW) 146f2aabda8SRichard HendersonTRANS(LHAX, do_ldst_X, false, false, MO_SW) 147f2aabda8SRichard HendersonTRANS(LHAU, do_ldst_D, true, false, MO_SW) 148f2aabda8SRichard HendersonTRANS(LHAXU, do_ldst_X, true, false, MO_SW) 14900e03265SRichard HendersonTRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW) 150f2aabda8SRichard Henderson 151f2aabda8SRichard Henderson/* Load Word and Zero */ 152f2aabda8SRichard HendersonTRANS(LWZ, do_ldst_D, false, false, MO_UL) 153f2aabda8SRichard HendersonTRANS(LWZX, do_ldst_X, false, false, MO_UL) 154f2aabda8SRichard HendersonTRANS(LWZU, do_ldst_D, true, false, MO_UL) 155f2aabda8SRichard HendersonTRANS(LWZUX, do_ldst_X, true, false, MO_UL) 15600e03265SRichard HendersonTRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL) 157f2aabda8SRichard Henderson 158f2aabda8SRichard Henderson/* Load Word Algebraic */ 159f2aabda8SRichard HendersonTRANS64(LWA, do_ldst_D, false, false, MO_SL) 160f2aabda8SRichard HendersonTRANS64(LWAX, do_ldst_X, false, false, MO_SL) 161f2aabda8SRichard HendersonTRANS64(LWAUX, do_ldst_X, true, false, MO_SL) 16200e03265SRichard HendersonTRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL) 163f2aabda8SRichard Henderson 164f2aabda8SRichard Henderson/* Load Doubleword */ 165fc313c64SFrédéric PétrotTRANS64(LD, do_ldst_D, false, false, MO_UQ) 166fc313c64SFrédéric PétrotTRANS64(LDX, do_ldst_X, false, false, MO_UQ) 167fc313c64SFrédéric PétrotTRANS64(LDU, do_ldst_D, true, false, MO_UQ) 168fc313c64SFrédéric PétrotTRANS64(LDUX, do_ldst_X, true, false, MO_UQ) 169fc313c64SFrédéric PétrotTRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ) 170f2aabda8SRichard Henderson 171e10271e1SMatheus Ferst/* Load Quadword */ 172e10271e1SMatheus FerstTRANS64(LQ, do_ldst_quad, false, false); 17349de0648SMatheus FerstTRANS64(PLQ, do_ldst_quad_PLS_D, false); 174e10271e1SMatheus Ferst 175e8f4c8d6SRichard Henderson/* Store Byte */ 176e8f4c8d6SRichard HendersonTRANS(STB, do_ldst_D, false, true, MO_UB) 177e8f4c8d6SRichard HendersonTRANS(STBX, do_ldst_X, false, true, MO_UB) 178e8f4c8d6SRichard HendersonTRANS(STBU, do_ldst_D, true, true, MO_UB) 179e8f4c8d6SRichard HendersonTRANS(STBUX, do_ldst_X, true, true, MO_UB) 180b0f7bebcSRichard HendersonTRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB) 181e8f4c8d6SRichard Henderson 182e8f4c8d6SRichard Henderson/* Store Halfword */ 183e8f4c8d6SRichard HendersonTRANS(STH, do_ldst_D, false, true, MO_UW) 184e8f4c8d6SRichard HendersonTRANS(STHX, do_ldst_X, false, true, MO_UW) 185e8f4c8d6SRichard HendersonTRANS(STHU, do_ldst_D, true, true, MO_UW) 186e8f4c8d6SRichard HendersonTRANS(STHUX, do_ldst_X, true, true, MO_UW) 187b0f7bebcSRichard HendersonTRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW) 188e8f4c8d6SRichard Henderson 189e8f4c8d6SRichard Henderson/* Store Word */ 190e8f4c8d6SRichard HendersonTRANS(STW, do_ldst_D, false, true, MO_UL) 191e8f4c8d6SRichard HendersonTRANS(STWX, do_ldst_X, false, true, MO_UL) 192e8f4c8d6SRichard HendersonTRANS(STWU, do_ldst_D, true, true, MO_UL) 193e8f4c8d6SRichard HendersonTRANS(STWUX, do_ldst_X, true, true, MO_UL) 194b0f7bebcSRichard HendersonTRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL) 195e8f4c8d6SRichard Henderson 196e8f4c8d6SRichard Henderson/* Store Doubleword */ 197fc313c64SFrédéric PétrotTRANS64(STD, do_ldst_D, false, true, MO_UQ) 198fc313c64SFrédéric PétrotTRANS64(STDX, do_ldst_X, false, true, MO_UQ) 199fc313c64SFrédéric PétrotTRANS64(STDU, do_ldst_D, true, true, MO_UQ) 200fc313c64SFrédéric PétrotTRANS64(STDUX, do_ldst_X, true, true, MO_UQ) 201fc313c64SFrédéric PétrotTRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ) 202e8f4c8d6SRichard Henderson 203e10271e1SMatheus Ferst/* Store Quadword */ 204e10271e1SMatheus FerstTRANS64(STQ, do_ldst_quad, true, false); 20549de0648SMatheus FerstTRANS64(PSTQ, do_ldst_quad_PLS_D, true); 206e10271e1SMatheus Ferst 207f2aabda8SRichard Henderson/* 2088f0a4b6aSMatheus Ferst * Fixed-Point Compare Instructions 2098f0a4b6aSMatheus Ferst */ 2108f0a4b6aSMatheus Ferst 2118f0a4b6aSMatheus Ferststatic bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s) 2128f0a4b6aSMatheus Ferst{ 2132d1154bdSMatheus Ferst if ((ctx->insns_flags & PPC_64B) == 0) { 2142d1154bdSMatheus Ferst /* 2152d1154bdSMatheus Ferst * For 32-bit implementations, The Programming Environments Manual says 2162d1154bdSMatheus Ferst * that "the L field must be cleared, otherwise the instruction form is 2172d1154bdSMatheus Ferst * invalid." It seems, however, that most 32-bit CPUs ignore invalid 2182d1154bdSMatheus Ferst * forms (e.g., section "Instruction Formats" of the 405 and 440 2192d1154bdSMatheus Ferst * manuals, "Integer Compare Instructions" of the 601 manual), with the 2202d1154bdSMatheus Ferst * notable exception of the e500 and e500mc, where L=1 was reported to 2212d1154bdSMatheus Ferst * cause an exception. 2222d1154bdSMatheus Ferst */ 2238f0a4b6aSMatheus Ferst if (a->l) { 2242d1154bdSMatheus Ferst if ((ctx->insns_flags2 & PPC2_BOOKE206)) { 2252d1154bdSMatheus Ferst /* 2262d1154bdSMatheus Ferst * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc), 2272d1154bdSMatheus Ferst * generate an illegal instruction exception. 2282d1154bdSMatheus Ferst */ 2292d1154bdSMatheus Ferst return false; 2302d1154bdSMatheus Ferst } else { 2312d1154bdSMatheus Ferst qemu_log_mask(LOG_GUEST_ERROR, 2322d1154bdSMatheus Ferst "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n", 2332d1154bdSMatheus Ferst s ? "" : "L", ctx->cia); 2342d1154bdSMatheus Ferst } 2352d1154bdSMatheus Ferst } 2362d1154bdSMatheus Ferst gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf); 2372d1154bdSMatheus Ferst return true; 2382d1154bdSMatheus Ferst } 2392d1154bdSMatheus Ferst 2402d1154bdSMatheus Ferst /* For 64-bit implementations, deal with bit L accordingly. */ 2412d1154bdSMatheus Ferst if (a->l) { 2428f0a4b6aSMatheus Ferst gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf); 2438f0a4b6aSMatheus Ferst } else { 2448f0a4b6aSMatheus Ferst gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf); 2458f0a4b6aSMatheus Ferst } 2468f0a4b6aSMatheus Ferst return true; 2478f0a4b6aSMatheus Ferst} 2488f0a4b6aSMatheus Ferst 2498f0a4b6aSMatheus Ferststatic bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s) 2508f0a4b6aSMatheus Ferst{ 2512d1154bdSMatheus Ferst if ((ctx->insns_flags & PPC_64B) == 0) { 2522d1154bdSMatheus Ferst /* 2532d1154bdSMatheus Ferst * For 32-bit implementations, The Programming Environments Manual says 2542d1154bdSMatheus Ferst * that "the L field must be cleared, otherwise the instruction form is 2552d1154bdSMatheus Ferst * invalid." It seems, however, that most 32-bit CPUs ignore invalid 2562d1154bdSMatheus Ferst * forms (e.g., section "Instruction Formats" of the 405 and 440 2572d1154bdSMatheus Ferst * manuals, "Integer Compare Instructions" of the 601 manual), with the 2582d1154bdSMatheus Ferst * notable exception of the e500 and e500mc, where L=1 was reported to 2592d1154bdSMatheus Ferst * cause an exception. 2602d1154bdSMatheus Ferst */ 2618f0a4b6aSMatheus Ferst if (a->l) { 2622d1154bdSMatheus Ferst if ((ctx->insns_flags2 & PPC2_BOOKE206)) { 2632d1154bdSMatheus Ferst /* 2642d1154bdSMatheus Ferst * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc), 2652d1154bdSMatheus Ferst * generate an illegal instruction exception. 2662d1154bdSMatheus Ferst */ 2672d1154bdSMatheus Ferst return false; 2682d1154bdSMatheus Ferst } else { 2692d1154bdSMatheus Ferst qemu_log_mask(LOG_GUEST_ERROR, 2702d1154bdSMatheus Ferst "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n", 2712d1154bdSMatheus Ferst s ? "I" : "LI", ctx->cia); 2722d1154bdSMatheus Ferst } 2732d1154bdSMatheus Ferst } 2742d1154bdSMatheus Ferst gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf); 2752d1154bdSMatheus Ferst return true; 2762d1154bdSMatheus Ferst } 2772d1154bdSMatheus Ferst 2782d1154bdSMatheus Ferst /* For 64-bit implementations, deal with bit L accordingly. */ 2792d1154bdSMatheus Ferst if (a->l) { 2808f0a4b6aSMatheus Ferst gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf); 2818f0a4b6aSMatheus Ferst } else { 2828f0a4b6aSMatheus Ferst gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf); 2838f0a4b6aSMatheus Ferst } 2848f0a4b6aSMatheus Ferst return true; 2858f0a4b6aSMatheus Ferst} 2868f0a4b6aSMatheus Ferst 2878f0a4b6aSMatheus FerstTRANS(CMP, do_cmp_X, true); 2888f0a4b6aSMatheus FerstTRANS(CMPL, do_cmp_X, false); 2898f0a4b6aSMatheus FerstTRANS(CMPI, do_cmp_D, true); 2908f0a4b6aSMatheus FerstTRANS(CMPLI, do_cmp_D, false); 2918f0a4b6aSMatheus Ferst 292ae556c6aSChinmay Rathstatic bool trans_CMPRB(DisasContext *ctx, arg_CMPRB *a) 293ae556c6aSChinmay Rath{ 294ae556c6aSChinmay Rath TCGv_i32 src1 = tcg_temp_new_i32(); 295ae556c6aSChinmay Rath TCGv_i32 src2 = tcg_temp_new_i32(); 296ae556c6aSChinmay Rath TCGv_i32 src2lo = tcg_temp_new_i32(); 297ae556c6aSChinmay Rath TCGv_i32 src2hi = tcg_temp_new_i32(); 298ae556c6aSChinmay Rath TCGv_i32 crf = cpu_crf[a->bf]; 299ae556c6aSChinmay Rath 300ae556c6aSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 301ae556c6aSChinmay Rath tcg_gen_trunc_tl_i32(src1, cpu_gpr[a->ra]); 302ae556c6aSChinmay Rath tcg_gen_trunc_tl_i32(src2, cpu_gpr[a->rb]); 303ae556c6aSChinmay Rath 304ae556c6aSChinmay Rath tcg_gen_andi_i32(src1, src1, 0xFF); 305ae556c6aSChinmay Rath tcg_gen_ext8u_i32(src2lo, src2); 306ae556c6aSChinmay Rath tcg_gen_extract_i32(src2hi, src2, 8, 8); 307ae556c6aSChinmay Rath 308ae556c6aSChinmay Rath tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1); 309ae556c6aSChinmay Rath tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi); 310ae556c6aSChinmay Rath tcg_gen_and_i32(crf, src2lo, src2hi); 311ae556c6aSChinmay Rath 312ae556c6aSChinmay Rath if (a->l) { 313ae556c6aSChinmay Rath tcg_gen_extract_i32(src2lo, src2, 16, 8); 314ae556c6aSChinmay Rath tcg_gen_extract_i32(src2hi, src2, 24, 8); 315ae556c6aSChinmay Rath tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1); 316ae556c6aSChinmay Rath tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi); 317ae556c6aSChinmay Rath tcg_gen_and_i32(src2lo, src2lo, src2hi); 318ae556c6aSChinmay Rath tcg_gen_or_i32(crf, crf, src2lo); 319ae556c6aSChinmay Rath } 320ae556c6aSChinmay Rath tcg_gen_shli_i32(crf, crf, CRF_GT_BIT); 321ae556c6aSChinmay Rath return true; 322ae556c6aSChinmay Rath} 323ae556c6aSChinmay Rath 324ae556c6aSChinmay Rathstatic bool trans_CMPEQB(DisasContext *ctx, arg_CMPEQB *a) 325ae556c6aSChinmay Rath{ 326ae556c6aSChinmay Rath REQUIRE_64BIT(ctx); 327ae556c6aSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 328ae556c6aSChinmay Rath#if defined(TARGET_PPC64) 329ae556c6aSChinmay Rath gen_helper_CMPEQB(cpu_crf[a->bf], cpu_gpr[a->ra], cpu_gpr[a->rb]); 330ae556c6aSChinmay Rath#else 331ae556c6aSChinmay Rath qemu_build_not_reached(); 332ae556c6aSChinmay Rath#endif 333ae556c6aSChinmay Rath return true; 334ae556c6aSChinmay Rath} 335ae556c6aSChinmay Rath 3368f0a4b6aSMatheus Ferst/* 337f2aabda8SRichard Henderson * Fixed-Point Arithmetic Instructions 338f2aabda8SRichard Henderson */ 339f2aabda8SRichard Henderson 3405e560864SRichard Hendersonstatic bool trans_ADDI(DisasContext *ctx, arg_D *a) 3415e560864SRichard Henderson{ 3425e560864SRichard Henderson if (a->ra) { 3435e560864SRichard Henderson tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si); 3445e560864SRichard Henderson } else { 3455e560864SRichard Henderson tcg_gen_movi_tl(cpu_gpr[a->rt], a->si); 3465e560864SRichard Henderson } 3475e560864SRichard Henderson return true; 3485e560864SRichard Henderson} 3495e560864SRichard Henderson 3505e560864SRichard Hendersonstatic bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a) 3515e560864SRichard Henderson{ 3525e560864SRichard Henderson arg_D d; 3535e560864SRichard Henderson if (!resolve_PLS_D(ctx, &d, a)) { 3545e560864SRichard Henderson return true; 3555e560864SRichard Henderson } 3565e560864SRichard Henderson return trans_ADDI(ctx, &d); 3575e560864SRichard Henderson} 3585e560864SRichard Henderson 3595e560864SRichard Hendersonstatic bool trans_ADDIS(DisasContext *ctx, arg_D *a) 3605e560864SRichard Henderson{ 3615e560864SRichard Henderson a->si <<= 16; 3625e560864SRichard Henderson return trans_ADDI(ctx, a); 3635e560864SRichard Henderson} 3640a11bb7aSRichard Henderson 365e7a5d578SMatheus Ferststatic bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a) 366e7a5d578SMatheus Ferst{ 367e7a5d578SMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, ISA300); 368e7a5d578SMatheus Ferst tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16)); 369e7a5d578SMatheus Ferst return true; 370e7a5d578SMatheus Ferst} 371e7a5d578SMatheus Ferst 372a9bd40d9SChinmay Rathstatic bool trans_ADDEX(DisasContext *ctx, arg_X *a) 373a9bd40d9SChinmay Rath{ 374a9bd40d9SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 375a9bd40d9SChinmay Rath gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 376a9bd40d9SChinmay Rath cpu_ov, cpu_ov32, true, true, false, false); 377a9bd40d9SChinmay Rath return true; 378a9bd40d9SChinmay Rath} 379a9bd40d9SChinmay Rath 380a9bd40d9SChinmay Rathstatic bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca, 381a9bd40d9SChinmay Rath bool compute_ov, bool compute_rc0) 382a9bd40d9SChinmay Rath{ 383a9bd40d9SChinmay Rath gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], 384a9bd40d9SChinmay Rath tcg_constant_tl(a->si), cpu_ca, cpu_ca32, 385a9bd40d9SChinmay Rath add_ca, compute_ca, compute_ov, compute_rc0); 386a9bd40d9SChinmay Rath return true; 387a9bd40d9SChinmay Rath} 388a9bd40d9SChinmay Rath 389a9bd40d9SChinmay Rathstatic bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca, 390a9bd40d9SChinmay Rath bool compute_ca) 391a9bd40d9SChinmay Rath{ 392a9bd40d9SChinmay Rath gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 393a9bd40d9SChinmay Rath cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc); 394a9bd40d9SChinmay Rath return true; 395a9bd40d9SChinmay Rath} 396a9bd40d9SChinmay Rath 397a9bd40d9SChinmay Rathstatic bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val, 398a9bd40d9SChinmay Rath bool add_ca, bool compute_ca) 399a9bd40d9SChinmay Rath{ 400a9bd40d9SChinmay Rath gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val, 401a9bd40d9SChinmay Rath cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc); 402a9bd40d9SChinmay Rath return true; 403a9bd40d9SChinmay Rath} 404a9bd40d9SChinmay Rath 405a9bd40d9SChinmay RathTRANS(ADD, do_add_XO, false, false); 406a9bd40d9SChinmay RathTRANS(ADDC, do_add_XO, false, true); 407a9bd40d9SChinmay RathTRANS(ADDE, do_add_XO, true, true); 408a9bd40d9SChinmay RathTRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true); 409a9bd40d9SChinmay RathTRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true); 410a9bd40d9SChinmay RathTRANS(ADDIC, do_add_D, false, true, false, false); 411a9bd40d9SChinmay RathTRANS(ADDIC_, do_add_D, false, true, false, true); 412a9bd40d9SChinmay Rath 413a9bd40d9SChinmay Rathstatic bool trans_SUBFIC(DisasContext *ctx, arg_D *a) 414a9bd40d9SChinmay Rath{ 415a9bd40d9SChinmay Rath gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], 416a9bd40d9SChinmay Rath tcg_constant_tl(a->si), false, true, false, false); 417a9bd40d9SChinmay Rath return true; 418a9bd40d9SChinmay Rath} 419a9bd40d9SChinmay Rath 420a9bd40d9SChinmay Rathstatic bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca, 421a9bd40d9SChinmay Rath bool compute_ca) 422a9bd40d9SChinmay Rath{ 423a9bd40d9SChinmay Rath gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 424a9bd40d9SChinmay Rath add_ca, compute_ca, a->oe, a->rc); 425a9bd40d9SChinmay Rath return true; 426a9bd40d9SChinmay Rath} 427a9bd40d9SChinmay Rath 428a9bd40d9SChinmay Rathstatic bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val, 429a9bd40d9SChinmay Rath bool add_ca, bool compute_ca) 430a9bd40d9SChinmay Rath{ 431a9bd40d9SChinmay Rath gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val, 432a9bd40d9SChinmay Rath add_ca, compute_ca, a->oe, a->rc); 433a9bd40d9SChinmay Rath return true; 434a9bd40d9SChinmay Rath} 435a9bd40d9SChinmay Rath 436a9bd40d9SChinmay RathTRANS(SUBF, do_subf_XO, false, false) 437a9bd40d9SChinmay RathTRANS(SUBFC, do_subf_XO, false, true) 438a9bd40d9SChinmay RathTRANS(SUBFE, do_subf_XO, true, true) 439a9bd40d9SChinmay RathTRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true) 440a9bd40d9SChinmay RathTRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true) 441a9bd40d9SChinmay Rath 442a1faff87SChinmay Rathstatic bool trans_MULLI(DisasContext *ctx, arg_MULLI *a) 443a1faff87SChinmay Rath{ 444a1faff87SChinmay Rath tcg_gen_muli_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si); 445a1faff87SChinmay Rath return true; 446a1faff87SChinmay Rath} 447a1faff87SChinmay Rath 448a1faff87SChinmay Rathstatic bool trans_MULLW(DisasContext *ctx, arg_MULLW *a) 449a1faff87SChinmay Rath{ 450a1faff87SChinmay Rath TCGv t0 = tcg_temp_new(); 451a1faff87SChinmay Rath TCGv t1 = tcg_temp_new(); 452a1faff87SChinmay Rath 453a1faff87SChinmay Rath tcg_gen_ext32s_tl(t0, cpu_gpr[a->ra]); 454a1faff87SChinmay Rath tcg_gen_ext32s_tl(t1, cpu_gpr[a->rb]); 455a1faff87SChinmay Rath tcg_gen_mul_tl(cpu_gpr[a->rt], t0, t1); 456a1faff87SChinmay Rath if (unlikely(a->rc)) { 457a1faff87SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 458a1faff87SChinmay Rath } 459a1faff87SChinmay Rath return true; 460a1faff87SChinmay Rath} 461a1faff87SChinmay Rath 462a1faff87SChinmay Rathstatic bool trans_MULLWO(DisasContext *ctx, arg_MULLWO *a) 463a1faff87SChinmay Rath{ 464a1faff87SChinmay Rath TCGv t0 = tcg_temp_new(); 465a1faff87SChinmay Rath TCGv t1 = tcg_temp_new(); 466a1faff87SChinmay Rath 467a1faff87SChinmay Rath#if defined(TARGET_PPC64) 468a1faff87SChinmay Rath tcg_gen_ext32s_i64(t0, cpu_gpr[a->ra]); 469a1faff87SChinmay Rath tcg_gen_ext32s_i64(t1, cpu_gpr[a->rb]); 470a1faff87SChinmay Rath tcg_gen_mul_i64(cpu_gpr[a->rt], t0, t1); 471a1faff87SChinmay Rath tcg_gen_sextract_i64(t0, cpu_gpr[a->rt], 31, 1); 472a1faff87SChinmay Rath tcg_gen_sari_i64(t1, cpu_gpr[a->rt], 32); 473a1faff87SChinmay Rath#else 474a1faff87SChinmay Rath tcg_gen_muls2_i32(cpu_gpr[a->rt], t1, cpu_gpr[a->ra], cpu_gpr[a->rb]); 475a1faff87SChinmay Rath tcg_gen_sari_i32(t0, cpu_gpr[a->rt], 31); 476a1faff87SChinmay Rath#endif 477a1faff87SChinmay Rath tcg_gen_setcond_tl(TCG_COND_NE, cpu_ov, t0, t1); 478a1faff87SChinmay Rath if (is_isa300(ctx)) { 479a1faff87SChinmay Rath tcg_gen_mov_tl(cpu_ov32, cpu_ov); 480a1faff87SChinmay Rath } 481a1faff87SChinmay Rath tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 482a1faff87SChinmay Rath 483a1faff87SChinmay Rath if (unlikely(a->rc)) { 484a1faff87SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 485a1faff87SChinmay Rath } 486a1faff87SChinmay Rath return true; 487a1faff87SChinmay Rath} 488a1faff87SChinmay Rath 489a1faff87SChinmay Rathstatic bool do_mulhw(DisasContext *ctx, arg_XO_tab_rc *a, 490a1faff87SChinmay Rath void (*helper)(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, 491a1faff87SChinmay Rath TCGv_i32 arg2)) 492a1faff87SChinmay Rath{ 493a1faff87SChinmay Rath TCGv_i32 t0 = tcg_temp_new_i32(); 494a1faff87SChinmay Rath TCGv_i32 t1 = tcg_temp_new_i32(); 495a1faff87SChinmay Rath tcg_gen_trunc_tl_i32(t0, cpu_gpr[a->ra]); 496a1faff87SChinmay Rath tcg_gen_trunc_tl_i32(t1, cpu_gpr[a->rb]); 497a1faff87SChinmay Rath helper(t0, t1, t0, t1); 498a1faff87SChinmay Rath tcg_gen_extu_i32_tl(cpu_gpr[a->rt], t1); 499a1faff87SChinmay Rath if (unlikely(a->rc)) { 500a1faff87SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 501a1faff87SChinmay Rath } 502a1faff87SChinmay Rath return true; 503a1faff87SChinmay Rath} 504a1faff87SChinmay Rath 505a1faff87SChinmay RathTRANS(MULHW, do_mulhw, tcg_gen_muls2_i32) 506a1faff87SChinmay RathTRANS(MULHWU, do_mulhw, tcg_gen_mulu2_i32) 507a1faff87SChinmay Rath 5082871921dSChinmay Rathstatic bool do_divw(DisasContext *ctx, arg_XO *a, int sign) 5092871921dSChinmay Rath{ 5102871921dSChinmay Rath gen_op_arith_divw(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 5112871921dSChinmay Rath sign, a->oe, a->rc); 5122871921dSChinmay Rath return true; 5132871921dSChinmay Rath} 5142871921dSChinmay Rath 515f424bc10SChinmay Rathstatic bool do_dive(DisasContext *ctx, arg_XO *a, 5162871921dSChinmay Rath void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv, TCGv_i32)) 5172871921dSChinmay Rath{ 5182871921dSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, DIVE_ISA206); 5192871921dSChinmay Rath helper(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], 5202871921dSChinmay Rath tcg_constant_i32(a->oe)); 5212871921dSChinmay Rath if (unlikely(a->rc)) { 5222871921dSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 5232871921dSChinmay Rath } 5242871921dSChinmay Rath return true; 5252871921dSChinmay Rath} 5262871921dSChinmay Rath 5272871921dSChinmay RathTRANS(DIVW, do_divw, 1); 5282871921dSChinmay RathTRANS(DIVWU, do_divw, 0); 529f424bc10SChinmay RathTRANS(DIVWE, do_dive, gen_helper_DIVWE); 530f424bc10SChinmay RathTRANS(DIVWEU, do_dive, gen_helper_DIVWEU); 5312871921dSChinmay Rath 532a81b5c18SChinmay Rathstatic bool do_modw(DisasContext *ctx, arg_X *a, bool sign) 533a81b5c18SChinmay Rath{ 534a81b5c18SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 535a81b5c18SChinmay Rath gen_op_arith_modw(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 536a81b5c18SChinmay Rath sign); 537a81b5c18SChinmay Rath return true; 538a81b5c18SChinmay Rath} 539a81b5c18SChinmay Rath 540a81b5c18SChinmay RathTRANS(MODUW, do_modw, false); 541a81b5c18SChinmay RathTRANS(MODSW, do_modw, true); 542a81b5c18SChinmay Rath 543a81b5c18SChinmay Rathstatic bool trans_NEG(DisasContext *ctx, arg_NEG *a) 544a81b5c18SChinmay Rath{ 545a81b5c18SChinmay Rath if (a->oe) { 546a81b5c18SChinmay Rath TCGv zero = tcg_constant_tl(0); 547a81b5c18SChinmay Rath gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], zero, 548a81b5c18SChinmay Rath false, false, true, a->rc); 549a81b5c18SChinmay Rath } else { 550a81b5c18SChinmay Rath tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->ra]); 551a81b5c18SChinmay Rath if (unlikely(a->rc)) { 552a81b5c18SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 553a81b5c18SChinmay Rath } 554a81b5c18SChinmay Rath } 555a81b5c18SChinmay Rath return true; 556a81b5c18SChinmay Rath} 557a81b5c18SChinmay Rath 558a81b5c18SChinmay Rathstatic bool trans_DARN(DisasContext *ctx, arg_DARN *a) 559a81b5c18SChinmay Rath{ 560a81b5c18SChinmay Rath REQUIRE_64BIT(ctx); 561a81b5c18SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 562a81b5c18SChinmay Rath#if defined(TARGET_PPC64) 563a81b5c18SChinmay Rath if (a->l > 2) { 564a81b5c18SChinmay Rath tcg_gen_movi_i64(cpu_gpr[a->rt], -1); 565a81b5c18SChinmay Rath } else { 566a81b5c18SChinmay Rath translator_io_start(&ctx->base); 567a81b5c18SChinmay Rath if (a->l == 0) { 568a81b5c18SChinmay Rath gen_helper_DARN32(cpu_gpr[a->rt]); 569a81b5c18SChinmay Rath } else { 570a81b5c18SChinmay Rath /* Return 64-bit random for both CRN and RRN */ 571a81b5c18SChinmay Rath gen_helper_DARN64(cpu_gpr[a->rt]); 572a81b5c18SChinmay Rath } 573a81b5c18SChinmay Rath } 574a81b5c18SChinmay Rath#else 575a81b5c18SChinmay Rath qemu_build_not_reached(); 576a81b5c18SChinmay Rath#endif 577a81b5c18SChinmay Rath return true; 578a81b5c18SChinmay Rath} 579a81b5c18SChinmay Rath 580703e88f7SChinmay Rathstatic bool trans_MULLD(DisasContext *ctx, arg_MULLD *a) 581703e88f7SChinmay Rath{ 582703e88f7SChinmay Rath REQUIRE_64BIT(ctx); 583703e88f7SChinmay Rath#if defined(TARGET_PPC64) 584703e88f7SChinmay Rath tcg_gen_mul_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb]); 585703e88f7SChinmay Rath if (unlikely(a->rc)) { 586703e88f7SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 587703e88f7SChinmay Rath } 588703e88f7SChinmay Rath#else 589703e88f7SChinmay Rath qemu_build_not_reached(); 590703e88f7SChinmay Rath#endif 591703e88f7SChinmay Rath return true; 592703e88f7SChinmay Rath} 593703e88f7SChinmay Rath 594703e88f7SChinmay Rathstatic bool trans_MULLDO(DisasContext *ctx, arg_MULLD *a) 595703e88f7SChinmay Rath{ 596703e88f7SChinmay Rath REQUIRE_64BIT(ctx); 597703e88f7SChinmay Rath#if defined(TARGET_PPC64) 598703e88f7SChinmay Rath TCGv_i64 t0 = tcg_temp_new_i64(); 599703e88f7SChinmay Rath TCGv_i64 t1 = tcg_temp_new_i64(); 600703e88f7SChinmay Rath 601703e88f7SChinmay Rath tcg_gen_muls2_i64(t0, t1, cpu_gpr[a->ra], cpu_gpr[a->rb]); 602703e88f7SChinmay Rath tcg_gen_mov_i64(cpu_gpr[a->rt], t0); 603703e88f7SChinmay Rath 604703e88f7SChinmay Rath tcg_gen_sari_i64(t0, t0, 63); 605703e88f7SChinmay Rath tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1); 606703e88f7SChinmay Rath if (is_isa300(ctx)) { 607703e88f7SChinmay Rath tcg_gen_mov_tl(cpu_ov32, cpu_ov); 608703e88f7SChinmay Rath } 609703e88f7SChinmay Rath tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 610703e88f7SChinmay Rath 611703e88f7SChinmay Rath if (unlikely(a->rc)) { 612703e88f7SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 613703e88f7SChinmay Rath } 614703e88f7SChinmay Rath#else 615703e88f7SChinmay Rath qemu_build_not_reached(); 616703e88f7SChinmay Rath#endif 617703e88f7SChinmay Rath return true; 618703e88f7SChinmay Rath} 619703e88f7SChinmay Rath 620703e88f7SChinmay Rathstatic bool do_mulhd(DisasContext *ctx, arg_XO_tab_rc *a, 621703e88f7SChinmay Rath void (*helper)(TCGv, TCGv, TCGv, TCGv)) 622703e88f7SChinmay Rath{ 623703e88f7SChinmay Rath TCGv lo = tcg_temp_new(); 624703e88f7SChinmay Rath helper(lo, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb]); 625703e88f7SChinmay Rath if (unlikely(a->rc)) { 626703e88f7SChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 627703e88f7SChinmay Rath } 628703e88f7SChinmay Rath return true; 629703e88f7SChinmay Rath} 630703e88f7SChinmay Rath 631703e88f7SChinmay RathTRANS64(MULHD, do_mulhd, tcg_gen_muls2_tl); 632703e88f7SChinmay RathTRANS64(MULHDU, do_mulhd, tcg_gen_mulu2_tl); 633703e88f7SChinmay Rath 634703e88f7SChinmay Rathstatic bool trans_MADDLD(DisasContext *ctx, arg_MADDLD *a) 635703e88f7SChinmay Rath{ 636703e88f7SChinmay Rath REQUIRE_64BIT(ctx); 637703e88f7SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 638703e88f7SChinmay Rath#if defined(TARGET_PPC64) 639703e88f7SChinmay Rath TCGv_i64 t1 = tcg_temp_new_i64(); 640703e88f7SChinmay Rath 641703e88f7SChinmay Rath tcg_gen_mul_i64(t1, cpu_gpr[a->vra], cpu_gpr[a->vrb]); 642703e88f7SChinmay Rath tcg_gen_add_i64(cpu_gpr[a->vrt], t1, cpu_gpr[a->rc]); 643703e88f7SChinmay Rath#else 644703e88f7SChinmay Rath qemu_build_not_reached(); 645703e88f7SChinmay Rath#endif 646703e88f7SChinmay Rath return true; 647703e88f7SChinmay Rath} 648703e88f7SChinmay Rath 649703e88f7SChinmay Rathstatic bool trans_MADDHD(DisasContext *ctx, arg_MADDHD *a) 650703e88f7SChinmay Rath{ 651703e88f7SChinmay Rath REQUIRE_64BIT(ctx); 652703e88f7SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 653703e88f7SChinmay Rath#if defined(TARGET_PPC64) 654703e88f7SChinmay Rath TCGv_i64 lo = tcg_temp_new_i64(); 655703e88f7SChinmay Rath TCGv_i64 hi = tcg_temp_new_i64(); 656703e88f7SChinmay Rath TCGv_i64 t1 = tcg_temp_new_i64(); 657703e88f7SChinmay Rath 658703e88f7SChinmay Rath tcg_gen_muls2_i64(lo, hi, cpu_gpr[a->vra], cpu_gpr[a->vrb]); 659703e88f7SChinmay Rath tcg_gen_sari_i64(t1, cpu_gpr[a->rc], 63); 660703e88f7SChinmay Rath tcg_gen_add2_i64(t1, cpu_gpr[a->vrt], lo, hi, cpu_gpr[a->rc], t1); 661703e88f7SChinmay Rath#else 662703e88f7SChinmay Rath qemu_build_not_reached(); 663703e88f7SChinmay Rath#endif 664703e88f7SChinmay Rath return true; 665703e88f7SChinmay Rath} 666703e88f7SChinmay Rath 667703e88f7SChinmay Rathstatic bool trans_MADDHDU(DisasContext *ctx, arg_MADDHDU *a) 668703e88f7SChinmay Rath{ 669703e88f7SChinmay Rath REQUIRE_64BIT(ctx); 670703e88f7SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 671703e88f7SChinmay Rath#if defined(TARGET_PPC64) 672703e88f7SChinmay Rath TCGv_i64 lo = tcg_temp_new_i64(); 673703e88f7SChinmay Rath TCGv_i64 hi = tcg_temp_new_i64(); 674703e88f7SChinmay Rath TCGv_i64 t1 = tcg_temp_new_i64(); 675703e88f7SChinmay Rath 676703e88f7SChinmay Rath tcg_gen_mulu2_i64(lo, hi, cpu_gpr[a->vra], cpu_gpr[a->vrb]); 677703e88f7SChinmay Rath tcg_gen_add2_i64(t1, cpu_gpr[a->vrt], lo, hi, cpu_gpr[a->rc], 678703e88f7SChinmay Rath tcg_constant_i64(0)); 679703e88f7SChinmay Rath#else 680703e88f7SChinmay Rath qemu_build_not_reached(); 681703e88f7SChinmay Rath#endif 682703e88f7SChinmay Rath return true; 683703e88f7SChinmay Rath} 684703e88f7SChinmay Rath 685f424bc10SChinmay Rathstatic bool do_divd(DisasContext *ctx, arg_XO *a, bool sign) 686f424bc10SChinmay Rath{ 687f424bc10SChinmay Rath REQUIRE_64BIT(ctx); 688f424bc10SChinmay Rath#if defined(TARGET_PPC64) 689f424bc10SChinmay Rath gen_op_arith_divd(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 690f424bc10SChinmay Rath sign, a->oe, a->rc); 691f424bc10SChinmay Rath#else 692f424bc10SChinmay Rath qemu_build_not_reached(); 693f424bc10SChinmay Rath#endif 694f424bc10SChinmay Rath return true; 695f424bc10SChinmay Rath} 696f424bc10SChinmay Rath 697f424bc10SChinmay Rathstatic bool do_modd(DisasContext *ctx, arg_X *a, bool sign) 698f424bc10SChinmay Rath{ 699f424bc10SChinmay Rath REQUIRE_64BIT(ctx); 700f424bc10SChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 701f424bc10SChinmay Rath#if defined(TARGET_PPC64) 702f424bc10SChinmay Rath gen_op_arith_modd(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb], 703f424bc10SChinmay Rath sign); 704f424bc10SChinmay Rath#else 705f424bc10SChinmay Rath qemu_build_not_reached(); 706f424bc10SChinmay Rath#endif 707f424bc10SChinmay Rath return true; 708f424bc10SChinmay Rath} 709f424bc10SChinmay Rath 710f424bc10SChinmay RathTRANS64(DIVD, do_divd, true); 711f424bc10SChinmay RathTRANS64(DIVDU, do_divd, false); 712f424bc10SChinmay Rath 713f424bc10SChinmay Rathstatic bool trans_DIVDE(DisasContext *ctx, arg_DIVDE *a) 714f424bc10SChinmay Rath{ 715f424bc10SChinmay Rath REQUIRE_64BIT(ctx); 716f424bc10SChinmay Rath#if defined(TARGET_PPC64) 717f424bc10SChinmay Rath return do_dive(ctx, a, gen_helper_DIVDE); 718f424bc10SChinmay Rath#else 719f424bc10SChinmay Rath qemu_build_not_reached(); 720f424bc10SChinmay Rath#endif 721f424bc10SChinmay Rath} 722f424bc10SChinmay Rath 723f424bc10SChinmay Rathstatic bool trans_DIVDEU(DisasContext *ctx, arg_DIVDEU *a) 724f424bc10SChinmay Rath{ 725f424bc10SChinmay Rath REQUIRE_64BIT(ctx); 726f424bc10SChinmay Rath#if defined(TARGET_PPC64) 727f424bc10SChinmay Rath return do_dive(ctx, a, gen_helper_DIVDEU); 728f424bc10SChinmay Rath#else 729f424bc10SChinmay Rath qemu_build_not_reached(); 730f424bc10SChinmay Rath#endif 731f424bc10SChinmay Rath return true; 732f424bc10SChinmay Rath} 733f424bc10SChinmay Rath 734f424bc10SChinmay RathTRANS64(MODSD, do_modd, true); 735f424bc10SChinmay RathTRANS64(MODUD, do_modd, false); 736f424bc10SChinmay Rath 737ae556c6aSChinmay Rath/* 738ae556c6aSChinmay Rath * Fixed-Point Select Instructions 739ae556c6aSChinmay Rath */ 740ae556c6aSChinmay Rath 741ae556c6aSChinmay Rathstatic bool trans_ISEL(DisasContext *ctx, arg_ISEL *a) 742ae556c6aSChinmay Rath{ 743ae556c6aSChinmay Rath REQUIRE_INSNS_FLAGS(ctx, ISEL); 744ae556c6aSChinmay Rath uint32_t bi = a->bc; 745ae556c6aSChinmay Rath uint32_t mask = 0x08 >> (bi & 0x03); 746ae556c6aSChinmay Rath TCGv t0 = tcg_temp_new(); 747ae556c6aSChinmay Rath TCGv zr; 748ae556c6aSChinmay Rath 749ae556c6aSChinmay Rath tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]); 750ae556c6aSChinmay Rath tcg_gen_andi_tl(t0, t0, mask); 751ae556c6aSChinmay Rath 752ae556c6aSChinmay Rath zr = tcg_constant_tl(0); 753ae556c6aSChinmay Rath tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, zr, 754ae556c6aSChinmay Rath a->ra ? cpu_gpr[a->ra] : zr, 755ae556c6aSChinmay Rath cpu_gpr[a->rb]); 756ae556c6aSChinmay Rath return true; 757ae556c6aSChinmay Rath} 758ae556c6aSChinmay Rath 759ae556c6aSChinmay Rath/* 760ae556c6aSChinmay Rath * Fixed-Point Trap Instructions 761ae556c6aSChinmay Rath */ 762ae556c6aSChinmay Rath 763ae556c6aSChinmay Rathstatic bool trans_TW(DisasContext *ctx, arg_TW *a) 764ae556c6aSChinmay Rath{ 765ae556c6aSChinmay Rath TCGv_i32 t0; 766ae556c6aSChinmay Rath 767ae556c6aSChinmay Rath if (check_unconditional_trap(ctx, a->rt)) { 768ae556c6aSChinmay Rath return true; 769ae556c6aSChinmay Rath } 770ae556c6aSChinmay Rath t0 = tcg_constant_i32(a->rt); 771ae556c6aSChinmay Rath gen_helper_TW(tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], t0); 772ae556c6aSChinmay Rath return true; 773ae556c6aSChinmay Rath} 774ae556c6aSChinmay Rath 775ae556c6aSChinmay Rathstatic bool trans_TWI(DisasContext *ctx, arg_TWI *a) 776ae556c6aSChinmay Rath{ 777ae556c6aSChinmay Rath TCGv t0; 778ae556c6aSChinmay Rath TCGv_i32 t1; 779ae556c6aSChinmay Rath 780ae556c6aSChinmay Rath if (check_unconditional_trap(ctx, a->rt)) { 781ae556c6aSChinmay Rath return true; 782ae556c6aSChinmay Rath } 783ae556c6aSChinmay Rath t0 = tcg_constant_tl(a->si); 784ae556c6aSChinmay Rath t1 = tcg_constant_i32(a->rt); 785ae556c6aSChinmay Rath gen_helper_TW(tcg_env, cpu_gpr[a->ra], t0, t1); 786ae556c6aSChinmay Rath return true; 787ae556c6aSChinmay Rath} 788ae556c6aSChinmay Rath 789ae556c6aSChinmay Rathstatic bool trans_TD(DisasContext *ctx, arg_TD *a) 790ae556c6aSChinmay Rath{ 791ae556c6aSChinmay Rath REQUIRE_64BIT(ctx); 792ae556c6aSChinmay Rath#if defined(TARGET_PPC64) 793ae556c6aSChinmay Rath TCGv_i32 t0; 794ae556c6aSChinmay Rath 795ae556c6aSChinmay Rath if (check_unconditional_trap(ctx, a->rt)) { 796ae556c6aSChinmay Rath return true; 797ae556c6aSChinmay Rath } 798ae556c6aSChinmay Rath t0 = tcg_constant_i32(a->rt); 799ae556c6aSChinmay Rath gen_helper_TD(tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], t0); 800ae556c6aSChinmay Rath#else 801ae556c6aSChinmay Rath qemu_build_not_reached(); 802ae556c6aSChinmay Rath#endif 803ae556c6aSChinmay Rath return true; 804ae556c6aSChinmay Rath} 805ae556c6aSChinmay Rath 806ae556c6aSChinmay Rathstatic bool trans_TDI(DisasContext *ctx, arg_TDI *a) 807ae556c6aSChinmay Rath{ 808ae556c6aSChinmay Rath REQUIRE_64BIT(ctx); 809ae556c6aSChinmay Rath#if defined(TARGET_PPC64) 810ae556c6aSChinmay Rath TCGv t0; 811ae556c6aSChinmay Rath TCGv_i32 t1; 812ae556c6aSChinmay Rath 813ae556c6aSChinmay Rath if (check_unconditional_trap(ctx, a->rt)) { 814ae556c6aSChinmay Rath return true; 815ae556c6aSChinmay Rath } 816ae556c6aSChinmay Rath t0 = tcg_constant_tl(a->si); 817ae556c6aSChinmay Rath t1 = tcg_constant_i32(a->rt); 818ae556c6aSChinmay Rath gen_helper_TD(tcg_env, cpu_gpr[a->ra], t0, t1); 819ae556c6aSChinmay Rath#else 820ae556c6aSChinmay Rath qemu_build_not_reached(); 821ae556c6aSChinmay Rath#endif 822ae556c6aSChinmay Rath return true; 823ae556c6aSChinmay Rath} 824ae556c6aSChinmay Rath 8250a11bb7aSRichard Hendersonstatic bool trans_INVALID(DisasContext *ctx, arg_INVALID *a) 8260a11bb7aSRichard Henderson{ 8270a11bb7aSRichard Henderson gen_invalid(ctx); 8280a11bb7aSRichard Henderson return true; 8290a11bb7aSRichard Henderson} 8300a11bb7aSRichard Henderson 8310a11bb7aSRichard Hendersonstatic bool trans_PNOP(DisasContext *ctx, arg_PNOP *a) 8320a11bb7aSRichard Henderson{ 8330a11bb7aSRichard Henderson return true; 8340a11bb7aSRichard Henderson} 8359a14365eSMatheus Ferst 8369a14365eSMatheus Ferststatic bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev) 8379a14365eSMatheus Ferst{ 8389a14365eSMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, ISA310); 8399a14365eSMatheus Ferst uint32_t mask = 0x08 >> (a->bi & 0x03); 8409a14365eSMatheus Ferst TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE; 8419a14365eSMatheus Ferst TCGv temp = tcg_temp_new(); 842253d110dSRichard Henderson TCGv zero = tcg_constant_tl(0); 8439a14365eSMatheus Ferst 8449a14365eSMatheus Ferst tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]); 8459a14365eSMatheus Ferst tcg_gen_andi_tl(temp, temp, mask); 8469a14365eSMatheus Ferst if (neg) { 847253d110dSRichard Henderson tcg_gen_negsetcond_tl(cond, cpu_gpr[a->rt], temp, zero); 848253d110dSRichard Henderson } else { 849253d110dSRichard Henderson tcg_gen_setcond_tl(cond, cpu_gpr[a->rt], temp, zero); 8509a14365eSMatheus Ferst } 8519a14365eSMatheus Ferst return true; 8529a14365eSMatheus Ferst} 8539a14365eSMatheus Ferst 8549a14365eSMatheus FerstTRANS(SETBC, do_set_bool_cond, false, false) 8559a14365eSMatheus FerstTRANS(SETBCR, do_set_bool_cond, false, true) 8569a14365eSMatheus FerstTRANS(SETNBC, do_set_bool_cond, true, false) 8579a14365eSMatheus FerstTRANS(SETNBCR, do_set_bool_cond, true, true) 85889ccd7dcSMatheus Ferst 859*948e257cSChinmay Rath/* 860*948e257cSChinmay Rath * Fixed-Point Logical Instructions 861*948e257cSChinmay Rath */ 862*948e257cSChinmay Rath 863*948e257cSChinmay Rathstatic bool do_addi_(DisasContext *ctx, arg_D_ui *a, bool shift) 864*948e257cSChinmay Rath{ 865*948e257cSChinmay Rath tcg_gen_andi_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], shift ? a->ui << 16 : a->ui); 866*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 867*948e257cSChinmay Rath return true; 868*948e257cSChinmay Rath} 869*948e257cSChinmay Rath 870*948e257cSChinmay Rathstatic bool do_ori(DisasContext *ctx, arg_D_ui *a, bool shift) 871*948e257cSChinmay Rath{ 872*948e257cSChinmay Rath if (a->rt == a->ra && a->ui == 0) { 873*948e257cSChinmay Rath /* NOP */ 874*948e257cSChinmay Rath return true; 875*948e257cSChinmay Rath } 876*948e257cSChinmay Rath tcg_gen_ori_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], shift ? a->ui << 16 : a->ui); 877*948e257cSChinmay Rath return true; 878*948e257cSChinmay Rath} 879*948e257cSChinmay Rath 880*948e257cSChinmay Rathstatic bool do_xori(DisasContext *ctx, arg_D_ui *a, bool shift) 881*948e257cSChinmay Rath{ 882*948e257cSChinmay Rath if (a->rt == a->ra && a->ui == 0) { 883*948e257cSChinmay Rath /* NOP */ 884*948e257cSChinmay Rath return true; 885*948e257cSChinmay Rath } 886*948e257cSChinmay Rath tcg_gen_xori_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], shift ? a->ui << 16 : a->ui); 887*948e257cSChinmay Rath return true; 888*948e257cSChinmay Rath} 889*948e257cSChinmay Rath 890*948e257cSChinmay Rathstatic bool do_logical1(DisasContext *ctx, arg_X_sa_rc *a, 891*948e257cSChinmay Rath void (*helper)(TCGv, TCGv)) 892*948e257cSChinmay Rath{ 893*948e257cSChinmay Rath helper(cpu_gpr[a->ra], cpu_gpr[a->rs]); 894*948e257cSChinmay Rath if (unlikely(a->rc)) { 895*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 896*948e257cSChinmay Rath } 897*948e257cSChinmay Rath return true; 898*948e257cSChinmay Rath} 899*948e257cSChinmay Rath 900*948e257cSChinmay Rathstatic bool do_logical2(DisasContext *ctx, arg_X_rc *a, 901*948e257cSChinmay Rath void (*helper)(TCGv, TCGv, TCGv)) 902*948e257cSChinmay Rath{ 903*948e257cSChinmay Rath helper(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 904*948e257cSChinmay Rath if (unlikely(a->rc)) { 905*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 906*948e257cSChinmay Rath } 907*948e257cSChinmay Rath return true; 908*948e257cSChinmay Rath} 909*948e257cSChinmay Rath 910*948e257cSChinmay Rathstatic bool trans_OR(DisasContext *ctx, arg_OR *a) 911*948e257cSChinmay Rath{ 912*948e257cSChinmay Rath /* Optimisation for mr. ri case */ 913*948e257cSChinmay Rath if (a->rt != a->ra || a->rt != a->rb) { 914*948e257cSChinmay Rath if (a->rt != a->rb) { 915*948e257cSChinmay Rath tcg_gen_or_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 916*948e257cSChinmay Rath } else { 917*948e257cSChinmay Rath tcg_gen_mov_tl(cpu_gpr[a->ra], cpu_gpr[a->rt]); 918*948e257cSChinmay Rath } 919*948e257cSChinmay Rath if (unlikely(a->rc)) { 920*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 921*948e257cSChinmay Rath } 922*948e257cSChinmay Rath } else if (unlikely(a->rc)) { 923*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->rt]); 924*948e257cSChinmay Rath#if defined(TARGET_PPC64) 925*948e257cSChinmay Rath } else if (a->rt != 0) { /* 0 is nop */ 926*948e257cSChinmay Rath int prio = 0; 927*948e257cSChinmay Rath 928*948e257cSChinmay Rath switch (a->rt) { 929*948e257cSChinmay Rath case 1: 930*948e257cSChinmay Rath /* Set process priority to low */ 931*948e257cSChinmay Rath prio = 2; 932*948e257cSChinmay Rath break; 933*948e257cSChinmay Rath case 6: 934*948e257cSChinmay Rath /* Set process priority to medium-low */ 935*948e257cSChinmay Rath prio = 3; 936*948e257cSChinmay Rath break; 937*948e257cSChinmay Rath case 2: 938*948e257cSChinmay Rath /* Set process priority to normal */ 939*948e257cSChinmay Rath prio = 4; 940*948e257cSChinmay Rath break; 941*948e257cSChinmay Rath#if !defined(CONFIG_USER_ONLY) 942*948e257cSChinmay Rath case 31: 943*948e257cSChinmay Rath if (!ctx->pr) { 944*948e257cSChinmay Rath /* Set process priority to very low */ 945*948e257cSChinmay Rath prio = 1; 946*948e257cSChinmay Rath } 947*948e257cSChinmay Rath break; 948*948e257cSChinmay Rath case 5: 949*948e257cSChinmay Rath if (!ctx->pr) { 950*948e257cSChinmay Rath /* Set process priority to medium-hight */ 951*948e257cSChinmay Rath prio = 5; 952*948e257cSChinmay Rath } 953*948e257cSChinmay Rath break; 954*948e257cSChinmay Rath case 3: 955*948e257cSChinmay Rath if (!ctx->pr) { 956*948e257cSChinmay Rath /* Set process priority to high */ 957*948e257cSChinmay Rath prio = 6; 958*948e257cSChinmay Rath } 959*948e257cSChinmay Rath break; 960*948e257cSChinmay Rath case 7: 961*948e257cSChinmay Rath if (ctx->hv && !ctx->pr) { 962*948e257cSChinmay Rath /* Set process priority to very high */ 963*948e257cSChinmay Rath prio = 7; 964*948e257cSChinmay Rath } 965*948e257cSChinmay Rath break; 966*948e257cSChinmay Rath#endif 967*948e257cSChinmay Rath default: 968*948e257cSChinmay Rath break; 969*948e257cSChinmay Rath } 970*948e257cSChinmay Rath if (prio) { 971*948e257cSChinmay Rath TCGv t0 = tcg_temp_new(); 972*948e257cSChinmay Rath gen_load_spr(t0, SPR_PPR); 973*948e257cSChinmay Rath tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL); 974*948e257cSChinmay Rath tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50); 975*948e257cSChinmay Rath gen_store_spr(SPR_PPR, t0); 976*948e257cSChinmay Rath } 977*948e257cSChinmay Rath#if !defined(CONFIG_USER_ONLY) 978*948e257cSChinmay Rath /* 979*948e257cSChinmay Rath * Pause out of TCG otherwise spin loops with smt_low eat too 980*948e257cSChinmay Rath * much CPU and the kernel hangs. This applies to all 981*948e257cSChinmay Rath * encodings other than no-op, e.g., miso(rs=26), yield(27), 982*948e257cSChinmay Rath * mdoio(29), mdoom(30), and all currently undefined. 983*948e257cSChinmay Rath */ 984*948e257cSChinmay Rath gen_pause(ctx); 985*948e257cSChinmay Rath#endif 986*948e257cSChinmay Rath#endif 987*948e257cSChinmay Rath } 988*948e257cSChinmay Rath 989*948e257cSChinmay Rath return true; 990*948e257cSChinmay Rath} 991*948e257cSChinmay Rath 992*948e257cSChinmay Rathstatic bool trans_XOR(DisasContext *ctx, arg_XOR *a) 993*948e257cSChinmay Rath{ 994*948e257cSChinmay Rath /* Optimisation for "set to zero" case */ 995*948e257cSChinmay Rath if (a->rt != a->rb) { 996*948e257cSChinmay Rath tcg_gen_xor_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 997*948e257cSChinmay Rath } else { 998*948e257cSChinmay Rath tcg_gen_movi_tl(cpu_gpr[a->ra], 0); 999*948e257cSChinmay Rath } 1000*948e257cSChinmay Rath if (unlikely(a->rc)) { 1001*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 1002*948e257cSChinmay Rath } 1003*948e257cSChinmay Rath return true; 1004*948e257cSChinmay Rath} 1005*948e257cSChinmay Rath 1006*948e257cSChinmay Rathstatic bool trans_CMPB(DisasContext *ctx, arg_CMPB *a) 1007*948e257cSChinmay Rath{ 1008*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA205); 1009*948e257cSChinmay Rath gen_helper_CMPB(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 1010*948e257cSChinmay Rath return true; 1011*948e257cSChinmay Rath} 1012*948e257cSChinmay Rath 1013*948e257cSChinmay Rathstatic bool do_cntzw(DisasContext *ctx, arg_X_sa_rc *a, 1014*948e257cSChinmay Rath void (*helper)(TCGv_i32, TCGv_i32, uint32_t)) 1015*948e257cSChinmay Rath{ 1016*948e257cSChinmay Rath TCGv_i32 t = tcg_temp_new_i32(); 1017*948e257cSChinmay Rath 1018*948e257cSChinmay Rath tcg_gen_trunc_tl_i32(t, cpu_gpr[a->rs]); 1019*948e257cSChinmay Rath helper(t, t, 32); 1020*948e257cSChinmay Rath tcg_gen_extu_i32_tl(cpu_gpr[a->ra], t); 1021*948e257cSChinmay Rath 1022*948e257cSChinmay Rath if (unlikely(a->rc)) { 1023*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 1024*948e257cSChinmay Rath } 1025*948e257cSChinmay Rath return true; 1026*948e257cSChinmay Rath} 1027*948e257cSChinmay Rath 1028*948e257cSChinmay Rath#if defined(TARGET_PPC64) 1029*948e257cSChinmay Rathstatic bool do_cntzd(DisasContext *ctx, arg_X_sa_rc *a, 1030*948e257cSChinmay Rath void (*helper)(TCGv_i64, TCGv_i64, uint64_t)) 1031*948e257cSChinmay Rath{ 1032*948e257cSChinmay Rath helper(cpu_gpr[a->ra], cpu_gpr[a->rs], 64); 1033*948e257cSChinmay Rath if (unlikely(a->rc)) { 1034*948e257cSChinmay Rath gen_set_Rc0(ctx, cpu_gpr[a->ra]); 1035*948e257cSChinmay Rath } 1036*948e257cSChinmay Rath return true; 1037*948e257cSChinmay Rath} 1038*948e257cSChinmay Rath#endif 1039*948e257cSChinmay Rath 1040*948e257cSChinmay Rathstatic bool trans_CNTLZD(DisasContext *ctx, arg_CNTLZD *a) 1041*948e257cSChinmay Rath{ 1042*948e257cSChinmay Rath REQUIRE_64BIT(ctx); 1043*948e257cSChinmay Rath#if defined(TARGET_PPC64) 1044*948e257cSChinmay Rath do_cntzd(ctx, a, tcg_gen_clzi_i64); 1045*948e257cSChinmay Rath#else 1046*948e257cSChinmay Rath qemu_build_not_reached(); 1047*948e257cSChinmay Rath#endif 1048*948e257cSChinmay Rath return true; 1049*948e257cSChinmay Rath} 1050*948e257cSChinmay Rath 1051*948e257cSChinmay Rathstatic bool trans_CNTTZD(DisasContext *ctx, arg_CNTTZD *a) 1052*948e257cSChinmay Rath{ 1053*948e257cSChinmay Rath REQUIRE_64BIT(ctx); 1054*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA300); 1055*948e257cSChinmay Rath#if defined(TARGET_PPC64) 1056*948e257cSChinmay Rath do_cntzd(ctx, a, tcg_gen_ctzi_i64); 1057*948e257cSChinmay Rath#else 1058*948e257cSChinmay Rath qemu_build_not_reached(); 1059*948e257cSChinmay Rath#endif 1060*948e257cSChinmay Rath return true; 1061*948e257cSChinmay Rath} 1062*948e257cSChinmay Rath 1063*948e257cSChinmay Rathstatic bool trans_POPCNTB(DisasContext *ctx, arg_POPCNTB *a) 1064*948e257cSChinmay Rath{ 1065*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS(ctx, POPCNTB); 1066*948e257cSChinmay Rath gen_helper_POPCNTB(cpu_gpr[a->ra], cpu_gpr[a->rs]); 1067*948e257cSChinmay Rath return true; 1068*948e257cSChinmay Rath} 1069*948e257cSChinmay Rath 1070*948e257cSChinmay Rathstatic bool trans_POPCNTW(DisasContext *ctx, arg_POPCNTW *a) 1071*948e257cSChinmay Rath{ 1072*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS(ctx, POPCNTWD); 1073*948e257cSChinmay Rath#if defined(TARGET_PPC64) 1074*948e257cSChinmay Rath gen_helper_POPCNTW(cpu_gpr[a->ra], cpu_gpr[a->rs]); 1075*948e257cSChinmay Rath#else 1076*948e257cSChinmay Rath tcg_gen_ctpop_i32(cpu_gpr[a->ra], cpu_gpr[a->rs]); 1077*948e257cSChinmay Rath#endif 1078*948e257cSChinmay Rath return true; 1079*948e257cSChinmay Rath} 1080*948e257cSChinmay Rath 1081*948e257cSChinmay Rathstatic bool trans_POPCNTD(DisasContext *ctx, arg_POPCNTD *a) 1082*948e257cSChinmay Rath{ 1083*948e257cSChinmay Rath REQUIRE_64BIT(ctx); 1084*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS(ctx, POPCNTWD); 1085*948e257cSChinmay Rath#if defined(TARGET_PPC64) 1086*948e257cSChinmay Rath tcg_gen_ctpop_i64(cpu_gpr[a->ra], cpu_gpr[a->rs]); 1087*948e257cSChinmay Rath#else 1088*948e257cSChinmay Rath qemu_build_not_reached(); 1089*948e257cSChinmay Rath#endif 1090*948e257cSChinmay Rath return true; 1091*948e257cSChinmay Rath} 1092*948e257cSChinmay Rath 1093*948e257cSChinmay Rathstatic bool trans_PRTYW(DisasContext *ctx, arg_PRTYW *a) 1094*948e257cSChinmay Rath{ 1095*948e257cSChinmay Rath TCGv ra = cpu_gpr[a->ra]; 1096*948e257cSChinmay Rath TCGv rs = cpu_gpr[a->rs]; 1097*948e257cSChinmay Rath TCGv t0 = tcg_temp_new(); 1098*948e257cSChinmay Rath 1099*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA205); 1100*948e257cSChinmay Rath tcg_gen_shri_tl(t0, rs, 16); 1101*948e257cSChinmay Rath tcg_gen_xor_tl(ra, rs, t0); 1102*948e257cSChinmay Rath tcg_gen_shri_tl(t0, ra, 8); 1103*948e257cSChinmay Rath tcg_gen_xor_tl(ra, ra, t0); 1104*948e257cSChinmay Rath tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL); 1105*948e257cSChinmay Rath return true; 1106*948e257cSChinmay Rath} 1107*948e257cSChinmay Rath 1108*948e257cSChinmay Rathstatic bool trans_PRTYD(DisasContext *ctx, arg_PRTYD *a) 1109*948e257cSChinmay Rath{ 1110*948e257cSChinmay Rath TCGv ra = cpu_gpr[a->ra]; 1111*948e257cSChinmay Rath TCGv rs = cpu_gpr[a->rs]; 1112*948e257cSChinmay Rath TCGv t0 = tcg_temp_new(); 1113*948e257cSChinmay Rath 1114*948e257cSChinmay Rath REQUIRE_64BIT(ctx); 1115*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, ISA205); 1116*948e257cSChinmay Rath tcg_gen_shri_tl(t0, rs, 32); 1117*948e257cSChinmay Rath tcg_gen_xor_tl(ra, rs, t0); 1118*948e257cSChinmay Rath tcg_gen_shri_tl(t0, ra, 16); 1119*948e257cSChinmay Rath tcg_gen_xor_tl(ra, ra, t0); 1120*948e257cSChinmay Rath tcg_gen_shri_tl(t0, ra, 8); 1121*948e257cSChinmay Rath tcg_gen_xor_tl(ra, ra, t0); 1122*948e257cSChinmay Rath tcg_gen_andi_tl(ra, ra, 1); 1123*948e257cSChinmay Rath return true; 1124*948e257cSChinmay Rath} 1125*948e257cSChinmay Rath 1126*948e257cSChinmay Rathstatic bool trans_BPERMD(DisasContext *ctx, arg_BPERMD *a) 1127*948e257cSChinmay Rath{ 1128*948e257cSChinmay Rath REQUIRE_64BIT(ctx); 1129*948e257cSChinmay Rath REQUIRE_INSNS_FLAGS2(ctx, PERM_ISA206); 1130*948e257cSChinmay Rath#if defined(TARGET_PPC64) 1131*948e257cSChinmay Rath gen_helper_BPERMD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 1132*948e257cSChinmay Rath#else 1133*948e257cSChinmay Rath qemu_build_not_reached(); 1134*948e257cSChinmay Rath#endif 1135*948e257cSChinmay Rath return true; 1136*948e257cSChinmay Rath} 1137*948e257cSChinmay Rath 113889ccd7dcSMatheus Ferststatic bool trans_CFUGED(DisasContext *ctx, arg_X *a) 113989ccd7dcSMatheus Ferst{ 114089ccd7dcSMatheus Ferst REQUIRE_64BIT(ctx); 114189ccd7dcSMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, ISA310); 114289ccd7dcSMatheus Ferst#if defined(TARGET_PPC64) 11436e0bbc40SMatheus Ferst gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 114489ccd7dcSMatheus Ferst#else 114589ccd7dcSMatheus Ferst qemu_build_not_reached(); 114689ccd7dcSMatheus Ferst#endif 114789ccd7dcSMatheus Ferst return true; 114889ccd7dcSMatheus Ferst} 114982be6e02SLuis Pires 1150a2c975e1SMatheus Ferststatic void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail) 115182be6e02SLuis Pires{ 1152ab1e25adSMatheus Ferst TCGv_i64 t0, t1; 115382be6e02SLuis Pires 1154ab1e25adSMatheus Ferst t0 = tcg_temp_new_i64(); 1155ab1e25adSMatheus Ferst t1 = tcg_temp_new_i64(); 115682be6e02SLuis Pires 1157ab1e25adSMatheus Ferst tcg_gen_and_i64(t0, src, mask); 1158f356b3baSLuis Pires if (trail) { 1159ab1e25adSMatheus Ferst tcg_gen_ctzi_i64(t0, t0, -1); 1160f356b3baSLuis Pires } else { 1161ab1e25adSMatheus Ferst tcg_gen_clzi_i64(t0, t0, -1); 1162f356b3baSLuis Pires } 116382be6e02SLuis Pires 1164ab1e25adSMatheus Ferst tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1); 1165ab1e25adSMatheus Ferst tcg_gen_andi_i64(t0, t0, 63); 1166ab1e25adSMatheus Ferst tcg_gen_xori_i64(t0, t0, 63); 1167f356b3baSLuis Pires if (trail) { 1168ab1e25adSMatheus Ferst tcg_gen_shl_i64(t0, mask, t0); 1169ab1e25adSMatheus Ferst tcg_gen_shl_i64(t0, t0, t1); 1170f356b3baSLuis Pires } else { 1171ab1e25adSMatheus Ferst tcg_gen_shr_i64(t0, mask, t0); 1172ab1e25adSMatheus Ferst tcg_gen_shr_i64(t0, t0, t1); 1173f356b3baSLuis Pires } 117482be6e02SLuis Pires 1175ab1e25adSMatheus Ferst tcg_gen_ctpop_i64(dst, t0); 117682be6e02SLuis Pires} 117782be6e02SLuis Pires 117882be6e02SLuis Piresstatic bool trans_CNTLZDM(DisasContext *ctx, arg_X *a) 117982be6e02SLuis Pires{ 118082be6e02SLuis Pires REQUIRE_64BIT(ctx); 118182be6e02SLuis Pires REQUIRE_INSNS_FLAGS2(ctx, ISA310); 118282be6e02SLuis Pires#if defined(TARGET_PPC64) 1183f356b3baSLuis Pires do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false); 1184f356b3baSLuis Pires#else 1185f356b3baSLuis Pires qemu_build_not_reached(); 1186f356b3baSLuis Pires#endif 1187f356b3baSLuis Pires return true; 1188f356b3baSLuis Pires} 1189f356b3baSLuis Pires 1190f356b3baSLuis Piresstatic bool trans_CNTTZDM(DisasContext *ctx, arg_X *a) 1191f356b3baSLuis Pires{ 1192f356b3baSLuis Pires REQUIRE_64BIT(ctx); 1193f356b3baSLuis Pires REQUIRE_INSNS_FLAGS2(ctx, ISA310); 1194f356b3baSLuis Pires#if defined(TARGET_PPC64) 1195f356b3baSLuis Pires do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true); 119682be6e02SLuis Pires#else 119782be6e02SLuis Pires qemu_build_not_reached(); 119882be6e02SLuis Pires#endif 119982be6e02SLuis Pires return true; 120082be6e02SLuis Pires} 120121ba6e58SMatheus Ferst 120221ba6e58SMatheus Ferststatic bool trans_PDEPD(DisasContext *ctx, arg_X *a) 120321ba6e58SMatheus Ferst{ 120421ba6e58SMatheus Ferst REQUIRE_64BIT(ctx); 120521ba6e58SMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, ISA310); 120621ba6e58SMatheus Ferst#if defined(TARGET_PPC64) 120721ba6e58SMatheus Ferst gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 120821ba6e58SMatheus Ferst#else 120921ba6e58SMatheus Ferst qemu_build_not_reached(); 121021ba6e58SMatheus Ferst#endif 121121ba6e58SMatheus Ferst return true; 121221ba6e58SMatheus Ferst} 12138bdb7606SMatheus Ferst 12148bdb7606SMatheus Ferststatic bool trans_PEXTD(DisasContext *ctx, arg_X *a) 12158bdb7606SMatheus Ferst{ 12168bdb7606SMatheus Ferst REQUIRE_64BIT(ctx); 12178bdb7606SMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, ISA310); 12188bdb7606SMatheus Ferst#if defined(TARGET_PPC64) 12198bdb7606SMatheus Ferst gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]); 12208bdb7606SMatheus Ferst#else 12218bdb7606SMatheus Ferst qemu_build_not_reached(); 12228bdb7606SMatheus Ferst#endif 12238bdb7606SMatheus Ferst return true; 12248bdb7606SMatheus Ferst} 12256addef4dSMatheus Ferst 1226*948e257cSChinmay RathTRANS(ANDI_, do_addi_, false); 1227*948e257cSChinmay RathTRANS(ANDIS_, do_addi_, true); 1228*948e257cSChinmay RathTRANS(ORI, do_ori, false); 1229*948e257cSChinmay RathTRANS(ORIS, do_ori, true); 1230*948e257cSChinmay RathTRANS(XORI, do_xori, false); 1231*948e257cSChinmay RathTRANS(XORIS, do_xori, true); 1232*948e257cSChinmay Rath 1233*948e257cSChinmay RathTRANS(AND, do_logical2, tcg_gen_and_tl); 1234*948e257cSChinmay RathTRANS(ANDC, do_logical2, tcg_gen_andc_tl); 1235*948e257cSChinmay RathTRANS(NAND, do_logical2, tcg_gen_nand_tl); 1236*948e257cSChinmay RathTRANS(ORC, do_logical2, tcg_gen_orc_tl); 1237*948e257cSChinmay RathTRANS(NOR, do_logical2, tcg_gen_nor_tl); 1238*948e257cSChinmay RathTRANS(EQV, do_logical2, tcg_gen_eqv_tl); 1239*948e257cSChinmay RathTRANS(EXTSB, do_logical1, tcg_gen_ext8s_tl); 1240*948e257cSChinmay RathTRANS(EXTSH, do_logical1, tcg_gen_ext16s_tl); 1241*948e257cSChinmay Rath 1242*948e257cSChinmay RathTRANS(CNTLZW, do_cntzw, tcg_gen_clzi_i32); 1243*948e257cSChinmay RathTRANS_FLAGS2(ISA300, CNTTZW, do_cntzw, tcg_gen_ctzi_i32); 1244*948e257cSChinmay Rath 1245*948e257cSChinmay RathTRANS64(EXTSW, do_logical1, tcg_gen_ext32s_tl); 1246*948e257cSChinmay Rath 12476addef4dSMatheus Ferststatic bool trans_ADDG6S(DisasContext *ctx, arg_X *a) 12486addef4dSMatheus Ferst{ 12494fe0e9dbSRichard Henderson const target_ulong carry_bits = (target_ulong)-1 / 0xf; 12504fe0e9dbSRichard Henderson TCGv in1, in2, carryl, carryh, tmp; 12514fe0e9dbSRichard Henderson TCGv zero = tcg_constant_tl(0); 12526addef4dSMatheus Ferst 12536addef4dSMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206); 12546addef4dSMatheus Ferst 12554fe0e9dbSRichard Henderson in1 = cpu_gpr[a->ra]; 12564fe0e9dbSRichard Henderson in2 = cpu_gpr[a->rb]; 12574fe0e9dbSRichard Henderson tmp = tcg_temp_new(); 12584fe0e9dbSRichard Henderson carryl = tcg_temp_new(); 12594fe0e9dbSRichard Henderson carryh = tcg_temp_new(); 12606addef4dSMatheus Ferst 12614fe0e9dbSRichard Henderson /* Addition with carry. */ 12624fe0e9dbSRichard Henderson tcg_gen_add2_tl(carryl, carryh, in1, zero, in2, zero); 12634fe0e9dbSRichard Henderson /* Addition without carry. */ 12644fe0e9dbSRichard Henderson tcg_gen_xor_tl(tmp, in1, in2); 12654fe0e9dbSRichard Henderson /* Difference between the two is carry in to each bit. */ 12664fe0e9dbSRichard Henderson tcg_gen_xor_tl(carryl, carryl, tmp); 12676addef4dSMatheus Ferst 12684fe0e9dbSRichard Henderson /* 12694fe0e9dbSRichard Henderson * The carry-out that we're looking for is the carry-in to 12704fe0e9dbSRichard Henderson * the next nibble. Shift the double-word down one nibble, 12714fe0e9dbSRichard Henderson * which puts all of the bits back into one word. 12724fe0e9dbSRichard Henderson */ 12734fe0e9dbSRichard Henderson tcg_gen_extract2_tl(carryl, carryl, carryh, 4); 12746addef4dSMatheus Ferst 12754fe0e9dbSRichard Henderson /* Invert, isolate the carry bits, and produce 6's. */ 12764fe0e9dbSRichard Henderson tcg_gen_andc_tl(carryl, tcg_constant_tl(carry_bits), carryl); 12774fe0e9dbSRichard Henderson tcg_gen_muli_tl(cpu_gpr[a->rt], carryl, 6); 12786addef4dSMatheus Ferst return true; 12796addef4dSMatheus Ferst} 128038d3690bSMatheus Ferst 12816b924d4aSMatheus Ferststatic bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a) 12826b924d4aSMatheus Ferst{ 12836b924d4aSMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206); 12846b924d4aSMatheus Ferst gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]); 12856b924d4aSMatheus Ferst return true; 12866b924d4aSMatheus Ferst} 12876b924d4aSMatheus Ferst 128838d3690bSMatheus Ferststatic bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a) 128938d3690bSMatheus Ferst{ 129038d3690bSMatheus Ferst REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206); 129138d3690bSMatheus Ferst gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]); 129238d3690bSMatheus Ferst return true; 129338d3690bSMatheus Ferst} 1294670f1da3SVíctor Colombo 1295670f1da3SVíctor Colombostatic bool do_hash(DisasContext *ctx, arg_X *a, bool priv, 1296670f1da3SVíctor Colombo void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv)) 1297670f1da3SVíctor Colombo{ 1298670f1da3SVíctor Colombo TCGv ea; 1299670f1da3SVíctor Colombo 1300670f1da3SVíctor Colombo if (!(ctx->insns_flags2 & PPC2_ISA310)) { 1301670f1da3SVíctor Colombo /* if version is before v3.1, this operation is a nop */ 1302670f1da3SVíctor Colombo return true; 1303670f1da3SVíctor Colombo } 1304670f1da3SVíctor Colombo 1305670f1da3SVíctor Colombo if (priv) { 1306670f1da3SVíctor Colombo /* if instruction is privileged but the context is in user space */ 1307670f1da3SVíctor Colombo REQUIRE_SV(ctx); 1308670f1da3SVíctor Colombo } 1309670f1da3SVíctor Colombo 1310670f1da3SVíctor Colombo if (unlikely(a->ra == 0)) { 1311670f1da3SVíctor Colombo /* if RA=0, the instruction form is invalid */ 1312670f1da3SVíctor Colombo gen_invalid(ctx); 1313670f1da3SVíctor Colombo return true; 1314670f1da3SVíctor Colombo } 1315670f1da3SVíctor Colombo 1316670f1da3SVíctor Colombo ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt)); 1317ad75a51eSRichard Henderson helper(tcg_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]); 1318670f1da3SVíctor Colombo return true; 1319670f1da3SVíctor Colombo} 1320670f1da3SVíctor Colombo 1321670f1da3SVíctor ColomboTRANS(HASHST, do_hash, false, gen_helper_HASHST) 1322670f1da3SVíctor ColomboTRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK) 132353ae2aebSVíctor ColomboTRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP) 132453ae2aebSVíctor ColomboTRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP) 1325