1*fcf5ef2aSThomas Huth /* 2*fcf5ef2aSThomas Huth * PowerPC emulation for qemu: main translation routines. 3*fcf5ef2aSThomas Huth * 4*fcf5ef2aSThomas Huth * Copyright (c) 2003-2007 Jocelyn Mayer 5*fcf5ef2aSThomas Huth * Copyright (C) 2011 Freescale Semiconductor, Inc. 6*fcf5ef2aSThomas Huth * 7*fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 8*fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 9*fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 10*fcf5ef2aSThomas Huth * version 2 of the License, or (at your option) any later version. 11*fcf5ef2aSThomas Huth * 12*fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 13*fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*fcf5ef2aSThomas Huth * Lesser General Public License for more details. 16*fcf5ef2aSThomas Huth * 17*fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 18*fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19*fcf5ef2aSThomas Huth */ 20*fcf5ef2aSThomas Huth 21*fcf5ef2aSThomas Huth #include "qemu/osdep.h" 22*fcf5ef2aSThomas Huth #include "cpu.h" 23*fcf5ef2aSThomas Huth #include "internal.h" 24*fcf5ef2aSThomas Huth #include "disas/disas.h" 25*fcf5ef2aSThomas Huth #include "exec/exec-all.h" 26*fcf5ef2aSThomas Huth #include "tcg-op.h" 27*fcf5ef2aSThomas Huth #include "qemu/host-utils.h" 28*fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h" 29*fcf5ef2aSThomas Huth 30*fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 31*fcf5ef2aSThomas Huth #include "exec/helper-gen.h" 32*fcf5ef2aSThomas Huth 33*fcf5ef2aSThomas Huth #include "trace-tcg.h" 34*fcf5ef2aSThomas Huth #include "exec/log.h" 35*fcf5ef2aSThomas Huth 36*fcf5ef2aSThomas Huth 37*fcf5ef2aSThomas Huth #define CPU_SINGLE_STEP 0x1 38*fcf5ef2aSThomas Huth #define CPU_BRANCH_STEP 0x2 39*fcf5ef2aSThomas Huth #define GDBSTUB_SINGLE_STEP 0x4 40*fcf5ef2aSThomas Huth 41*fcf5ef2aSThomas Huth /* Include definitions for instructions classes and implementations flags */ 42*fcf5ef2aSThomas Huth //#define PPC_DEBUG_DISAS 43*fcf5ef2aSThomas Huth //#define DO_PPC_STATISTICS 44*fcf5ef2aSThomas Huth 45*fcf5ef2aSThomas Huth #ifdef PPC_DEBUG_DISAS 46*fcf5ef2aSThomas Huth # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) 47*fcf5ef2aSThomas Huth #else 48*fcf5ef2aSThomas Huth # define LOG_DISAS(...) do { } while (0) 49*fcf5ef2aSThomas Huth #endif 50*fcf5ef2aSThomas Huth /*****************************************************************************/ 51*fcf5ef2aSThomas Huth /* Code translation helpers */ 52*fcf5ef2aSThomas Huth 53*fcf5ef2aSThomas Huth /* global register indexes */ 54*fcf5ef2aSThomas Huth static TCGv_env cpu_env; 55*fcf5ef2aSThomas Huth static char cpu_reg_names[10*3 + 22*4 /* GPR */ 56*fcf5ef2aSThomas Huth + 10*4 + 22*5 /* SPE GPRh */ 57*fcf5ef2aSThomas Huth + 10*4 + 22*5 /* FPR */ 58*fcf5ef2aSThomas Huth + 2*(10*6 + 22*7) /* AVRh, AVRl */ 59*fcf5ef2aSThomas Huth + 10*5 + 22*6 /* VSR */ 60*fcf5ef2aSThomas Huth + 8*5 /* CRF */]; 61*fcf5ef2aSThomas Huth static TCGv cpu_gpr[32]; 62*fcf5ef2aSThomas Huth static TCGv cpu_gprh[32]; 63*fcf5ef2aSThomas Huth static TCGv_i64 cpu_fpr[32]; 64*fcf5ef2aSThomas Huth static TCGv_i64 cpu_avrh[32], cpu_avrl[32]; 65*fcf5ef2aSThomas Huth static TCGv_i64 cpu_vsr[32]; 66*fcf5ef2aSThomas Huth static TCGv_i32 cpu_crf[8]; 67*fcf5ef2aSThomas Huth static TCGv cpu_nip; 68*fcf5ef2aSThomas Huth static TCGv cpu_msr; 69*fcf5ef2aSThomas Huth static TCGv cpu_ctr; 70*fcf5ef2aSThomas Huth static TCGv cpu_lr; 71*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 72*fcf5ef2aSThomas Huth static TCGv cpu_cfar; 73*fcf5ef2aSThomas Huth #endif 74*fcf5ef2aSThomas Huth static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca; 75*fcf5ef2aSThomas Huth static TCGv cpu_reserve; 76*fcf5ef2aSThomas Huth static TCGv cpu_fpscr; 77*fcf5ef2aSThomas Huth static TCGv_i32 cpu_access_type; 78*fcf5ef2aSThomas Huth 79*fcf5ef2aSThomas Huth #include "exec/gen-icount.h" 80*fcf5ef2aSThomas Huth 81*fcf5ef2aSThomas Huth void ppc_translate_init(void) 82*fcf5ef2aSThomas Huth { 83*fcf5ef2aSThomas Huth int i; 84*fcf5ef2aSThomas Huth char* p; 85*fcf5ef2aSThomas Huth size_t cpu_reg_names_size; 86*fcf5ef2aSThomas Huth static int done_init = 0; 87*fcf5ef2aSThomas Huth 88*fcf5ef2aSThomas Huth if (done_init) 89*fcf5ef2aSThomas Huth return; 90*fcf5ef2aSThomas Huth 91*fcf5ef2aSThomas Huth cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 92*fcf5ef2aSThomas Huth tcg_ctx.tcg_env = cpu_env; 93*fcf5ef2aSThomas Huth 94*fcf5ef2aSThomas Huth p = cpu_reg_names; 95*fcf5ef2aSThomas Huth cpu_reg_names_size = sizeof(cpu_reg_names); 96*fcf5ef2aSThomas Huth 97*fcf5ef2aSThomas Huth for (i = 0; i < 8; i++) { 98*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "crf%d", i); 99*fcf5ef2aSThomas Huth cpu_crf[i] = tcg_global_mem_new_i32(cpu_env, 100*fcf5ef2aSThomas Huth offsetof(CPUPPCState, crf[i]), p); 101*fcf5ef2aSThomas Huth p += 5; 102*fcf5ef2aSThomas Huth cpu_reg_names_size -= 5; 103*fcf5ef2aSThomas Huth } 104*fcf5ef2aSThomas Huth 105*fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 106*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "r%d", i); 107*fcf5ef2aSThomas Huth cpu_gpr[i] = tcg_global_mem_new(cpu_env, 108*fcf5ef2aSThomas Huth offsetof(CPUPPCState, gpr[i]), p); 109*fcf5ef2aSThomas Huth p += (i < 10) ? 3 : 4; 110*fcf5ef2aSThomas Huth cpu_reg_names_size -= (i < 10) ? 3 : 4; 111*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "r%dH", i); 112*fcf5ef2aSThomas Huth cpu_gprh[i] = tcg_global_mem_new(cpu_env, 113*fcf5ef2aSThomas Huth offsetof(CPUPPCState, gprh[i]), p); 114*fcf5ef2aSThomas Huth p += (i < 10) ? 4 : 5; 115*fcf5ef2aSThomas Huth cpu_reg_names_size -= (i < 10) ? 4 : 5; 116*fcf5ef2aSThomas Huth 117*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "fp%d", i); 118*fcf5ef2aSThomas Huth cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env, 119*fcf5ef2aSThomas Huth offsetof(CPUPPCState, fpr[i]), p); 120*fcf5ef2aSThomas Huth p += (i < 10) ? 4 : 5; 121*fcf5ef2aSThomas Huth cpu_reg_names_size -= (i < 10) ? 4 : 5; 122*fcf5ef2aSThomas Huth 123*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "avr%dH", i); 124*fcf5ef2aSThomas Huth #ifdef HOST_WORDS_BIGENDIAN 125*fcf5ef2aSThomas Huth cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env, 126*fcf5ef2aSThomas Huth offsetof(CPUPPCState, avr[i].u64[0]), p); 127*fcf5ef2aSThomas Huth #else 128*fcf5ef2aSThomas Huth cpu_avrh[i] = tcg_global_mem_new_i64(cpu_env, 129*fcf5ef2aSThomas Huth offsetof(CPUPPCState, avr[i].u64[1]), p); 130*fcf5ef2aSThomas Huth #endif 131*fcf5ef2aSThomas Huth p += (i < 10) ? 6 : 7; 132*fcf5ef2aSThomas Huth cpu_reg_names_size -= (i < 10) ? 6 : 7; 133*fcf5ef2aSThomas Huth 134*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "avr%dL", i); 135*fcf5ef2aSThomas Huth #ifdef HOST_WORDS_BIGENDIAN 136*fcf5ef2aSThomas Huth cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env, 137*fcf5ef2aSThomas Huth offsetof(CPUPPCState, avr[i].u64[1]), p); 138*fcf5ef2aSThomas Huth #else 139*fcf5ef2aSThomas Huth cpu_avrl[i] = tcg_global_mem_new_i64(cpu_env, 140*fcf5ef2aSThomas Huth offsetof(CPUPPCState, avr[i].u64[0]), p); 141*fcf5ef2aSThomas Huth #endif 142*fcf5ef2aSThomas Huth p += (i < 10) ? 6 : 7; 143*fcf5ef2aSThomas Huth cpu_reg_names_size -= (i < 10) ? 6 : 7; 144*fcf5ef2aSThomas Huth snprintf(p, cpu_reg_names_size, "vsr%d", i); 145*fcf5ef2aSThomas Huth cpu_vsr[i] = tcg_global_mem_new_i64(cpu_env, 146*fcf5ef2aSThomas Huth offsetof(CPUPPCState, vsr[i]), p); 147*fcf5ef2aSThomas Huth p += (i < 10) ? 5 : 6; 148*fcf5ef2aSThomas Huth cpu_reg_names_size -= (i < 10) ? 5 : 6; 149*fcf5ef2aSThomas Huth } 150*fcf5ef2aSThomas Huth 151*fcf5ef2aSThomas Huth cpu_nip = tcg_global_mem_new(cpu_env, 152*fcf5ef2aSThomas Huth offsetof(CPUPPCState, nip), "nip"); 153*fcf5ef2aSThomas Huth 154*fcf5ef2aSThomas Huth cpu_msr = tcg_global_mem_new(cpu_env, 155*fcf5ef2aSThomas Huth offsetof(CPUPPCState, msr), "msr"); 156*fcf5ef2aSThomas Huth 157*fcf5ef2aSThomas Huth cpu_ctr = tcg_global_mem_new(cpu_env, 158*fcf5ef2aSThomas Huth offsetof(CPUPPCState, ctr), "ctr"); 159*fcf5ef2aSThomas Huth 160*fcf5ef2aSThomas Huth cpu_lr = tcg_global_mem_new(cpu_env, 161*fcf5ef2aSThomas Huth offsetof(CPUPPCState, lr), "lr"); 162*fcf5ef2aSThomas Huth 163*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 164*fcf5ef2aSThomas Huth cpu_cfar = tcg_global_mem_new(cpu_env, 165*fcf5ef2aSThomas Huth offsetof(CPUPPCState, cfar), "cfar"); 166*fcf5ef2aSThomas Huth #endif 167*fcf5ef2aSThomas Huth 168*fcf5ef2aSThomas Huth cpu_xer = tcg_global_mem_new(cpu_env, 169*fcf5ef2aSThomas Huth offsetof(CPUPPCState, xer), "xer"); 170*fcf5ef2aSThomas Huth cpu_so = tcg_global_mem_new(cpu_env, 171*fcf5ef2aSThomas Huth offsetof(CPUPPCState, so), "SO"); 172*fcf5ef2aSThomas Huth cpu_ov = tcg_global_mem_new(cpu_env, 173*fcf5ef2aSThomas Huth offsetof(CPUPPCState, ov), "OV"); 174*fcf5ef2aSThomas Huth cpu_ca = tcg_global_mem_new(cpu_env, 175*fcf5ef2aSThomas Huth offsetof(CPUPPCState, ca), "CA"); 176*fcf5ef2aSThomas Huth 177*fcf5ef2aSThomas Huth cpu_reserve = tcg_global_mem_new(cpu_env, 178*fcf5ef2aSThomas Huth offsetof(CPUPPCState, reserve_addr), 179*fcf5ef2aSThomas Huth "reserve_addr"); 180*fcf5ef2aSThomas Huth 181*fcf5ef2aSThomas Huth cpu_fpscr = tcg_global_mem_new(cpu_env, 182*fcf5ef2aSThomas Huth offsetof(CPUPPCState, fpscr), "fpscr"); 183*fcf5ef2aSThomas Huth 184*fcf5ef2aSThomas Huth cpu_access_type = tcg_global_mem_new_i32(cpu_env, 185*fcf5ef2aSThomas Huth offsetof(CPUPPCState, access_type), "access_type"); 186*fcf5ef2aSThomas Huth 187*fcf5ef2aSThomas Huth done_init = 1; 188*fcf5ef2aSThomas Huth } 189*fcf5ef2aSThomas Huth 190*fcf5ef2aSThomas Huth /* internal defines */ 191*fcf5ef2aSThomas Huth struct DisasContext { 192*fcf5ef2aSThomas Huth struct TranslationBlock *tb; 193*fcf5ef2aSThomas Huth target_ulong nip; 194*fcf5ef2aSThomas Huth uint32_t opcode; 195*fcf5ef2aSThomas Huth uint32_t exception; 196*fcf5ef2aSThomas Huth /* Routine used to access memory */ 197*fcf5ef2aSThomas Huth bool pr, hv, dr, le_mode; 198*fcf5ef2aSThomas Huth bool lazy_tlb_flush; 199*fcf5ef2aSThomas Huth bool need_access_type; 200*fcf5ef2aSThomas Huth int mem_idx; 201*fcf5ef2aSThomas Huth int access_type; 202*fcf5ef2aSThomas Huth /* Translation flags */ 203*fcf5ef2aSThomas Huth TCGMemOp default_tcg_memop_mask; 204*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 205*fcf5ef2aSThomas Huth bool sf_mode; 206*fcf5ef2aSThomas Huth bool has_cfar; 207*fcf5ef2aSThomas Huth #endif 208*fcf5ef2aSThomas Huth bool fpu_enabled; 209*fcf5ef2aSThomas Huth bool altivec_enabled; 210*fcf5ef2aSThomas Huth bool vsx_enabled; 211*fcf5ef2aSThomas Huth bool spe_enabled; 212*fcf5ef2aSThomas Huth bool tm_enabled; 213*fcf5ef2aSThomas Huth ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ 214*fcf5ef2aSThomas Huth int singlestep_enabled; 215*fcf5ef2aSThomas Huth uint64_t insns_flags; 216*fcf5ef2aSThomas Huth uint64_t insns_flags2; 217*fcf5ef2aSThomas Huth }; 218*fcf5ef2aSThomas Huth 219*fcf5ef2aSThomas Huth /* Return true iff byteswap is needed in a scalar memop */ 220*fcf5ef2aSThomas Huth static inline bool need_byteswap(const DisasContext *ctx) 221*fcf5ef2aSThomas Huth { 222*fcf5ef2aSThomas Huth #if defined(TARGET_WORDS_BIGENDIAN) 223*fcf5ef2aSThomas Huth return ctx->le_mode; 224*fcf5ef2aSThomas Huth #else 225*fcf5ef2aSThomas Huth return !ctx->le_mode; 226*fcf5ef2aSThomas Huth #endif 227*fcf5ef2aSThomas Huth } 228*fcf5ef2aSThomas Huth 229*fcf5ef2aSThomas Huth /* True when active word size < size of target_long. */ 230*fcf5ef2aSThomas Huth #ifdef TARGET_PPC64 231*fcf5ef2aSThomas Huth # define NARROW_MODE(C) (!(C)->sf_mode) 232*fcf5ef2aSThomas Huth #else 233*fcf5ef2aSThomas Huth # define NARROW_MODE(C) 0 234*fcf5ef2aSThomas Huth #endif 235*fcf5ef2aSThomas Huth 236*fcf5ef2aSThomas Huth struct opc_handler_t { 237*fcf5ef2aSThomas Huth /* invalid bits for instruction 1 (Rc(opcode) == 0) */ 238*fcf5ef2aSThomas Huth uint32_t inval1; 239*fcf5ef2aSThomas Huth /* invalid bits for instruction 2 (Rc(opcode) == 1) */ 240*fcf5ef2aSThomas Huth uint32_t inval2; 241*fcf5ef2aSThomas Huth /* instruction type */ 242*fcf5ef2aSThomas Huth uint64_t type; 243*fcf5ef2aSThomas Huth /* extended instruction type */ 244*fcf5ef2aSThomas Huth uint64_t type2; 245*fcf5ef2aSThomas Huth /* handler */ 246*fcf5ef2aSThomas Huth void (*handler)(DisasContext *ctx); 247*fcf5ef2aSThomas Huth #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU) 248*fcf5ef2aSThomas Huth const char *oname; 249*fcf5ef2aSThomas Huth #endif 250*fcf5ef2aSThomas Huth #if defined(DO_PPC_STATISTICS) 251*fcf5ef2aSThomas Huth uint64_t count; 252*fcf5ef2aSThomas Huth #endif 253*fcf5ef2aSThomas Huth }; 254*fcf5ef2aSThomas Huth 255*fcf5ef2aSThomas Huth static inline void gen_set_access_type(DisasContext *ctx, int access_type) 256*fcf5ef2aSThomas Huth { 257*fcf5ef2aSThomas Huth if (ctx->need_access_type && ctx->access_type != access_type) { 258*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_access_type, access_type); 259*fcf5ef2aSThomas Huth ctx->access_type = access_type; 260*fcf5ef2aSThomas Huth } 261*fcf5ef2aSThomas Huth } 262*fcf5ef2aSThomas Huth 263*fcf5ef2aSThomas Huth static inline void gen_update_nip(DisasContext *ctx, target_ulong nip) 264*fcf5ef2aSThomas Huth { 265*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 266*fcf5ef2aSThomas Huth nip = (uint32_t)nip; 267*fcf5ef2aSThomas Huth } 268*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_nip, nip); 269*fcf5ef2aSThomas Huth } 270*fcf5ef2aSThomas Huth 271*fcf5ef2aSThomas Huth static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error) 272*fcf5ef2aSThomas Huth { 273*fcf5ef2aSThomas Huth TCGv_i32 t0, t1; 274*fcf5ef2aSThomas Huth 275*fcf5ef2aSThomas Huth /* These are all synchronous exceptions, we set the PC back to 276*fcf5ef2aSThomas Huth * the faulting instruction 277*fcf5ef2aSThomas Huth */ 278*fcf5ef2aSThomas Huth if (ctx->exception == POWERPC_EXCP_NONE) { 279*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip - 4); 280*fcf5ef2aSThomas Huth } 281*fcf5ef2aSThomas Huth t0 = tcg_const_i32(excp); 282*fcf5ef2aSThomas Huth t1 = tcg_const_i32(error); 283*fcf5ef2aSThomas Huth gen_helper_raise_exception_err(cpu_env, t0, t1); 284*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 285*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 286*fcf5ef2aSThomas Huth ctx->exception = (excp); 287*fcf5ef2aSThomas Huth } 288*fcf5ef2aSThomas Huth 289*fcf5ef2aSThomas Huth static void gen_exception(DisasContext *ctx, uint32_t excp) 290*fcf5ef2aSThomas Huth { 291*fcf5ef2aSThomas Huth TCGv_i32 t0; 292*fcf5ef2aSThomas Huth 293*fcf5ef2aSThomas Huth /* These are all synchronous exceptions, we set the PC back to 294*fcf5ef2aSThomas Huth * the faulting instruction 295*fcf5ef2aSThomas Huth */ 296*fcf5ef2aSThomas Huth if (ctx->exception == POWERPC_EXCP_NONE) { 297*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip - 4); 298*fcf5ef2aSThomas Huth } 299*fcf5ef2aSThomas Huth t0 = tcg_const_i32(excp); 300*fcf5ef2aSThomas Huth gen_helper_raise_exception(cpu_env, t0); 301*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 302*fcf5ef2aSThomas Huth ctx->exception = (excp); 303*fcf5ef2aSThomas Huth } 304*fcf5ef2aSThomas Huth 305*fcf5ef2aSThomas Huth static void gen_exception_nip(DisasContext *ctx, uint32_t excp, 306*fcf5ef2aSThomas Huth target_ulong nip) 307*fcf5ef2aSThomas Huth { 308*fcf5ef2aSThomas Huth TCGv_i32 t0; 309*fcf5ef2aSThomas Huth 310*fcf5ef2aSThomas Huth gen_update_nip(ctx, nip); 311*fcf5ef2aSThomas Huth t0 = tcg_const_i32(excp); 312*fcf5ef2aSThomas Huth gen_helper_raise_exception(cpu_env, t0); 313*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 314*fcf5ef2aSThomas Huth ctx->exception = (excp); 315*fcf5ef2aSThomas Huth } 316*fcf5ef2aSThomas Huth 317*fcf5ef2aSThomas Huth static void gen_debug_exception(DisasContext *ctx) 318*fcf5ef2aSThomas Huth { 319*fcf5ef2aSThomas Huth TCGv_i32 t0; 320*fcf5ef2aSThomas Huth 321*fcf5ef2aSThomas Huth /* These are all synchronous exceptions, we set the PC back to 322*fcf5ef2aSThomas Huth * the faulting instruction 323*fcf5ef2aSThomas Huth */ 324*fcf5ef2aSThomas Huth if ((ctx->exception != POWERPC_EXCP_BRANCH) && 325*fcf5ef2aSThomas Huth (ctx->exception != POWERPC_EXCP_SYNC)) { 326*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip); 327*fcf5ef2aSThomas Huth } 328*fcf5ef2aSThomas Huth t0 = tcg_const_i32(EXCP_DEBUG); 329*fcf5ef2aSThomas Huth gen_helper_raise_exception(cpu_env, t0); 330*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 331*fcf5ef2aSThomas Huth } 332*fcf5ef2aSThomas Huth 333*fcf5ef2aSThomas Huth static inline void gen_inval_exception(DisasContext *ctx, uint32_t error) 334*fcf5ef2aSThomas Huth { 335*fcf5ef2aSThomas Huth /* Will be converted to program check if needed */ 336*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_INVAL | error); 337*fcf5ef2aSThomas Huth } 338*fcf5ef2aSThomas Huth 339*fcf5ef2aSThomas Huth static inline void gen_priv_exception(DisasContext *ctx, uint32_t error) 340*fcf5ef2aSThomas Huth { 341*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_PRIV | error); 342*fcf5ef2aSThomas Huth } 343*fcf5ef2aSThomas Huth 344*fcf5ef2aSThomas Huth static inline void gen_hvpriv_exception(DisasContext *ctx, uint32_t error) 345*fcf5ef2aSThomas Huth { 346*fcf5ef2aSThomas Huth /* Will be converted to program check if needed */ 347*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error); 348*fcf5ef2aSThomas Huth } 349*fcf5ef2aSThomas Huth 350*fcf5ef2aSThomas Huth /* Stop translation */ 351*fcf5ef2aSThomas Huth static inline void gen_stop_exception(DisasContext *ctx) 352*fcf5ef2aSThomas Huth { 353*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip); 354*fcf5ef2aSThomas Huth ctx->exception = POWERPC_EXCP_STOP; 355*fcf5ef2aSThomas Huth } 356*fcf5ef2aSThomas Huth 357*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY 358*fcf5ef2aSThomas Huth /* No need to update nip here, as execution flow will change */ 359*fcf5ef2aSThomas Huth static inline void gen_sync_exception(DisasContext *ctx) 360*fcf5ef2aSThomas Huth { 361*fcf5ef2aSThomas Huth ctx->exception = POWERPC_EXCP_SYNC; 362*fcf5ef2aSThomas Huth } 363*fcf5ef2aSThomas Huth #endif 364*fcf5ef2aSThomas Huth 365*fcf5ef2aSThomas Huth #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ 366*fcf5ef2aSThomas Huth GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE) 367*fcf5ef2aSThomas Huth 368*fcf5ef2aSThomas Huth #define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \ 369*fcf5ef2aSThomas Huth GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2) 370*fcf5ef2aSThomas Huth 371*fcf5ef2aSThomas Huth #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \ 372*fcf5ef2aSThomas Huth GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE) 373*fcf5ef2aSThomas Huth 374*fcf5ef2aSThomas Huth #define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \ 375*fcf5ef2aSThomas Huth GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2) 376*fcf5ef2aSThomas Huth 377*fcf5ef2aSThomas Huth #define GEN_HANDLER_E_2(name, opc1, opc2, opc3, opc4, inval, type, type2) \ 378*fcf5ef2aSThomas Huth GEN_OPCODE3(name, opc1, opc2, opc3, opc4, inval, type, type2) 379*fcf5ef2aSThomas Huth 380*fcf5ef2aSThomas Huth #define GEN_HANDLER2_E_2(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2) \ 381*fcf5ef2aSThomas Huth GEN_OPCODE4(name, onam, opc1, opc2, opc3, opc4, inval, typ, typ2) 382*fcf5ef2aSThomas Huth 383*fcf5ef2aSThomas Huth typedef struct opcode_t { 384*fcf5ef2aSThomas Huth unsigned char opc1, opc2, opc3, opc4; 385*fcf5ef2aSThomas Huth #if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */ 386*fcf5ef2aSThomas Huth unsigned char pad[4]; 387*fcf5ef2aSThomas Huth #endif 388*fcf5ef2aSThomas Huth opc_handler_t handler; 389*fcf5ef2aSThomas Huth const char *oname; 390*fcf5ef2aSThomas Huth } opcode_t; 391*fcf5ef2aSThomas Huth 392*fcf5ef2aSThomas Huth /* Helpers for priv. check */ 393*fcf5ef2aSThomas Huth #define GEN_PRIV \ 394*fcf5ef2aSThomas Huth do { \ 395*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; \ 396*fcf5ef2aSThomas Huth } while (0) 397*fcf5ef2aSThomas Huth 398*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 399*fcf5ef2aSThomas Huth #define CHK_HV GEN_PRIV 400*fcf5ef2aSThomas Huth #define CHK_SV GEN_PRIV 401*fcf5ef2aSThomas Huth #define CHK_HVRM GEN_PRIV 402*fcf5ef2aSThomas Huth #else 403*fcf5ef2aSThomas Huth #define CHK_HV \ 404*fcf5ef2aSThomas Huth do { \ 405*fcf5ef2aSThomas Huth if (unlikely(ctx->pr || !ctx->hv)) { \ 406*fcf5ef2aSThomas Huth GEN_PRIV; \ 407*fcf5ef2aSThomas Huth } \ 408*fcf5ef2aSThomas Huth } while (0) 409*fcf5ef2aSThomas Huth #define CHK_SV \ 410*fcf5ef2aSThomas Huth do { \ 411*fcf5ef2aSThomas Huth if (unlikely(ctx->pr)) { \ 412*fcf5ef2aSThomas Huth GEN_PRIV; \ 413*fcf5ef2aSThomas Huth } \ 414*fcf5ef2aSThomas Huth } while (0) 415*fcf5ef2aSThomas Huth #define CHK_HVRM \ 416*fcf5ef2aSThomas Huth do { \ 417*fcf5ef2aSThomas Huth if (unlikely(ctx->pr || !ctx->hv || ctx->dr)) { \ 418*fcf5ef2aSThomas Huth GEN_PRIV; \ 419*fcf5ef2aSThomas Huth } \ 420*fcf5ef2aSThomas Huth } while (0) 421*fcf5ef2aSThomas Huth #endif 422*fcf5ef2aSThomas Huth 423*fcf5ef2aSThomas Huth #define CHK_NONE 424*fcf5ef2aSThomas Huth 425*fcf5ef2aSThomas Huth 426*fcf5ef2aSThomas Huth /*****************************************************************************/ 427*fcf5ef2aSThomas Huth /*** Instruction decoding ***/ 428*fcf5ef2aSThomas Huth #define EXTRACT_HELPER(name, shift, nb) \ 429*fcf5ef2aSThomas Huth static inline uint32_t name(uint32_t opcode) \ 430*fcf5ef2aSThomas Huth { \ 431*fcf5ef2aSThomas Huth return (opcode >> (shift)) & ((1 << (nb)) - 1); \ 432*fcf5ef2aSThomas Huth } 433*fcf5ef2aSThomas Huth 434*fcf5ef2aSThomas Huth #define EXTRACT_SHELPER(name, shift, nb) \ 435*fcf5ef2aSThomas Huth static inline int32_t name(uint32_t opcode) \ 436*fcf5ef2aSThomas Huth { \ 437*fcf5ef2aSThomas Huth return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \ 438*fcf5ef2aSThomas Huth } 439*fcf5ef2aSThomas Huth 440*fcf5ef2aSThomas Huth #define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2) \ 441*fcf5ef2aSThomas Huth static inline uint32_t name(uint32_t opcode) \ 442*fcf5ef2aSThomas Huth { \ 443*fcf5ef2aSThomas Huth return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) | \ 444*fcf5ef2aSThomas Huth ((opcode >> (shift2)) & ((1 << (nb2)) - 1)); \ 445*fcf5ef2aSThomas Huth } 446*fcf5ef2aSThomas Huth 447*fcf5ef2aSThomas Huth #define EXTRACT_HELPER_DXFORM(name, \ 448*fcf5ef2aSThomas Huth d0_bits, shift_op_d0, shift_d0, \ 449*fcf5ef2aSThomas Huth d1_bits, shift_op_d1, shift_d1, \ 450*fcf5ef2aSThomas Huth d2_bits, shift_op_d2, shift_d2) \ 451*fcf5ef2aSThomas Huth static inline int16_t name(uint32_t opcode) \ 452*fcf5ef2aSThomas Huth { \ 453*fcf5ef2aSThomas Huth return \ 454*fcf5ef2aSThomas Huth (((opcode >> (shift_op_d0)) & ((1 << (d0_bits)) - 1)) << (shift_d0)) | \ 455*fcf5ef2aSThomas Huth (((opcode >> (shift_op_d1)) & ((1 << (d1_bits)) - 1)) << (shift_d1)) | \ 456*fcf5ef2aSThomas Huth (((opcode >> (shift_op_d2)) & ((1 << (d2_bits)) - 1)) << (shift_d2)); \ 457*fcf5ef2aSThomas Huth } 458*fcf5ef2aSThomas Huth 459*fcf5ef2aSThomas Huth 460*fcf5ef2aSThomas Huth /* Opcode part 1 */ 461*fcf5ef2aSThomas Huth EXTRACT_HELPER(opc1, 26, 6); 462*fcf5ef2aSThomas Huth /* Opcode part 2 */ 463*fcf5ef2aSThomas Huth EXTRACT_HELPER(opc2, 1, 5); 464*fcf5ef2aSThomas Huth /* Opcode part 3 */ 465*fcf5ef2aSThomas Huth EXTRACT_HELPER(opc3, 6, 5); 466*fcf5ef2aSThomas Huth /* Opcode part 4 */ 467*fcf5ef2aSThomas Huth EXTRACT_HELPER(opc4, 16, 5); 468*fcf5ef2aSThomas Huth /* Update Cr0 flags */ 469*fcf5ef2aSThomas Huth EXTRACT_HELPER(Rc, 0, 1); 470*fcf5ef2aSThomas Huth /* Update Cr6 flags (Altivec) */ 471*fcf5ef2aSThomas Huth EXTRACT_HELPER(Rc21, 10, 1); 472*fcf5ef2aSThomas Huth /* Destination */ 473*fcf5ef2aSThomas Huth EXTRACT_HELPER(rD, 21, 5); 474*fcf5ef2aSThomas Huth /* Source */ 475*fcf5ef2aSThomas Huth EXTRACT_HELPER(rS, 21, 5); 476*fcf5ef2aSThomas Huth /* First operand */ 477*fcf5ef2aSThomas Huth EXTRACT_HELPER(rA, 16, 5); 478*fcf5ef2aSThomas Huth /* Second operand */ 479*fcf5ef2aSThomas Huth EXTRACT_HELPER(rB, 11, 5); 480*fcf5ef2aSThomas Huth /* Third operand */ 481*fcf5ef2aSThomas Huth EXTRACT_HELPER(rC, 6, 5); 482*fcf5ef2aSThomas Huth /*** Get CRn ***/ 483*fcf5ef2aSThomas Huth EXTRACT_HELPER(crfD, 23, 3); 484*fcf5ef2aSThomas Huth EXTRACT_HELPER(crfS, 18, 3); 485*fcf5ef2aSThomas Huth EXTRACT_HELPER(crbD, 21, 5); 486*fcf5ef2aSThomas Huth EXTRACT_HELPER(crbA, 16, 5); 487*fcf5ef2aSThomas Huth EXTRACT_HELPER(crbB, 11, 5); 488*fcf5ef2aSThomas Huth /* SPR / TBL */ 489*fcf5ef2aSThomas Huth EXTRACT_HELPER(_SPR, 11, 10); 490*fcf5ef2aSThomas Huth static inline uint32_t SPR(uint32_t opcode) 491*fcf5ef2aSThomas Huth { 492*fcf5ef2aSThomas Huth uint32_t sprn = _SPR(opcode); 493*fcf5ef2aSThomas Huth 494*fcf5ef2aSThomas Huth return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5); 495*fcf5ef2aSThomas Huth } 496*fcf5ef2aSThomas Huth /*** Get constants ***/ 497*fcf5ef2aSThomas Huth /* 16 bits signed immediate value */ 498*fcf5ef2aSThomas Huth EXTRACT_SHELPER(SIMM, 0, 16); 499*fcf5ef2aSThomas Huth /* 16 bits unsigned immediate value */ 500*fcf5ef2aSThomas Huth EXTRACT_HELPER(UIMM, 0, 16); 501*fcf5ef2aSThomas Huth /* 5 bits signed immediate value */ 502*fcf5ef2aSThomas Huth EXTRACT_HELPER(SIMM5, 16, 5); 503*fcf5ef2aSThomas Huth /* 5 bits signed immediate value */ 504*fcf5ef2aSThomas Huth EXTRACT_HELPER(UIMM5, 16, 5); 505*fcf5ef2aSThomas Huth /* 4 bits unsigned immediate value */ 506*fcf5ef2aSThomas Huth EXTRACT_HELPER(UIMM4, 16, 4); 507*fcf5ef2aSThomas Huth /* Bit count */ 508*fcf5ef2aSThomas Huth EXTRACT_HELPER(NB, 11, 5); 509*fcf5ef2aSThomas Huth /* Shift count */ 510*fcf5ef2aSThomas Huth EXTRACT_HELPER(SH, 11, 5); 511*fcf5ef2aSThomas Huth /* Vector shift count */ 512*fcf5ef2aSThomas Huth EXTRACT_HELPER(VSH, 6, 4); 513*fcf5ef2aSThomas Huth /* Mask start */ 514*fcf5ef2aSThomas Huth EXTRACT_HELPER(MB, 6, 5); 515*fcf5ef2aSThomas Huth /* Mask end */ 516*fcf5ef2aSThomas Huth EXTRACT_HELPER(ME, 1, 5); 517*fcf5ef2aSThomas Huth /* Trap operand */ 518*fcf5ef2aSThomas Huth EXTRACT_HELPER(TO, 21, 5); 519*fcf5ef2aSThomas Huth 520*fcf5ef2aSThomas Huth EXTRACT_HELPER(CRM, 12, 8); 521*fcf5ef2aSThomas Huth 522*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY 523*fcf5ef2aSThomas Huth EXTRACT_HELPER(SR, 16, 4); 524*fcf5ef2aSThomas Huth #endif 525*fcf5ef2aSThomas Huth 526*fcf5ef2aSThomas Huth /* mtfsf/mtfsfi */ 527*fcf5ef2aSThomas Huth EXTRACT_HELPER(FPBF, 23, 3); 528*fcf5ef2aSThomas Huth EXTRACT_HELPER(FPIMM, 12, 4); 529*fcf5ef2aSThomas Huth EXTRACT_HELPER(FPL, 25, 1); 530*fcf5ef2aSThomas Huth EXTRACT_HELPER(FPFLM, 17, 8); 531*fcf5ef2aSThomas Huth EXTRACT_HELPER(FPW, 16, 1); 532*fcf5ef2aSThomas Huth 533*fcf5ef2aSThomas Huth /* addpcis */ 534*fcf5ef2aSThomas Huth EXTRACT_HELPER_DXFORM(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0) 535*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 536*fcf5ef2aSThomas Huth /* darn */ 537*fcf5ef2aSThomas Huth EXTRACT_HELPER(L, 16, 2); 538*fcf5ef2aSThomas Huth #endif 539*fcf5ef2aSThomas Huth 540*fcf5ef2aSThomas Huth /*** Jump target decoding ***/ 541*fcf5ef2aSThomas Huth /* Immediate address */ 542*fcf5ef2aSThomas Huth static inline target_ulong LI(uint32_t opcode) 543*fcf5ef2aSThomas Huth { 544*fcf5ef2aSThomas Huth return (opcode >> 0) & 0x03FFFFFC; 545*fcf5ef2aSThomas Huth } 546*fcf5ef2aSThomas Huth 547*fcf5ef2aSThomas Huth static inline uint32_t BD(uint32_t opcode) 548*fcf5ef2aSThomas Huth { 549*fcf5ef2aSThomas Huth return (opcode >> 0) & 0xFFFC; 550*fcf5ef2aSThomas Huth } 551*fcf5ef2aSThomas Huth 552*fcf5ef2aSThomas Huth EXTRACT_HELPER(BO, 21, 5); 553*fcf5ef2aSThomas Huth EXTRACT_HELPER(BI, 16, 5); 554*fcf5ef2aSThomas Huth /* Absolute/relative address */ 555*fcf5ef2aSThomas Huth EXTRACT_HELPER(AA, 1, 1); 556*fcf5ef2aSThomas Huth /* Link */ 557*fcf5ef2aSThomas Huth EXTRACT_HELPER(LK, 0, 1); 558*fcf5ef2aSThomas Huth 559*fcf5ef2aSThomas Huth /* DFP Z22-form */ 560*fcf5ef2aSThomas Huth EXTRACT_HELPER(DCM, 10, 6) 561*fcf5ef2aSThomas Huth 562*fcf5ef2aSThomas Huth /* DFP Z23-form */ 563*fcf5ef2aSThomas Huth EXTRACT_HELPER(RMC, 9, 2) 564*fcf5ef2aSThomas Huth 565*fcf5ef2aSThomas Huth EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5); 566*fcf5ef2aSThomas Huth EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5); 567*fcf5ef2aSThomas Huth EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5); 568*fcf5ef2aSThomas Huth EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5); 569*fcf5ef2aSThomas Huth EXTRACT_HELPER_SPLIT(xC, 3, 1, 6, 5); 570*fcf5ef2aSThomas Huth EXTRACT_HELPER(DM, 8, 2); 571*fcf5ef2aSThomas Huth EXTRACT_HELPER(UIM, 16, 2); 572*fcf5ef2aSThomas Huth EXTRACT_HELPER(SHW, 8, 2); 573*fcf5ef2aSThomas Huth EXTRACT_HELPER(SP, 19, 2); 574*fcf5ef2aSThomas Huth EXTRACT_HELPER(IMM8, 11, 8); 575*fcf5ef2aSThomas Huth 576*fcf5ef2aSThomas Huth /*****************************************************************************/ 577*fcf5ef2aSThomas Huth /* PowerPC instructions table */ 578*fcf5ef2aSThomas Huth 579*fcf5ef2aSThomas Huth #if defined(DO_PPC_STATISTICS) 580*fcf5ef2aSThomas Huth #define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \ 581*fcf5ef2aSThomas Huth { \ 582*fcf5ef2aSThomas Huth .opc1 = op1, \ 583*fcf5ef2aSThomas Huth .opc2 = op2, \ 584*fcf5ef2aSThomas Huth .opc3 = op3, \ 585*fcf5ef2aSThomas Huth .opc4 = 0xff, \ 586*fcf5ef2aSThomas Huth .handler = { \ 587*fcf5ef2aSThomas Huth .inval1 = invl, \ 588*fcf5ef2aSThomas Huth .type = _typ, \ 589*fcf5ef2aSThomas Huth .type2 = _typ2, \ 590*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 591*fcf5ef2aSThomas Huth .oname = stringify(name), \ 592*fcf5ef2aSThomas Huth }, \ 593*fcf5ef2aSThomas Huth .oname = stringify(name), \ 594*fcf5ef2aSThomas Huth } 595*fcf5ef2aSThomas Huth #define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \ 596*fcf5ef2aSThomas Huth { \ 597*fcf5ef2aSThomas Huth .opc1 = op1, \ 598*fcf5ef2aSThomas Huth .opc2 = op2, \ 599*fcf5ef2aSThomas Huth .opc3 = op3, \ 600*fcf5ef2aSThomas Huth .opc4 = 0xff, \ 601*fcf5ef2aSThomas Huth .handler = { \ 602*fcf5ef2aSThomas Huth .inval1 = invl1, \ 603*fcf5ef2aSThomas Huth .inval2 = invl2, \ 604*fcf5ef2aSThomas Huth .type = _typ, \ 605*fcf5ef2aSThomas Huth .type2 = _typ2, \ 606*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 607*fcf5ef2aSThomas Huth .oname = stringify(name), \ 608*fcf5ef2aSThomas Huth }, \ 609*fcf5ef2aSThomas Huth .oname = stringify(name), \ 610*fcf5ef2aSThomas Huth } 611*fcf5ef2aSThomas Huth #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \ 612*fcf5ef2aSThomas Huth { \ 613*fcf5ef2aSThomas Huth .opc1 = op1, \ 614*fcf5ef2aSThomas Huth .opc2 = op2, \ 615*fcf5ef2aSThomas Huth .opc3 = op3, \ 616*fcf5ef2aSThomas Huth .opc4 = 0xff, \ 617*fcf5ef2aSThomas Huth .handler = { \ 618*fcf5ef2aSThomas Huth .inval1 = invl, \ 619*fcf5ef2aSThomas Huth .type = _typ, \ 620*fcf5ef2aSThomas Huth .type2 = _typ2, \ 621*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 622*fcf5ef2aSThomas Huth .oname = onam, \ 623*fcf5ef2aSThomas Huth }, \ 624*fcf5ef2aSThomas Huth .oname = onam, \ 625*fcf5ef2aSThomas Huth } 626*fcf5ef2aSThomas Huth #define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2) \ 627*fcf5ef2aSThomas Huth { \ 628*fcf5ef2aSThomas Huth .opc1 = op1, \ 629*fcf5ef2aSThomas Huth .opc2 = op2, \ 630*fcf5ef2aSThomas Huth .opc3 = op3, \ 631*fcf5ef2aSThomas Huth .opc4 = op4, \ 632*fcf5ef2aSThomas Huth .handler = { \ 633*fcf5ef2aSThomas Huth .inval1 = invl, \ 634*fcf5ef2aSThomas Huth .type = _typ, \ 635*fcf5ef2aSThomas Huth .type2 = _typ2, \ 636*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 637*fcf5ef2aSThomas Huth .oname = stringify(name), \ 638*fcf5ef2aSThomas Huth }, \ 639*fcf5ef2aSThomas Huth .oname = stringify(name), \ 640*fcf5ef2aSThomas Huth } 641*fcf5ef2aSThomas Huth #define GEN_OPCODE4(name, onam, op1, op2, op3, op4, invl, _typ, _typ2) \ 642*fcf5ef2aSThomas Huth { \ 643*fcf5ef2aSThomas Huth .opc1 = op1, \ 644*fcf5ef2aSThomas Huth .opc2 = op2, \ 645*fcf5ef2aSThomas Huth .opc3 = op3, \ 646*fcf5ef2aSThomas Huth .opc4 = op4, \ 647*fcf5ef2aSThomas Huth .handler = { \ 648*fcf5ef2aSThomas Huth .inval1 = invl, \ 649*fcf5ef2aSThomas Huth .type = _typ, \ 650*fcf5ef2aSThomas Huth .type2 = _typ2, \ 651*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 652*fcf5ef2aSThomas Huth .oname = onam, \ 653*fcf5ef2aSThomas Huth }, \ 654*fcf5ef2aSThomas Huth .oname = onam, \ 655*fcf5ef2aSThomas Huth } 656*fcf5ef2aSThomas Huth #else 657*fcf5ef2aSThomas Huth #define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \ 658*fcf5ef2aSThomas Huth { \ 659*fcf5ef2aSThomas Huth .opc1 = op1, \ 660*fcf5ef2aSThomas Huth .opc2 = op2, \ 661*fcf5ef2aSThomas Huth .opc3 = op3, \ 662*fcf5ef2aSThomas Huth .opc4 = 0xff, \ 663*fcf5ef2aSThomas Huth .handler = { \ 664*fcf5ef2aSThomas Huth .inval1 = invl, \ 665*fcf5ef2aSThomas Huth .type = _typ, \ 666*fcf5ef2aSThomas Huth .type2 = _typ2, \ 667*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 668*fcf5ef2aSThomas Huth }, \ 669*fcf5ef2aSThomas Huth .oname = stringify(name), \ 670*fcf5ef2aSThomas Huth } 671*fcf5ef2aSThomas Huth #define GEN_OPCODE_DUAL(name, op1, op2, op3, invl1, invl2, _typ, _typ2) \ 672*fcf5ef2aSThomas Huth { \ 673*fcf5ef2aSThomas Huth .opc1 = op1, \ 674*fcf5ef2aSThomas Huth .opc2 = op2, \ 675*fcf5ef2aSThomas Huth .opc3 = op3, \ 676*fcf5ef2aSThomas Huth .opc4 = 0xff, \ 677*fcf5ef2aSThomas Huth .handler = { \ 678*fcf5ef2aSThomas Huth .inval1 = invl1, \ 679*fcf5ef2aSThomas Huth .inval2 = invl2, \ 680*fcf5ef2aSThomas Huth .type = _typ, \ 681*fcf5ef2aSThomas Huth .type2 = _typ2, \ 682*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 683*fcf5ef2aSThomas Huth }, \ 684*fcf5ef2aSThomas Huth .oname = stringify(name), \ 685*fcf5ef2aSThomas Huth } 686*fcf5ef2aSThomas Huth #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \ 687*fcf5ef2aSThomas Huth { \ 688*fcf5ef2aSThomas Huth .opc1 = op1, \ 689*fcf5ef2aSThomas Huth .opc2 = op2, \ 690*fcf5ef2aSThomas Huth .opc3 = op3, \ 691*fcf5ef2aSThomas Huth .opc4 = 0xff, \ 692*fcf5ef2aSThomas Huth .handler = { \ 693*fcf5ef2aSThomas Huth .inval1 = invl, \ 694*fcf5ef2aSThomas Huth .type = _typ, \ 695*fcf5ef2aSThomas Huth .type2 = _typ2, \ 696*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 697*fcf5ef2aSThomas Huth }, \ 698*fcf5ef2aSThomas Huth .oname = onam, \ 699*fcf5ef2aSThomas Huth } 700*fcf5ef2aSThomas Huth #define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2) \ 701*fcf5ef2aSThomas Huth { \ 702*fcf5ef2aSThomas Huth .opc1 = op1, \ 703*fcf5ef2aSThomas Huth .opc2 = op2, \ 704*fcf5ef2aSThomas Huth .opc3 = op3, \ 705*fcf5ef2aSThomas Huth .opc4 = op4, \ 706*fcf5ef2aSThomas Huth .handler = { \ 707*fcf5ef2aSThomas Huth .inval1 = invl, \ 708*fcf5ef2aSThomas Huth .type = _typ, \ 709*fcf5ef2aSThomas Huth .type2 = _typ2, \ 710*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 711*fcf5ef2aSThomas Huth }, \ 712*fcf5ef2aSThomas Huth .oname = stringify(name), \ 713*fcf5ef2aSThomas Huth } 714*fcf5ef2aSThomas Huth #define GEN_OPCODE4(name, onam, op1, op2, op3, op4, invl, _typ, _typ2) \ 715*fcf5ef2aSThomas Huth { \ 716*fcf5ef2aSThomas Huth .opc1 = op1, \ 717*fcf5ef2aSThomas Huth .opc2 = op2, \ 718*fcf5ef2aSThomas Huth .opc3 = op3, \ 719*fcf5ef2aSThomas Huth .opc4 = op4, \ 720*fcf5ef2aSThomas Huth .handler = { \ 721*fcf5ef2aSThomas Huth .inval1 = invl, \ 722*fcf5ef2aSThomas Huth .type = _typ, \ 723*fcf5ef2aSThomas Huth .type2 = _typ2, \ 724*fcf5ef2aSThomas Huth .handler = &gen_##name, \ 725*fcf5ef2aSThomas Huth }, \ 726*fcf5ef2aSThomas Huth .oname = onam, \ 727*fcf5ef2aSThomas Huth } 728*fcf5ef2aSThomas Huth #endif 729*fcf5ef2aSThomas Huth 730*fcf5ef2aSThomas Huth /* SPR load/store helpers */ 731*fcf5ef2aSThomas Huth static inline void gen_load_spr(TCGv t, int reg) 732*fcf5ef2aSThomas Huth { 733*fcf5ef2aSThomas Huth tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg])); 734*fcf5ef2aSThomas Huth } 735*fcf5ef2aSThomas Huth 736*fcf5ef2aSThomas Huth static inline void gen_store_spr(int reg, TCGv t) 737*fcf5ef2aSThomas Huth { 738*fcf5ef2aSThomas Huth tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg])); 739*fcf5ef2aSThomas Huth } 740*fcf5ef2aSThomas Huth 741*fcf5ef2aSThomas Huth /* Invalid instruction */ 742*fcf5ef2aSThomas Huth static void gen_invalid(DisasContext *ctx) 743*fcf5ef2aSThomas Huth { 744*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 745*fcf5ef2aSThomas Huth } 746*fcf5ef2aSThomas Huth 747*fcf5ef2aSThomas Huth static opc_handler_t invalid_handler = { 748*fcf5ef2aSThomas Huth .inval1 = 0xFFFFFFFF, 749*fcf5ef2aSThomas Huth .inval2 = 0xFFFFFFFF, 750*fcf5ef2aSThomas Huth .type = PPC_NONE, 751*fcf5ef2aSThomas Huth .type2 = PPC_NONE, 752*fcf5ef2aSThomas Huth .handler = gen_invalid, 753*fcf5ef2aSThomas Huth }; 754*fcf5ef2aSThomas Huth 755*fcf5ef2aSThomas Huth /*** Integer comparison ***/ 756*fcf5ef2aSThomas Huth 757*fcf5ef2aSThomas Huth static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf) 758*fcf5ef2aSThomas Huth { 759*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 760*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 761*fcf5ef2aSThomas Huth 762*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so); 763*fcf5ef2aSThomas Huth 764*fcf5ef2aSThomas Huth tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1); 765*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, t0); 766*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t1, t1, CRF_LT); 767*fcf5ef2aSThomas Huth tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); 768*fcf5ef2aSThomas Huth 769*fcf5ef2aSThomas Huth tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1); 770*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, t0); 771*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t1, t1, CRF_GT); 772*fcf5ef2aSThomas Huth tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); 773*fcf5ef2aSThomas Huth 774*fcf5ef2aSThomas Huth tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1); 775*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, t0); 776*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t1, t1, CRF_EQ); 777*fcf5ef2aSThomas Huth tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); 778*fcf5ef2aSThomas Huth 779*fcf5ef2aSThomas Huth tcg_temp_free(t0); 780*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 781*fcf5ef2aSThomas Huth } 782*fcf5ef2aSThomas Huth 783*fcf5ef2aSThomas Huth static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf) 784*fcf5ef2aSThomas Huth { 785*fcf5ef2aSThomas Huth TCGv t0 = tcg_const_tl(arg1); 786*fcf5ef2aSThomas Huth gen_op_cmp(arg0, t0, s, crf); 787*fcf5ef2aSThomas Huth tcg_temp_free(t0); 788*fcf5ef2aSThomas Huth } 789*fcf5ef2aSThomas Huth 790*fcf5ef2aSThomas Huth static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf) 791*fcf5ef2aSThomas Huth { 792*fcf5ef2aSThomas Huth TCGv t0, t1; 793*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 794*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 795*fcf5ef2aSThomas Huth if (s) { 796*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(t0, arg0); 797*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(t1, arg1); 798*fcf5ef2aSThomas Huth } else { 799*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(t0, arg0); 800*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(t1, arg1); 801*fcf5ef2aSThomas Huth } 802*fcf5ef2aSThomas Huth gen_op_cmp(t0, t1, s, crf); 803*fcf5ef2aSThomas Huth tcg_temp_free(t1); 804*fcf5ef2aSThomas Huth tcg_temp_free(t0); 805*fcf5ef2aSThomas Huth } 806*fcf5ef2aSThomas Huth 807*fcf5ef2aSThomas Huth static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf) 808*fcf5ef2aSThomas Huth { 809*fcf5ef2aSThomas Huth TCGv t0 = tcg_const_tl(arg1); 810*fcf5ef2aSThomas Huth gen_op_cmp32(arg0, t0, s, crf); 811*fcf5ef2aSThomas Huth tcg_temp_free(t0); 812*fcf5ef2aSThomas Huth } 813*fcf5ef2aSThomas Huth 814*fcf5ef2aSThomas Huth static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg) 815*fcf5ef2aSThomas Huth { 816*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 817*fcf5ef2aSThomas Huth gen_op_cmpi32(reg, 0, 1, 0); 818*fcf5ef2aSThomas Huth } else { 819*fcf5ef2aSThomas Huth gen_op_cmpi(reg, 0, 1, 0); 820*fcf5ef2aSThomas Huth } 821*fcf5ef2aSThomas Huth } 822*fcf5ef2aSThomas Huth 823*fcf5ef2aSThomas Huth /* cmp */ 824*fcf5ef2aSThomas Huth static void gen_cmp(DisasContext *ctx) 825*fcf5ef2aSThomas Huth { 826*fcf5ef2aSThomas Huth if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) { 827*fcf5ef2aSThomas Huth gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], 828*fcf5ef2aSThomas Huth 1, crfD(ctx->opcode)); 829*fcf5ef2aSThomas Huth } else { 830*fcf5ef2aSThomas Huth gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], 831*fcf5ef2aSThomas Huth 1, crfD(ctx->opcode)); 832*fcf5ef2aSThomas Huth } 833*fcf5ef2aSThomas Huth } 834*fcf5ef2aSThomas Huth 835*fcf5ef2aSThomas Huth /* cmpi */ 836*fcf5ef2aSThomas Huth static void gen_cmpi(DisasContext *ctx) 837*fcf5ef2aSThomas Huth { 838*fcf5ef2aSThomas Huth if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) { 839*fcf5ef2aSThomas Huth gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode), 840*fcf5ef2aSThomas Huth 1, crfD(ctx->opcode)); 841*fcf5ef2aSThomas Huth } else { 842*fcf5ef2aSThomas Huth gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode), 843*fcf5ef2aSThomas Huth 1, crfD(ctx->opcode)); 844*fcf5ef2aSThomas Huth } 845*fcf5ef2aSThomas Huth } 846*fcf5ef2aSThomas Huth 847*fcf5ef2aSThomas Huth /* cmpl */ 848*fcf5ef2aSThomas Huth static void gen_cmpl(DisasContext *ctx) 849*fcf5ef2aSThomas Huth { 850*fcf5ef2aSThomas Huth if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) { 851*fcf5ef2aSThomas Huth gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], 852*fcf5ef2aSThomas Huth 0, crfD(ctx->opcode)); 853*fcf5ef2aSThomas Huth } else { 854*fcf5ef2aSThomas Huth gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], 855*fcf5ef2aSThomas Huth 0, crfD(ctx->opcode)); 856*fcf5ef2aSThomas Huth } 857*fcf5ef2aSThomas Huth } 858*fcf5ef2aSThomas Huth 859*fcf5ef2aSThomas Huth /* cmpli */ 860*fcf5ef2aSThomas Huth static void gen_cmpli(DisasContext *ctx) 861*fcf5ef2aSThomas Huth { 862*fcf5ef2aSThomas Huth if ((ctx->opcode & 0x00200000) && (ctx->insns_flags & PPC_64B)) { 863*fcf5ef2aSThomas Huth gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode), 864*fcf5ef2aSThomas Huth 0, crfD(ctx->opcode)); 865*fcf5ef2aSThomas Huth } else { 866*fcf5ef2aSThomas Huth gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode), 867*fcf5ef2aSThomas Huth 0, crfD(ctx->opcode)); 868*fcf5ef2aSThomas Huth } 869*fcf5ef2aSThomas Huth } 870*fcf5ef2aSThomas Huth 871*fcf5ef2aSThomas Huth /* cmprb - range comparison: isupper, isaplha, islower*/ 872*fcf5ef2aSThomas Huth static void gen_cmprb(DisasContext *ctx) 873*fcf5ef2aSThomas Huth { 874*fcf5ef2aSThomas Huth TCGv_i32 src1 = tcg_temp_new_i32(); 875*fcf5ef2aSThomas Huth TCGv_i32 src2 = tcg_temp_new_i32(); 876*fcf5ef2aSThomas Huth TCGv_i32 src2lo = tcg_temp_new_i32(); 877*fcf5ef2aSThomas Huth TCGv_i32 src2hi = tcg_temp_new_i32(); 878*fcf5ef2aSThomas Huth TCGv_i32 crf = cpu_crf[crfD(ctx->opcode)]; 879*fcf5ef2aSThomas Huth 880*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(src1, cpu_gpr[rA(ctx->opcode)]); 881*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(src2, cpu_gpr[rB(ctx->opcode)]); 882*fcf5ef2aSThomas Huth 883*fcf5ef2aSThomas Huth tcg_gen_andi_i32(src1, src1, 0xFF); 884*fcf5ef2aSThomas Huth tcg_gen_ext8u_i32(src2lo, src2); 885*fcf5ef2aSThomas Huth tcg_gen_shri_i32(src2, src2, 8); 886*fcf5ef2aSThomas Huth tcg_gen_ext8u_i32(src2hi, src2); 887*fcf5ef2aSThomas Huth 888*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1); 889*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi); 890*fcf5ef2aSThomas Huth tcg_gen_and_i32(crf, src2lo, src2hi); 891*fcf5ef2aSThomas Huth 892*fcf5ef2aSThomas Huth if (ctx->opcode & 0x00200000) { 893*fcf5ef2aSThomas Huth tcg_gen_shri_i32(src2, src2, 8); 894*fcf5ef2aSThomas Huth tcg_gen_ext8u_i32(src2lo, src2); 895*fcf5ef2aSThomas Huth tcg_gen_shri_i32(src2, src2, 8); 896*fcf5ef2aSThomas Huth tcg_gen_ext8u_i32(src2hi, src2); 897*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1); 898*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi); 899*fcf5ef2aSThomas Huth tcg_gen_and_i32(src2lo, src2lo, src2hi); 900*fcf5ef2aSThomas Huth tcg_gen_or_i32(crf, crf, src2lo); 901*fcf5ef2aSThomas Huth } 902*fcf5ef2aSThomas Huth tcg_gen_shli_i32(crf, crf, CRF_GT); 903*fcf5ef2aSThomas Huth tcg_temp_free_i32(src1); 904*fcf5ef2aSThomas Huth tcg_temp_free_i32(src2); 905*fcf5ef2aSThomas Huth tcg_temp_free_i32(src2lo); 906*fcf5ef2aSThomas Huth tcg_temp_free_i32(src2hi); 907*fcf5ef2aSThomas Huth } 908*fcf5ef2aSThomas Huth 909*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 910*fcf5ef2aSThomas Huth /* cmpeqb */ 911*fcf5ef2aSThomas Huth static void gen_cmpeqb(DisasContext *ctx) 912*fcf5ef2aSThomas Huth { 913*fcf5ef2aSThomas Huth gen_helper_cmpeqb(cpu_crf[crfD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 914*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 915*fcf5ef2aSThomas Huth } 916*fcf5ef2aSThomas Huth #endif 917*fcf5ef2aSThomas Huth 918*fcf5ef2aSThomas Huth /* isel (PowerPC 2.03 specification) */ 919*fcf5ef2aSThomas Huth static void gen_isel(DisasContext *ctx) 920*fcf5ef2aSThomas Huth { 921*fcf5ef2aSThomas Huth uint32_t bi = rC(ctx->opcode); 922*fcf5ef2aSThomas Huth uint32_t mask = 0x08 >> (bi & 0x03); 923*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 924*fcf5ef2aSThomas Huth TCGv zr; 925*fcf5ef2aSThomas Huth 926*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]); 927*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, mask); 928*fcf5ef2aSThomas Huth 929*fcf5ef2aSThomas Huth zr = tcg_const_tl(0); 930*fcf5ef2aSThomas Huth tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], t0, zr, 931*fcf5ef2aSThomas Huth rA(ctx->opcode) ? cpu_gpr[rA(ctx->opcode)] : zr, 932*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 933*fcf5ef2aSThomas Huth tcg_temp_free(zr); 934*fcf5ef2aSThomas Huth tcg_temp_free(t0); 935*fcf5ef2aSThomas Huth } 936*fcf5ef2aSThomas Huth 937*fcf5ef2aSThomas Huth /* cmpb: PowerPC 2.05 specification */ 938*fcf5ef2aSThomas Huth static void gen_cmpb(DisasContext *ctx) 939*fcf5ef2aSThomas Huth { 940*fcf5ef2aSThomas Huth gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 941*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 942*fcf5ef2aSThomas Huth } 943*fcf5ef2aSThomas Huth 944*fcf5ef2aSThomas Huth /*** Integer arithmetic ***/ 945*fcf5ef2aSThomas Huth 946*fcf5ef2aSThomas Huth static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, 947*fcf5ef2aSThomas Huth TCGv arg1, TCGv arg2, int sub) 948*fcf5ef2aSThomas Huth { 949*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 950*fcf5ef2aSThomas Huth 951*fcf5ef2aSThomas Huth tcg_gen_xor_tl(cpu_ov, arg0, arg2); 952*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t0, arg1, arg2); 953*fcf5ef2aSThomas Huth if (sub) { 954*fcf5ef2aSThomas Huth tcg_gen_and_tl(cpu_ov, cpu_ov, t0); 955*fcf5ef2aSThomas Huth } else { 956*fcf5ef2aSThomas Huth tcg_gen_andc_tl(cpu_ov, cpu_ov, t0); 957*fcf5ef2aSThomas Huth } 958*fcf5ef2aSThomas Huth tcg_temp_free(t0); 959*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 960*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(cpu_ov, cpu_ov); 961*fcf5ef2aSThomas Huth } 962*fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1); 963*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 964*fcf5ef2aSThomas Huth } 965*fcf5ef2aSThomas Huth 966*fcf5ef2aSThomas Huth /* Common add function */ 967*fcf5ef2aSThomas Huth static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, 968*fcf5ef2aSThomas Huth TCGv arg2, bool add_ca, bool compute_ca, 969*fcf5ef2aSThomas Huth bool compute_ov, bool compute_rc0) 970*fcf5ef2aSThomas Huth { 971*fcf5ef2aSThomas Huth TCGv t0 = ret; 972*fcf5ef2aSThomas Huth 973*fcf5ef2aSThomas Huth if (compute_ca || compute_ov) { 974*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 975*fcf5ef2aSThomas Huth } 976*fcf5ef2aSThomas Huth 977*fcf5ef2aSThomas Huth if (compute_ca) { 978*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 979*fcf5ef2aSThomas Huth /* Caution: a non-obvious corner case of the spec is that we 980*fcf5ef2aSThomas Huth must produce the *entire* 64-bit addition, but produce the 981*fcf5ef2aSThomas Huth carry into bit 32. */ 982*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 983*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t1, arg1, arg2); /* add without carry */ 984*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, arg1, arg2); 985*fcf5ef2aSThomas Huth if (add_ca) { 986*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, t0, cpu_ca); 987*fcf5ef2aSThomas Huth } 988*fcf5ef2aSThomas Huth tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changed w/ carry */ 989*fcf5ef2aSThomas Huth tcg_temp_free(t1); 990*fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */ 991*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_ca, cpu_ca, 1); 992*fcf5ef2aSThomas Huth } else { 993*fcf5ef2aSThomas Huth TCGv zero = tcg_const_tl(0); 994*fcf5ef2aSThomas Huth if (add_ca) { 995*fcf5ef2aSThomas Huth tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero); 996*fcf5ef2aSThomas Huth tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero); 997*fcf5ef2aSThomas Huth } else { 998*fcf5ef2aSThomas Huth tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero); 999*fcf5ef2aSThomas Huth } 1000*fcf5ef2aSThomas Huth tcg_temp_free(zero); 1001*fcf5ef2aSThomas Huth } 1002*fcf5ef2aSThomas Huth } else { 1003*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, arg1, arg2); 1004*fcf5ef2aSThomas Huth if (add_ca) { 1005*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, t0, cpu_ca); 1006*fcf5ef2aSThomas Huth } 1007*fcf5ef2aSThomas Huth } 1008*fcf5ef2aSThomas Huth 1009*fcf5ef2aSThomas Huth if (compute_ov) { 1010*fcf5ef2aSThomas Huth gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0); 1011*fcf5ef2aSThomas Huth } 1012*fcf5ef2aSThomas Huth if (unlikely(compute_rc0)) { 1013*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t0); 1014*fcf5ef2aSThomas Huth } 1015*fcf5ef2aSThomas Huth 1016*fcf5ef2aSThomas Huth if (!TCGV_EQUAL(t0, ret)) { 1017*fcf5ef2aSThomas Huth tcg_gen_mov_tl(ret, t0); 1018*fcf5ef2aSThomas Huth tcg_temp_free(t0); 1019*fcf5ef2aSThomas Huth } 1020*fcf5ef2aSThomas Huth } 1021*fcf5ef2aSThomas Huth /* Add functions with two operands */ 1022*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \ 1023*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1024*fcf5ef2aSThomas Huth { \ 1025*fcf5ef2aSThomas Huth gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \ 1026*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ 1027*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \ 1028*fcf5ef2aSThomas Huth } 1029*fcf5ef2aSThomas Huth /* Add functions with one operand and one immediate */ 1030*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \ 1031*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov) \ 1032*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1033*fcf5ef2aSThomas Huth { \ 1034*fcf5ef2aSThomas Huth TCGv t0 = tcg_const_tl(const_val); \ 1035*fcf5ef2aSThomas Huth gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \ 1036*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], t0, \ 1037*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \ 1038*fcf5ef2aSThomas Huth tcg_temp_free(t0); \ 1039*fcf5ef2aSThomas Huth } 1040*fcf5ef2aSThomas Huth 1041*fcf5ef2aSThomas Huth /* add add. addo addo. */ 1042*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0) 1043*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1) 1044*fcf5ef2aSThomas Huth /* addc addc. addco addco. */ 1045*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0) 1046*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1) 1047*fcf5ef2aSThomas Huth /* adde adde. addeo addeo. */ 1048*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0) 1049*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1) 1050*fcf5ef2aSThomas Huth /* addme addme. addmeo addmeo. */ 1051*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0) 1052*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1) 1053*fcf5ef2aSThomas Huth /* addze addze. addzeo addzeo.*/ 1054*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0) 1055*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1) 1056*fcf5ef2aSThomas Huth /* addi */ 1057*fcf5ef2aSThomas Huth static void gen_addi(DisasContext *ctx) 1058*fcf5ef2aSThomas Huth { 1059*fcf5ef2aSThomas Huth target_long simm = SIMM(ctx->opcode); 1060*fcf5ef2aSThomas Huth 1061*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 1062*fcf5ef2aSThomas Huth /* li case */ 1063*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm); 1064*fcf5ef2aSThomas Huth } else { 1065*fcf5ef2aSThomas Huth tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], 1066*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], simm); 1067*fcf5ef2aSThomas Huth } 1068*fcf5ef2aSThomas Huth } 1069*fcf5ef2aSThomas Huth /* addic addic.*/ 1070*fcf5ef2aSThomas Huth static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0) 1071*fcf5ef2aSThomas Huth { 1072*fcf5ef2aSThomas Huth TCGv c = tcg_const_tl(SIMM(ctx->opcode)); 1073*fcf5ef2aSThomas Huth gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1074*fcf5ef2aSThomas Huth c, 0, 1, 0, compute_rc0); 1075*fcf5ef2aSThomas Huth tcg_temp_free(c); 1076*fcf5ef2aSThomas Huth } 1077*fcf5ef2aSThomas Huth 1078*fcf5ef2aSThomas Huth static void gen_addic(DisasContext *ctx) 1079*fcf5ef2aSThomas Huth { 1080*fcf5ef2aSThomas Huth gen_op_addic(ctx, 0); 1081*fcf5ef2aSThomas Huth } 1082*fcf5ef2aSThomas Huth 1083*fcf5ef2aSThomas Huth static void gen_addic_(DisasContext *ctx) 1084*fcf5ef2aSThomas Huth { 1085*fcf5ef2aSThomas Huth gen_op_addic(ctx, 1); 1086*fcf5ef2aSThomas Huth } 1087*fcf5ef2aSThomas Huth 1088*fcf5ef2aSThomas Huth /* addis */ 1089*fcf5ef2aSThomas Huth static void gen_addis(DisasContext *ctx) 1090*fcf5ef2aSThomas Huth { 1091*fcf5ef2aSThomas Huth target_long simm = SIMM(ctx->opcode); 1092*fcf5ef2aSThomas Huth 1093*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 1094*fcf5ef2aSThomas Huth /* lis case */ 1095*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16); 1096*fcf5ef2aSThomas Huth } else { 1097*fcf5ef2aSThomas Huth tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], 1098*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], simm << 16); 1099*fcf5ef2aSThomas Huth } 1100*fcf5ef2aSThomas Huth } 1101*fcf5ef2aSThomas Huth 1102*fcf5ef2aSThomas Huth /* addpcis */ 1103*fcf5ef2aSThomas Huth static void gen_addpcis(DisasContext *ctx) 1104*fcf5ef2aSThomas Huth { 1105*fcf5ef2aSThomas Huth target_long d = DX(ctx->opcode); 1106*fcf5ef2aSThomas Huth 1107*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], ctx->nip + (d << 16)); 1108*fcf5ef2aSThomas Huth } 1109*fcf5ef2aSThomas Huth 1110*fcf5ef2aSThomas Huth static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1, 1111*fcf5ef2aSThomas Huth TCGv arg2, int sign, int compute_ov) 1112*fcf5ef2aSThomas Huth { 1113*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1114*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 1115*fcf5ef2aSThomas Huth TCGv_i32 t2 = tcg_temp_new_i32(); 1116*fcf5ef2aSThomas Huth TCGv_i32 t3 = tcg_temp_new_i32(); 1117*fcf5ef2aSThomas Huth 1118*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, arg1); 1119*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, arg2); 1120*fcf5ef2aSThomas Huth if (sign) { 1121*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN); 1122*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1); 1123*fcf5ef2aSThomas Huth tcg_gen_and_i32(t2, t2, t3); 1124*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0); 1125*fcf5ef2aSThomas Huth tcg_gen_or_i32(t2, t2, t3); 1126*fcf5ef2aSThomas Huth tcg_gen_movi_i32(t3, 0); 1127*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1); 1128*fcf5ef2aSThomas Huth tcg_gen_div_i32(t3, t0, t1); 1129*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(ret, t3); 1130*fcf5ef2aSThomas Huth } else { 1131*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t1, 0); 1132*fcf5ef2aSThomas Huth tcg_gen_movi_i32(t3, 0); 1133*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1); 1134*fcf5ef2aSThomas Huth tcg_gen_divu_i32(t3, t0, t1); 1135*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(ret, t3); 1136*fcf5ef2aSThomas Huth } 1137*fcf5ef2aSThomas Huth if (compute_ov) { 1138*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(cpu_ov, t2); 1139*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 1140*fcf5ef2aSThomas Huth } 1141*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1142*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 1143*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 1144*fcf5ef2aSThomas Huth tcg_temp_free_i32(t3); 1145*fcf5ef2aSThomas Huth 1146*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1147*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, ret); 1148*fcf5ef2aSThomas Huth } 1149*fcf5ef2aSThomas Huth /* Div functions */ 1150*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \ 1151*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1152*fcf5ef2aSThomas Huth { \ 1153*fcf5ef2aSThomas Huth gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \ 1154*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ 1155*fcf5ef2aSThomas Huth sign, compute_ov); \ 1156*fcf5ef2aSThomas Huth } 1157*fcf5ef2aSThomas Huth /* divwu divwu. divwuo divwuo. */ 1158*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0); 1159*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1); 1160*fcf5ef2aSThomas Huth /* divw divw. divwo divwo. */ 1161*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0); 1162*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1); 1163*fcf5ef2aSThomas Huth 1164*fcf5ef2aSThomas Huth /* div[wd]eu[o][.] */ 1165*fcf5ef2aSThomas Huth #define GEN_DIVE(name, hlpr, compute_ov) \ 1166*fcf5ef2aSThomas Huth static void gen_##name(DisasContext *ctx) \ 1167*fcf5ef2aSThomas Huth { \ 1168*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(compute_ov); \ 1169*fcf5ef2aSThomas Huth gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env, \ 1170*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \ 1171*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); \ 1172*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { \ 1173*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \ 1174*fcf5ef2aSThomas Huth } \ 1175*fcf5ef2aSThomas Huth } 1176*fcf5ef2aSThomas Huth 1177*fcf5ef2aSThomas Huth GEN_DIVE(divweu, divweu, 0); 1178*fcf5ef2aSThomas Huth GEN_DIVE(divweuo, divweu, 1); 1179*fcf5ef2aSThomas Huth GEN_DIVE(divwe, divwe, 0); 1180*fcf5ef2aSThomas Huth GEN_DIVE(divweo, divwe, 1); 1181*fcf5ef2aSThomas Huth 1182*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1183*fcf5ef2aSThomas Huth static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1, 1184*fcf5ef2aSThomas Huth TCGv arg2, int sign, int compute_ov) 1185*fcf5ef2aSThomas Huth { 1186*fcf5ef2aSThomas Huth TCGv_i64 t0 = tcg_temp_new_i64(); 1187*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 1188*fcf5ef2aSThomas Huth TCGv_i64 t2 = tcg_temp_new_i64(); 1189*fcf5ef2aSThomas Huth TCGv_i64 t3 = tcg_temp_new_i64(); 1190*fcf5ef2aSThomas Huth 1191*fcf5ef2aSThomas Huth tcg_gen_mov_i64(t0, arg1); 1192*fcf5ef2aSThomas Huth tcg_gen_mov_i64(t1, arg2); 1193*fcf5ef2aSThomas Huth if (sign) { 1194*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN); 1195*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1); 1196*fcf5ef2aSThomas Huth tcg_gen_and_i64(t2, t2, t3); 1197*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0); 1198*fcf5ef2aSThomas Huth tcg_gen_or_i64(t2, t2, t3); 1199*fcf5ef2aSThomas Huth tcg_gen_movi_i64(t3, 0); 1200*fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1); 1201*fcf5ef2aSThomas Huth tcg_gen_div_i64(ret, t0, t1); 1202*fcf5ef2aSThomas Huth } else { 1203*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t1, 0); 1204*fcf5ef2aSThomas Huth tcg_gen_movi_i64(t3, 0); 1205*fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1); 1206*fcf5ef2aSThomas Huth tcg_gen_divu_i64(ret, t0, t1); 1207*fcf5ef2aSThomas Huth } 1208*fcf5ef2aSThomas Huth if (compute_ov) { 1209*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_ov, t2); 1210*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 1211*fcf5ef2aSThomas Huth } 1212*fcf5ef2aSThomas Huth tcg_temp_free_i64(t0); 1213*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 1214*fcf5ef2aSThomas Huth tcg_temp_free_i64(t2); 1215*fcf5ef2aSThomas Huth tcg_temp_free_i64(t3); 1216*fcf5ef2aSThomas Huth 1217*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1218*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, ret); 1219*fcf5ef2aSThomas Huth } 1220*fcf5ef2aSThomas Huth 1221*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \ 1222*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1223*fcf5ef2aSThomas Huth { \ 1224*fcf5ef2aSThomas Huth gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \ 1225*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ 1226*fcf5ef2aSThomas Huth sign, compute_ov); \ 1227*fcf5ef2aSThomas Huth } 1228*fcf5ef2aSThomas Huth /* divwu divwu. divwuo divwuo. */ 1229*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0); 1230*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1); 1231*fcf5ef2aSThomas Huth /* divw divw. divwo divwo. */ 1232*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0); 1233*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1); 1234*fcf5ef2aSThomas Huth 1235*fcf5ef2aSThomas Huth GEN_DIVE(divdeu, divdeu, 0); 1236*fcf5ef2aSThomas Huth GEN_DIVE(divdeuo, divdeu, 1); 1237*fcf5ef2aSThomas Huth GEN_DIVE(divde, divde, 0); 1238*fcf5ef2aSThomas Huth GEN_DIVE(divdeo, divde, 1); 1239*fcf5ef2aSThomas Huth #endif 1240*fcf5ef2aSThomas Huth 1241*fcf5ef2aSThomas Huth static inline void gen_op_arith_modw(DisasContext *ctx, TCGv ret, TCGv arg1, 1242*fcf5ef2aSThomas Huth TCGv arg2, int sign) 1243*fcf5ef2aSThomas Huth { 1244*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1245*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 1246*fcf5ef2aSThomas Huth 1247*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, arg1); 1248*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, arg2); 1249*fcf5ef2aSThomas Huth if (sign) { 1250*fcf5ef2aSThomas Huth TCGv_i32 t2 = tcg_temp_new_i32(); 1251*fcf5ef2aSThomas Huth TCGv_i32 t3 = tcg_temp_new_i32(); 1252*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t2, t0, INT_MIN); 1253*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, -1); 1254*fcf5ef2aSThomas Huth tcg_gen_and_i32(t2, t2, t3); 1255*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, t3, t1, 0); 1256*fcf5ef2aSThomas Huth tcg_gen_or_i32(t2, t2, t3); 1257*fcf5ef2aSThomas Huth tcg_gen_movi_i32(t3, 0); 1258*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, t1, t2, t3, t2, t1); 1259*fcf5ef2aSThomas Huth tcg_gen_rem_i32(t3, t0, t1); 1260*fcf5ef2aSThomas Huth tcg_gen_ext_i32_tl(ret, t3); 1261*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 1262*fcf5ef2aSThomas Huth tcg_temp_free_i32(t3); 1263*fcf5ef2aSThomas Huth } else { 1264*fcf5ef2aSThomas Huth TCGv_i32 t2 = tcg_const_i32(1); 1265*fcf5ef2aSThomas Huth TCGv_i32 t3 = tcg_const_i32(0); 1266*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_EQ, t1, t1, t3, t2, t1); 1267*fcf5ef2aSThomas Huth tcg_gen_remu_i32(t3, t0, t1); 1268*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(ret, t3); 1269*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 1270*fcf5ef2aSThomas Huth tcg_temp_free_i32(t3); 1271*fcf5ef2aSThomas Huth } 1272*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1273*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 1274*fcf5ef2aSThomas Huth } 1275*fcf5ef2aSThomas Huth 1276*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_MODW(name, opc3, sign) \ 1277*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1278*fcf5ef2aSThomas Huth { \ 1279*fcf5ef2aSThomas Huth gen_op_arith_modw(ctx, cpu_gpr[rD(ctx->opcode)], \ 1280*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ 1281*fcf5ef2aSThomas Huth sign); \ 1282*fcf5ef2aSThomas Huth } 1283*fcf5ef2aSThomas Huth 1284*fcf5ef2aSThomas Huth GEN_INT_ARITH_MODW(moduw, 0x08, 0); 1285*fcf5ef2aSThomas Huth GEN_INT_ARITH_MODW(modsw, 0x18, 1); 1286*fcf5ef2aSThomas Huth 1287*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1288*fcf5ef2aSThomas Huth static inline void gen_op_arith_modd(DisasContext *ctx, TCGv ret, TCGv arg1, 1289*fcf5ef2aSThomas Huth TCGv arg2, int sign) 1290*fcf5ef2aSThomas Huth { 1291*fcf5ef2aSThomas Huth TCGv_i64 t0 = tcg_temp_new_i64(); 1292*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 1293*fcf5ef2aSThomas Huth 1294*fcf5ef2aSThomas Huth tcg_gen_mov_i64(t0, arg1); 1295*fcf5ef2aSThomas Huth tcg_gen_mov_i64(t1, arg2); 1296*fcf5ef2aSThomas Huth if (sign) { 1297*fcf5ef2aSThomas Huth TCGv_i64 t2 = tcg_temp_new_i64(); 1298*fcf5ef2aSThomas Huth TCGv_i64 t3 = tcg_temp_new_i64(); 1299*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t2, t0, INT64_MIN); 1300*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, -1); 1301*fcf5ef2aSThomas Huth tcg_gen_and_i64(t2, t2, t3); 1302*fcf5ef2aSThomas Huth tcg_gen_setcondi_i64(TCG_COND_EQ, t3, t1, 0); 1303*fcf5ef2aSThomas Huth tcg_gen_or_i64(t2, t2, t3); 1304*fcf5ef2aSThomas Huth tcg_gen_movi_i64(t3, 0); 1305*fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_NE, t1, t2, t3, t2, t1); 1306*fcf5ef2aSThomas Huth tcg_gen_rem_i64(ret, t0, t1); 1307*fcf5ef2aSThomas Huth tcg_temp_free_i64(t2); 1308*fcf5ef2aSThomas Huth tcg_temp_free_i64(t3); 1309*fcf5ef2aSThomas Huth } else { 1310*fcf5ef2aSThomas Huth TCGv_i64 t2 = tcg_const_i64(1); 1311*fcf5ef2aSThomas Huth TCGv_i64 t3 = tcg_const_i64(0); 1312*fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_EQ, t1, t1, t3, t2, t1); 1313*fcf5ef2aSThomas Huth tcg_gen_remu_i64(ret, t0, t1); 1314*fcf5ef2aSThomas Huth tcg_temp_free_i64(t2); 1315*fcf5ef2aSThomas Huth tcg_temp_free_i64(t3); 1316*fcf5ef2aSThomas Huth } 1317*fcf5ef2aSThomas Huth tcg_temp_free_i64(t0); 1318*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 1319*fcf5ef2aSThomas Huth } 1320*fcf5ef2aSThomas Huth 1321*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_MODD(name, opc3, sign) \ 1322*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1323*fcf5ef2aSThomas Huth { \ 1324*fcf5ef2aSThomas Huth gen_op_arith_modd(ctx, cpu_gpr[rD(ctx->opcode)], \ 1325*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ 1326*fcf5ef2aSThomas Huth sign); \ 1327*fcf5ef2aSThomas Huth } 1328*fcf5ef2aSThomas Huth 1329*fcf5ef2aSThomas Huth GEN_INT_ARITH_MODD(modud, 0x08, 0); 1330*fcf5ef2aSThomas Huth GEN_INT_ARITH_MODD(modsd, 0x18, 1); 1331*fcf5ef2aSThomas Huth #endif 1332*fcf5ef2aSThomas Huth 1333*fcf5ef2aSThomas Huth /* mulhw mulhw. */ 1334*fcf5ef2aSThomas Huth static void gen_mulhw(DisasContext *ctx) 1335*fcf5ef2aSThomas Huth { 1336*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1337*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 1338*fcf5ef2aSThomas Huth 1339*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); 1340*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); 1341*fcf5ef2aSThomas Huth tcg_gen_muls2_i32(t0, t1, t0, t1); 1342*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); 1343*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1344*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 1345*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1346*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1347*fcf5ef2aSThomas Huth } 1348*fcf5ef2aSThomas Huth 1349*fcf5ef2aSThomas Huth /* mulhwu mulhwu. */ 1350*fcf5ef2aSThomas Huth static void gen_mulhwu(DisasContext *ctx) 1351*fcf5ef2aSThomas Huth { 1352*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1353*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 1354*fcf5ef2aSThomas Huth 1355*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); 1356*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); 1357*fcf5ef2aSThomas Huth tcg_gen_mulu2_i32(t0, t1, t0, t1); 1358*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); 1359*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1360*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 1361*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1362*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1363*fcf5ef2aSThomas Huth } 1364*fcf5ef2aSThomas Huth 1365*fcf5ef2aSThomas Huth /* mullw mullw. */ 1366*fcf5ef2aSThomas Huth static void gen_mullw(DisasContext *ctx) 1367*fcf5ef2aSThomas Huth { 1368*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1369*fcf5ef2aSThomas Huth TCGv_i64 t0, t1; 1370*fcf5ef2aSThomas Huth t0 = tcg_temp_new_i64(); 1371*fcf5ef2aSThomas Huth t1 = tcg_temp_new_i64(); 1372*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]); 1373*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]); 1374*fcf5ef2aSThomas Huth tcg_gen_mul_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); 1375*fcf5ef2aSThomas Huth tcg_temp_free(t0); 1376*fcf5ef2aSThomas Huth tcg_temp_free(t1); 1377*fcf5ef2aSThomas Huth #else 1378*fcf5ef2aSThomas Huth tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1379*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 1380*fcf5ef2aSThomas Huth #endif 1381*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1382*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1383*fcf5ef2aSThomas Huth } 1384*fcf5ef2aSThomas Huth 1385*fcf5ef2aSThomas Huth /* mullwo mullwo. */ 1386*fcf5ef2aSThomas Huth static void gen_mullwo(DisasContext *ctx) 1387*fcf5ef2aSThomas Huth { 1388*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1389*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 1390*fcf5ef2aSThomas Huth 1391*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); 1392*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); 1393*fcf5ef2aSThomas Huth tcg_gen_muls2_i32(t0, t1, t0, t1); 1394*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1395*fcf5ef2aSThomas Huth tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); 1396*fcf5ef2aSThomas Huth #else 1397*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0); 1398*fcf5ef2aSThomas Huth #endif 1399*fcf5ef2aSThomas Huth 1400*fcf5ef2aSThomas Huth tcg_gen_sari_i32(t0, t0, 31); 1401*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1); 1402*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(cpu_ov, t0); 1403*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 1404*fcf5ef2aSThomas Huth 1405*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1406*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 1407*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1408*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1409*fcf5ef2aSThomas Huth } 1410*fcf5ef2aSThomas Huth 1411*fcf5ef2aSThomas Huth /* mulli */ 1412*fcf5ef2aSThomas Huth static void gen_mulli(DisasContext *ctx) 1413*fcf5ef2aSThomas Huth { 1414*fcf5ef2aSThomas Huth tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1415*fcf5ef2aSThomas Huth SIMM(ctx->opcode)); 1416*fcf5ef2aSThomas Huth } 1417*fcf5ef2aSThomas Huth 1418*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1419*fcf5ef2aSThomas Huth /* mulhd mulhd. */ 1420*fcf5ef2aSThomas Huth static void gen_mulhd(DisasContext *ctx) 1421*fcf5ef2aSThomas Huth { 1422*fcf5ef2aSThomas Huth TCGv lo = tcg_temp_new(); 1423*fcf5ef2aSThomas Huth tcg_gen_muls2_tl(lo, cpu_gpr[rD(ctx->opcode)], 1424*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 1425*fcf5ef2aSThomas Huth tcg_temp_free(lo); 1426*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 1427*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1428*fcf5ef2aSThomas Huth } 1429*fcf5ef2aSThomas Huth } 1430*fcf5ef2aSThomas Huth 1431*fcf5ef2aSThomas Huth /* mulhdu mulhdu. */ 1432*fcf5ef2aSThomas Huth static void gen_mulhdu(DisasContext *ctx) 1433*fcf5ef2aSThomas Huth { 1434*fcf5ef2aSThomas Huth TCGv lo = tcg_temp_new(); 1435*fcf5ef2aSThomas Huth tcg_gen_mulu2_tl(lo, cpu_gpr[rD(ctx->opcode)], 1436*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 1437*fcf5ef2aSThomas Huth tcg_temp_free(lo); 1438*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 1439*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1440*fcf5ef2aSThomas Huth } 1441*fcf5ef2aSThomas Huth } 1442*fcf5ef2aSThomas Huth 1443*fcf5ef2aSThomas Huth /* mulld mulld. */ 1444*fcf5ef2aSThomas Huth static void gen_mulld(DisasContext *ctx) 1445*fcf5ef2aSThomas Huth { 1446*fcf5ef2aSThomas Huth tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1447*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 1448*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1449*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1450*fcf5ef2aSThomas Huth } 1451*fcf5ef2aSThomas Huth 1452*fcf5ef2aSThomas Huth /* mulldo mulldo. */ 1453*fcf5ef2aSThomas Huth static void gen_mulldo(DisasContext *ctx) 1454*fcf5ef2aSThomas Huth { 1455*fcf5ef2aSThomas Huth TCGv_i64 t0 = tcg_temp_new_i64(); 1456*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 1457*fcf5ef2aSThomas Huth 1458*fcf5ef2aSThomas Huth tcg_gen_muls2_i64(t0, t1, cpu_gpr[rA(ctx->opcode)], 1459*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 1460*fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_gpr[rD(ctx->opcode)], t0); 1461*fcf5ef2aSThomas Huth 1462*fcf5ef2aSThomas Huth tcg_gen_sari_i64(t0, t0, 63); 1463*fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1); 1464*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov); 1465*fcf5ef2aSThomas Huth 1466*fcf5ef2aSThomas Huth tcg_temp_free_i64(t0); 1467*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 1468*fcf5ef2aSThomas Huth 1469*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 1470*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 1471*fcf5ef2aSThomas Huth } 1472*fcf5ef2aSThomas Huth } 1473*fcf5ef2aSThomas Huth #endif 1474*fcf5ef2aSThomas Huth 1475*fcf5ef2aSThomas Huth /* Common subf function */ 1476*fcf5ef2aSThomas Huth static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, 1477*fcf5ef2aSThomas Huth TCGv arg2, bool add_ca, bool compute_ca, 1478*fcf5ef2aSThomas Huth bool compute_ov, bool compute_rc0) 1479*fcf5ef2aSThomas Huth { 1480*fcf5ef2aSThomas Huth TCGv t0 = ret; 1481*fcf5ef2aSThomas Huth 1482*fcf5ef2aSThomas Huth if (compute_ca || compute_ov) { 1483*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 1484*fcf5ef2aSThomas Huth } 1485*fcf5ef2aSThomas Huth 1486*fcf5ef2aSThomas Huth if (compute_ca) { 1487*fcf5ef2aSThomas Huth /* dest = ~arg1 + arg2 [+ ca]. */ 1488*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 1489*fcf5ef2aSThomas Huth /* Caution: a non-obvious corner case of the spec is that we 1490*fcf5ef2aSThomas Huth must produce the *entire* 64-bit addition, but produce the 1491*fcf5ef2aSThomas Huth carry into bit 32. */ 1492*fcf5ef2aSThomas Huth TCGv inv1 = tcg_temp_new(); 1493*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 1494*fcf5ef2aSThomas Huth tcg_gen_not_tl(inv1, arg1); 1495*fcf5ef2aSThomas Huth if (add_ca) { 1496*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, arg2, cpu_ca); 1497*fcf5ef2aSThomas Huth } else { 1498*fcf5ef2aSThomas Huth tcg_gen_addi_tl(t0, arg2, 1); 1499*fcf5ef2aSThomas Huth } 1500*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */ 1501*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, t0, inv1); 1502*fcf5ef2aSThomas Huth tcg_temp_free(inv1); 1503*fcf5ef2aSThomas Huth tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */ 1504*fcf5ef2aSThomas Huth tcg_temp_free(t1); 1505*fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */ 1506*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_ca, cpu_ca, 1); 1507*fcf5ef2aSThomas Huth } else if (add_ca) { 1508*fcf5ef2aSThomas Huth TCGv zero, inv1 = tcg_temp_new(); 1509*fcf5ef2aSThomas Huth tcg_gen_not_tl(inv1, arg1); 1510*fcf5ef2aSThomas Huth zero = tcg_const_tl(0); 1511*fcf5ef2aSThomas Huth tcg_gen_add2_tl(t0, cpu_ca, arg2, zero, cpu_ca, zero); 1512*fcf5ef2aSThomas Huth tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, inv1, zero); 1513*fcf5ef2aSThomas Huth tcg_temp_free(zero); 1514*fcf5ef2aSThomas Huth tcg_temp_free(inv1); 1515*fcf5ef2aSThomas Huth } else { 1516*fcf5ef2aSThomas Huth tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1); 1517*fcf5ef2aSThomas Huth tcg_gen_sub_tl(t0, arg2, arg1); 1518*fcf5ef2aSThomas Huth } 1519*fcf5ef2aSThomas Huth } else if (add_ca) { 1520*fcf5ef2aSThomas Huth /* Since we're ignoring carry-out, we can simplify the 1521*fcf5ef2aSThomas Huth standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1. */ 1522*fcf5ef2aSThomas Huth tcg_gen_sub_tl(t0, arg2, arg1); 1523*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, t0, cpu_ca); 1524*fcf5ef2aSThomas Huth tcg_gen_subi_tl(t0, t0, 1); 1525*fcf5ef2aSThomas Huth } else { 1526*fcf5ef2aSThomas Huth tcg_gen_sub_tl(t0, arg2, arg1); 1527*fcf5ef2aSThomas Huth } 1528*fcf5ef2aSThomas Huth 1529*fcf5ef2aSThomas Huth if (compute_ov) { 1530*fcf5ef2aSThomas Huth gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1); 1531*fcf5ef2aSThomas Huth } 1532*fcf5ef2aSThomas Huth if (unlikely(compute_rc0)) { 1533*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t0); 1534*fcf5ef2aSThomas Huth } 1535*fcf5ef2aSThomas Huth 1536*fcf5ef2aSThomas Huth if (!TCGV_EQUAL(t0, ret)) { 1537*fcf5ef2aSThomas Huth tcg_gen_mov_tl(ret, t0); 1538*fcf5ef2aSThomas Huth tcg_temp_free(t0); 1539*fcf5ef2aSThomas Huth } 1540*fcf5ef2aSThomas Huth } 1541*fcf5ef2aSThomas Huth /* Sub functions with Two operands functions */ 1542*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \ 1543*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1544*fcf5ef2aSThomas Huth { \ 1545*fcf5ef2aSThomas Huth gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \ 1546*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \ 1547*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \ 1548*fcf5ef2aSThomas Huth } 1549*fcf5ef2aSThomas Huth /* Sub functions with one operand and one immediate */ 1550*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \ 1551*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov) \ 1552*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1553*fcf5ef2aSThomas Huth { \ 1554*fcf5ef2aSThomas Huth TCGv t0 = tcg_const_tl(const_val); \ 1555*fcf5ef2aSThomas Huth gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \ 1556*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], t0, \ 1557*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \ 1558*fcf5ef2aSThomas Huth tcg_temp_free(t0); \ 1559*fcf5ef2aSThomas Huth } 1560*fcf5ef2aSThomas Huth /* subf subf. subfo subfo. */ 1561*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0) 1562*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1) 1563*fcf5ef2aSThomas Huth /* subfc subfc. subfco subfco. */ 1564*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0) 1565*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1) 1566*fcf5ef2aSThomas Huth /* subfe subfe. subfeo subfo. */ 1567*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0) 1568*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1) 1569*fcf5ef2aSThomas Huth /* subfme subfme. subfmeo subfmeo. */ 1570*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0) 1571*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1) 1572*fcf5ef2aSThomas Huth /* subfze subfze. subfzeo subfzeo.*/ 1573*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0) 1574*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1) 1575*fcf5ef2aSThomas Huth 1576*fcf5ef2aSThomas Huth /* subfic */ 1577*fcf5ef2aSThomas Huth static void gen_subfic(DisasContext *ctx) 1578*fcf5ef2aSThomas Huth { 1579*fcf5ef2aSThomas Huth TCGv c = tcg_const_tl(SIMM(ctx->opcode)); 1580*fcf5ef2aSThomas Huth gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1581*fcf5ef2aSThomas Huth c, 0, 1, 0, 0); 1582*fcf5ef2aSThomas Huth tcg_temp_free(c); 1583*fcf5ef2aSThomas Huth } 1584*fcf5ef2aSThomas Huth 1585*fcf5ef2aSThomas Huth /* neg neg. nego nego. */ 1586*fcf5ef2aSThomas Huth static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov) 1587*fcf5ef2aSThomas Huth { 1588*fcf5ef2aSThomas Huth TCGv zero = tcg_const_tl(0); 1589*fcf5ef2aSThomas Huth gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1590*fcf5ef2aSThomas Huth zero, 0, 0, compute_ov, Rc(ctx->opcode)); 1591*fcf5ef2aSThomas Huth tcg_temp_free(zero); 1592*fcf5ef2aSThomas Huth } 1593*fcf5ef2aSThomas Huth 1594*fcf5ef2aSThomas Huth static void gen_neg(DisasContext *ctx) 1595*fcf5ef2aSThomas Huth { 1596*fcf5ef2aSThomas Huth gen_op_arith_neg(ctx, 0); 1597*fcf5ef2aSThomas Huth } 1598*fcf5ef2aSThomas Huth 1599*fcf5ef2aSThomas Huth static void gen_nego(DisasContext *ctx) 1600*fcf5ef2aSThomas Huth { 1601*fcf5ef2aSThomas Huth gen_op_arith_neg(ctx, 1); 1602*fcf5ef2aSThomas Huth } 1603*fcf5ef2aSThomas Huth 1604*fcf5ef2aSThomas Huth /*** Integer logical ***/ 1605*fcf5ef2aSThomas Huth #define GEN_LOGICAL2(name, tcg_op, opc, type) \ 1606*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1607*fcf5ef2aSThomas Huth { \ 1608*fcf5ef2aSThomas Huth tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \ 1609*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); \ 1610*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) \ 1611*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \ 1612*fcf5ef2aSThomas Huth } 1613*fcf5ef2aSThomas Huth 1614*fcf5ef2aSThomas Huth #define GEN_LOGICAL1(name, tcg_op, opc, type) \ 1615*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 1616*fcf5ef2aSThomas Huth { \ 1617*fcf5ef2aSThomas Huth tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \ 1618*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) \ 1619*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \ 1620*fcf5ef2aSThomas Huth } 1621*fcf5ef2aSThomas Huth 1622*fcf5ef2aSThomas Huth /* and & and. */ 1623*fcf5ef2aSThomas Huth GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER); 1624*fcf5ef2aSThomas Huth /* andc & andc. */ 1625*fcf5ef2aSThomas Huth GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER); 1626*fcf5ef2aSThomas Huth 1627*fcf5ef2aSThomas Huth /* andi. */ 1628*fcf5ef2aSThomas Huth static void gen_andi_(DisasContext *ctx) 1629*fcf5ef2aSThomas Huth { 1630*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode)); 1631*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1632*fcf5ef2aSThomas Huth } 1633*fcf5ef2aSThomas Huth 1634*fcf5ef2aSThomas Huth /* andis. */ 1635*fcf5ef2aSThomas Huth static void gen_andis_(DisasContext *ctx) 1636*fcf5ef2aSThomas Huth { 1637*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16); 1638*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1639*fcf5ef2aSThomas Huth } 1640*fcf5ef2aSThomas Huth 1641*fcf5ef2aSThomas Huth /* cntlzw */ 1642*fcf5ef2aSThomas Huth static void gen_cntlzw(DisasContext *ctx) 1643*fcf5ef2aSThomas Huth { 1644*fcf5ef2aSThomas Huth gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1645*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1646*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1647*fcf5ef2aSThomas Huth } 1648*fcf5ef2aSThomas Huth 1649*fcf5ef2aSThomas Huth /* cnttzw */ 1650*fcf5ef2aSThomas Huth static void gen_cnttzw(DisasContext *ctx) 1651*fcf5ef2aSThomas Huth { 1652*fcf5ef2aSThomas Huth gen_helper_cnttzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1653*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 1654*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1655*fcf5ef2aSThomas Huth } 1656*fcf5ef2aSThomas Huth } 1657*fcf5ef2aSThomas Huth 1658*fcf5ef2aSThomas Huth /* eqv & eqv. */ 1659*fcf5ef2aSThomas Huth GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER); 1660*fcf5ef2aSThomas Huth /* extsb & extsb. */ 1661*fcf5ef2aSThomas Huth GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER); 1662*fcf5ef2aSThomas Huth /* extsh & extsh. */ 1663*fcf5ef2aSThomas Huth GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER); 1664*fcf5ef2aSThomas Huth /* nand & nand. */ 1665*fcf5ef2aSThomas Huth GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER); 1666*fcf5ef2aSThomas Huth /* nor & nor. */ 1667*fcf5ef2aSThomas Huth GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER); 1668*fcf5ef2aSThomas Huth 1669*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) 1670*fcf5ef2aSThomas Huth static void gen_pause(DisasContext *ctx) 1671*fcf5ef2aSThomas Huth { 1672*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(0); 1673*fcf5ef2aSThomas Huth tcg_gen_st_i32(t0, cpu_env, 1674*fcf5ef2aSThomas Huth -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted)); 1675*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1676*fcf5ef2aSThomas Huth 1677*fcf5ef2aSThomas Huth /* Stop translation, this gives other CPUs a chance to run */ 1678*fcf5ef2aSThomas Huth gen_exception_nip(ctx, EXCP_HLT, ctx->nip); 1679*fcf5ef2aSThomas Huth } 1680*fcf5ef2aSThomas Huth #endif /* defined(TARGET_PPC64) */ 1681*fcf5ef2aSThomas Huth 1682*fcf5ef2aSThomas Huth /* or & or. */ 1683*fcf5ef2aSThomas Huth static void gen_or(DisasContext *ctx) 1684*fcf5ef2aSThomas Huth { 1685*fcf5ef2aSThomas Huth int rs, ra, rb; 1686*fcf5ef2aSThomas Huth 1687*fcf5ef2aSThomas Huth rs = rS(ctx->opcode); 1688*fcf5ef2aSThomas Huth ra = rA(ctx->opcode); 1689*fcf5ef2aSThomas Huth rb = rB(ctx->opcode); 1690*fcf5ef2aSThomas Huth /* Optimisation for mr. ri case */ 1691*fcf5ef2aSThomas Huth if (rs != ra || rs != rb) { 1692*fcf5ef2aSThomas Huth if (rs != rb) 1693*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]); 1694*fcf5ef2aSThomas Huth else 1695*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]); 1696*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1697*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[ra]); 1698*fcf5ef2aSThomas Huth } else if (unlikely(Rc(ctx->opcode) != 0)) { 1699*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rs]); 1700*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1701*fcf5ef2aSThomas Huth } else if (rs != 0) { /* 0 is nop */ 1702*fcf5ef2aSThomas Huth int prio = 0; 1703*fcf5ef2aSThomas Huth 1704*fcf5ef2aSThomas Huth switch (rs) { 1705*fcf5ef2aSThomas Huth case 1: 1706*fcf5ef2aSThomas Huth /* Set process priority to low */ 1707*fcf5ef2aSThomas Huth prio = 2; 1708*fcf5ef2aSThomas Huth break; 1709*fcf5ef2aSThomas Huth case 6: 1710*fcf5ef2aSThomas Huth /* Set process priority to medium-low */ 1711*fcf5ef2aSThomas Huth prio = 3; 1712*fcf5ef2aSThomas Huth break; 1713*fcf5ef2aSThomas Huth case 2: 1714*fcf5ef2aSThomas Huth /* Set process priority to normal */ 1715*fcf5ef2aSThomas Huth prio = 4; 1716*fcf5ef2aSThomas Huth break; 1717*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1718*fcf5ef2aSThomas Huth case 31: 1719*fcf5ef2aSThomas Huth if (!ctx->pr) { 1720*fcf5ef2aSThomas Huth /* Set process priority to very low */ 1721*fcf5ef2aSThomas Huth prio = 1; 1722*fcf5ef2aSThomas Huth } 1723*fcf5ef2aSThomas Huth break; 1724*fcf5ef2aSThomas Huth case 5: 1725*fcf5ef2aSThomas Huth if (!ctx->pr) { 1726*fcf5ef2aSThomas Huth /* Set process priority to medium-hight */ 1727*fcf5ef2aSThomas Huth prio = 5; 1728*fcf5ef2aSThomas Huth } 1729*fcf5ef2aSThomas Huth break; 1730*fcf5ef2aSThomas Huth case 3: 1731*fcf5ef2aSThomas Huth if (!ctx->pr) { 1732*fcf5ef2aSThomas Huth /* Set process priority to high */ 1733*fcf5ef2aSThomas Huth prio = 6; 1734*fcf5ef2aSThomas Huth } 1735*fcf5ef2aSThomas Huth break; 1736*fcf5ef2aSThomas Huth case 7: 1737*fcf5ef2aSThomas Huth if (ctx->hv && !ctx->pr) { 1738*fcf5ef2aSThomas Huth /* Set process priority to very high */ 1739*fcf5ef2aSThomas Huth prio = 7; 1740*fcf5ef2aSThomas Huth } 1741*fcf5ef2aSThomas Huth break; 1742*fcf5ef2aSThomas Huth #endif 1743*fcf5ef2aSThomas Huth default: 1744*fcf5ef2aSThomas Huth break; 1745*fcf5ef2aSThomas Huth } 1746*fcf5ef2aSThomas Huth if (prio) { 1747*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 1748*fcf5ef2aSThomas Huth gen_load_spr(t0, SPR_PPR); 1749*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL); 1750*fcf5ef2aSThomas Huth tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50); 1751*fcf5ef2aSThomas Huth gen_store_spr(SPR_PPR, t0); 1752*fcf5ef2aSThomas Huth tcg_temp_free(t0); 1753*fcf5ef2aSThomas Huth } 1754*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1755*fcf5ef2aSThomas Huth /* Pause out of TCG otherwise spin loops with smt_low eat too much 1756*fcf5ef2aSThomas Huth * CPU and the kernel hangs. This applies to all encodings other 1757*fcf5ef2aSThomas Huth * than no-op, e.g., miso(rs=26), yield(27), mdoio(29), mdoom(30), 1758*fcf5ef2aSThomas Huth * and all currently undefined. 1759*fcf5ef2aSThomas Huth */ 1760*fcf5ef2aSThomas Huth gen_pause(ctx); 1761*fcf5ef2aSThomas Huth #endif 1762*fcf5ef2aSThomas Huth #endif 1763*fcf5ef2aSThomas Huth } 1764*fcf5ef2aSThomas Huth } 1765*fcf5ef2aSThomas Huth /* orc & orc. */ 1766*fcf5ef2aSThomas Huth GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER); 1767*fcf5ef2aSThomas Huth 1768*fcf5ef2aSThomas Huth /* xor & xor. */ 1769*fcf5ef2aSThomas Huth static void gen_xor(DisasContext *ctx) 1770*fcf5ef2aSThomas Huth { 1771*fcf5ef2aSThomas Huth /* Optimisation for "set to zero" case */ 1772*fcf5ef2aSThomas Huth if (rS(ctx->opcode) != rB(ctx->opcode)) 1773*fcf5ef2aSThomas Huth tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 1774*fcf5ef2aSThomas Huth else 1775*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); 1776*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1777*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1778*fcf5ef2aSThomas Huth } 1779*fcf5ef2aSThomas Huth 1780*fcf5ef2aSThomas Huth /* ori */ 1781*fcf5ef2aSThomas Huth static void gen_ori(DisasContext *ctx) 1782*fcf5ef2aSThomas Huth { 1783*fcf5ef2aSThomas Huth target_ulong uimm = UIMM(ctx->opcode); 1784*fcf5ef2aSThomas Huth 1785*fcf5ef2aSThomas Huth if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { 1786*fcf5ef2aSThomas Huth return; 1787*fcf5ef2aSThomas Huth } 1788*fcf5ef2aSThomas Huth tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm); 1789*fcf5ef2aSThomas Huth } 1790*fcf5ef2aSThomas Huth 1791*fcf5ef2aSThomas Huth /* oris */ 1792*fcf5ef2aSThomas Huth static void gen_oris(DisasContext *ctx) 1793*fcf5ef2aSThomas Huth { 1794*fcf5ef2aSThomas Huth target_ulong uimm = UIMM(ctx->opcode); 1795*fcf5ef2aSThomas Huth 1796*fcf5ef2aSThomas Huth if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { 1797*fcf5ef2aSThomas Huth /* NOP */ 1798*fcf5ef2aSThomas Huth return; 1799*fcf5ef2aSThomas Huth } 1800*fcf5ef2aSThomas Huth tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16); 1801*fcf5ef2aSThomas Huth } 1802*fcf5ef2aSThomas Huth 1803*fcf5ef2aSThomas Huth /* xori */ 1804*fcf5ef2aSThomas Huth static void gen_xori(DisasContext *ctx) 1805*fcf5ef2aSThomas Huth { 1806*fcf5ef2aSThomas Huth target_ulong uimm = UIMM(ctx->opcode); 1807*fcf5ef2aSThomas Huth 1808*fcf5ef2aSThomas Huth if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { 1809*fcf5ef2aSThomas Huth /* NOP */ 1810*fcf5ef2aSThomas Huth return; 1811*fcf5ef2aSThomas Huth } 1812*fcf5ef2aSThomas Huth tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm); 1813*fcf5ef2aSThomas Huth } 1814*fcf5ef2aSThomas Huth 1815*fcf5ef2aSThomas Huth /* xoris */ 1816*fcf5ef2aSThomas Huth static void gen_xoris(DisasContext *ctx) 1817*fcf5ef2aSThomas Huth { 1818*fcf5ef2aSThomas Huth target_ulong uimm = UIMM(ctx->opcode); 1819*fcf5ef2aSThomas Huth 1820*fcf5ef2aSThomas Huth if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) { 1821*fcf5ef2aSThomas Huth /* NOP */ 1822*fcf5ef2aSThomas Huth return; 1823*fcf5ef2aSThomas Huth } 1824*fcf5ef2aSThomas Huth tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16); 1825*fcf5ef2aSThomas Huth } 1826*fcf5ef2aSThomas Huth 1827*fcf5ef2aSThomas Huth /* popcntb : PowerPC 2.03 specification */ 1828*fcf5ef2aSThomas Huth static void gen_popcntb(DisasContext *ctx) 1829*fcf5ef2aSThomas Huth { 1830*fcf5ef2aSThomas Huth gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1831*fcf5ef2aSThomas Huth } 1832*fcf5ef2aSThomas Huth 1833*fcf5ef2aSThomas Huth static void gen_popcntw(DisasContext *ctx) 1834*fcf5ef2aSThomas Huth { 1835*fcf5ef2aSThomas Huth gen_helper_popcntw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1836*fcf5ef2aSThomas Huth } 1837*fcf5ef2aSThomas Huth 1838*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1839*fcf5ef2aSThomas Huth /* popcntd: PowerPC 2.06 specification */ 1840*fcf5ef2aSThomas Huth static void gen_popcntd(DisasContext *ctx) 1841*fcf5ef2aSThomas Huth { 1842*fcf5ef2aSThomas Huth gen_helper_popcntd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1843*fcf5ef2aSThomas Huth } 1844*fcf5ef2aSThomas Huth #endif 1845*fcf5ef2aSThomas Huth 1846*fcf5ef2aSThomas Huth /* prtyw: PowerPC 2.05 specification */ 1847*fcf5ef2aSThomas Huth static void gen_prtyw(DisasContext *ctx) 1848*fcf5ef2aSThomas Huth { 1849*fcf5ef2aSThomas Huth TCGv ra = cpu_gpr[rA(ctx->opcode)]; 1850*fcf5ef2aSThomas Huth TCGv rs = cpu_gpr[rS(ctx->opcode)]; 1851*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 1852*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, rs, 16); 1853*fcf5ef2aSThomas Huth tcg_gen_xor_tl(ra, rs, t0); 1854*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, ra, 8); 1855*fcf5ef2aSThomas Huth tcg_gen_xor_tl(ra, ra, t0); 1856*fcf5ef2aSThomas Huth tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL); 1857*fcf5ef2aSThomas Huth tcg_temp_free(t0); 1858*fcf5ef2aSThomas Huth } 1859*fcf5ef2aSThomas Huth 1860*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1861*fcf5ef2aSThomas Huth /* prtyd: PowerPC 2.05 specification */ 1862*fcf5ef2aSThomas Huth static void gen_prtyd(DisasContext *ctx) 1863*fcf5ef2aSThomas Huth { 1864*fcf5ef2aSThomas Huth TCGv ra = cpu_gpr[rA(ctx->opcode)]; 1865*fcf5ef2aSThomas Huth TCGv rs = cpu_gpr[rS(ctx->opcode)]; 1866*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 1867*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, rs, 32); 1868*fcf5ef2aSThomas Huth tcg_gen_xor_tl(ra, rs, t0); 1869*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, ra, 16); 1870*fcf5ef2aSThomas Huth tcg_gen_xor_tl(ra, ra, t0); 1871*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, ra, 8); 1872*fcf5ef2aSThomas Huth tcg_gen_xor_tl(ra, ra, t0); 1873*fcf5ef2aSThomas Huth tcg_gen_andi_tl(ra, ra, 1); 1874*fcf5ef2aSThomas Huth tcg_temp_free(t0); 1875*fcf5ef2aSThomas Huth } 1876*fcf5ef2aSThomas Huth #endif 1877*fcf5ef2aSThomas Huth 1878*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1879*fcf5ef2aSThomas Huth /* bpermd */ 1880*fcf5ef2aSThomas Huth static void gen_bpermd(DisasContext *ctx) 1881*fcf5ef2aSThomas Huth { 1882*fcf5ef2aSThomas Huth gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)], 1883*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 1884*fcf5ef2aSThomas Huth } 1885*fcf5ef2aSThomas Huth #endif 1886*fcf5ef2aSThomas Huth 1887*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1888*fcf5ef2aSThomas Huth /* extsw & extsw. */ 1889*fcf5ef2aSThomas Huth GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B); 1890*fcf5ef2aSThomas Huth 1891*fcf5ef2aSThomas Huth /* cntlzd */ 1892*fcf5ef2aSThomas Huth static void gen_cntlzd(DisasContext *ctx) 1893*fcf5ef2aSThomas Huth { 1894*fcf5ef2aSThomas Huth gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1895*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 1896*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1897*fcf5ef2aSThomas Huth } 1898*fcf5ef2aSThomas Huth 1899*fcf5ef2aSThomas Huth /* cnttzd */ 1900*fcf5ef2aSThomas Huth static void gen_cnttzd(DisasContext *ctx) 1901*fcf5ef2aSThomas Huth { 1902*fcf5ef2aSThomas Huth gen_helper_cnttzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); 1903*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 1904*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 1905*fcf5ef2aSThomas Huth } 1906*fcf5ef2aSThomas Huth } 1907*fcf5ef2aSThomas Huth 1908*fcf5ef2aSThomas Huth /* darn */ 1909*fcf5ef2aSThomas Huth static void gen_darn(DisasContext *ctx) 1910*fcf5ef2aSThomas Huth { 1911*fcf5ef2aSThomas Huth int l = L(ctx->opcode); 1912*fcf5ef2aSThomas Huth 1913*fcf5ef2aSThomas Huth if (l == 0) { 1914*fcf5ef2aSThomas Huth gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]); 1915*fcf5ef2aSThomas Huth } else if (l <= 2) { 1916*fcf5ef2aSThomas Huth /* Return 64-bit random for both CRN and RRN */ 1917*fcf5ef2aSThomas Huth gen_helper_darn64(cpu_gpr[rD(ctx->opcode)]); 1918*fcf5ef2aSThomas Huth } else { 1919*fcf5ef2aSThomas Huth tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1); 1920*fcf5ef2aSThomas Huth } 1921*fcf5ef2aSThomas Huth } 1922*fcf5ef2aSThomas Huth #endif 1923*fcf5ef2aSThomas Huth 1924*fcf5ef2aSThomas Huth /*** Integer rotate ***/ 1925*fcf5ef2aSThomas Huth 1926*fcf5ef2aSThomas Huth /* rlwimi & rlwimi. */ 1927*fcf5ef2aSThomas Huth static void gen_rlwimi(DisasContext *ctx) 1928*fcf5ef2aSThomas Huth { 1929*fcf5ef2aSThomas Huth TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; 1930*fcf5ef2aSThomas Huth TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; 1931*fcf5ef2aSThomas Huth uint32_t sh = SH(ctx->opcode); 1932*fcf5ef2aSThomas Huth uint32_t mb = MB(ctx->opcode); 1933*fcf5ef2aSThomas Huth uint32_t me = ME(ctx->opcode); 1934*fcf5ef2aSThomas Huth 1935*fcf5ef2aSThomas Huth if (sh == (31-me) && mb <= me) { 1936*fcf5ef2aSThomas Huth tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1); 1937*fcf5ef2aSThomas Huth } else { 1938*fcf5ef2aSThomas Huth target_ulong mask; 1939*fcf5ef2aSThomas Huth TCGv t1; 1940*fcf5ef2aSThomas Huth 1941*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1942*fcf5ef2aSThomas Huth mb += 32; 1943*fcf5ef2aSThomas Huth me += 32; 1944*fcf5ef2aSThomas Huth #endif 1945*fcf5ef2aSThomas Huth mask = MASK(mb, me); 1946*fcf5ef2aSThomas Huth 1947*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 1948*fcf5ef2aSThomas Huth if (mask <= 0xffffffffu) { 1949*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1950*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, t_rs); 1951*fcf5ef2aSThomas Huth tcg_gen_rotli_i32(t0, t0, sh); 1952*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(t1, t0); 1953*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 1954*fcf5ef2aSThomas Huth } else { 1955*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1956*fcf5ef2aSThomas Huth tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32); 1957*fcf5ef2aSThomas Huth tcg_gen_rotli_i64(t1, t1, sh); 1958*fcf5ef2aSThomas Huth #else 1959*fcf5ef2aSThomas Huth g_assert_not_reached(); 1960*fcf5ef2aSThomas Huth #endif 1961*fcf5ef2aSThomas Huth } 1962*fcf5ef2aSThomas Huth 1963*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, t1, mask); 1964*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t_ra, t_ra, ~mask); 1965*fcf5ef2aSThomas Huth tcg_gen_or_tl(t_ra, t_ra, t1); 1966*fcf5ef2aSThomas Huth tcg_temp_free(t1); 1967*fcf5ef2aSThomas Huth } 1968*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 1969*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t_ra); 1970*fcf5ef2aSThomas Huth } 1971*fcf5ef2aSThomas Huth } 1972*fcf5ef2aSThomas Huth 1973*fcf5ef2aSThomas Huth /* rlwinm & rlwinm. */ 1974*fcf5ef2aSThomas Huth static void gen_rlwinm(DisasContext *ctx) 1975*fcf5ef2aSThomas Huth { 1976*fcf5ef2aSThomas Huth TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; 1977*fcf5ef2aSThomas Huth TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; 1978*fcf5ef2aSThomas Huth uint32_t sh = SH(ctx->opcode); 1979*fcf5ef2aSThomas Huth uint32_t mb = MB(ctx->opcode); 1980*fcf5ef2aSThomas Huth uint32_t me = ME(ctx->opcode); 1981*fcf5ef2aSThomas Huth 1982*fcf5ef2aSThomas Huth if (mb == 0 && me == (31 - sh)) { 1983*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t_ra, t_rs, sh); 1984*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(t_ra, t_ra); 1985*fcf5ef2aSThomas Huth } else if (sh != 0 && me == 31 && sh == (32 - mb)) { 1986*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(t_ra, t_rs); 1987*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t_ra, t_ra, mb); 1988*fcf5ef2aSThomas Huth } else { 1989*fcf5ef2aSThomas Huth target_ulong mask; 1990*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 1991*fcf5ef2aSThomas Huth mb += 32; 1992*fcf5ef2aSThomas Huth me += 32; 1993*fcf5ef2aSThomas Huth #endif 1994*fcf5ef2aSThomas Huth mask = MASK(mb, me); 1995*fcf5ef2aSThomas Huth 1996*fcf5ef2aSThomas Huth if (mask <= 0xffffffffu) { 1997*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 1998*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, t_rs); 1999*fcf5ef2aSThomas Huth tcg_gen_rotli_i32(t0, t0, sh); 2000*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t0, t0, mask); 2001*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(t_ra, t0); 2002*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 2003*fcf5ef2aSThomas Huth } else { 2004*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2005*fcf5ef2aSThomas Huth tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32); 2006*fcf5ef2aSThomas Huth tcg_gen_rotli_i64(t_ra, t_ra, sh); 2007*fcf5ef2aSThomas Huth tcg_gen_andi_i64(t_ra, t_ra, mask); 2008*fcf5ef2aSThomas Huth #else 2009*fcf5ef2aSThomas Huth g_assert_not_reached(); 2010*fcf5ef2aSThomas Huth #endif 2011*fcf5ef2aSThomas Huth } 2012*fcf5ef2aSThomas Huth } 2013*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2014*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t_ra); 2015*fcf5ef2aSThomas Huth } 2016*fcf5ef2aSThomas Huth } 2017*fcf5ef2aSThomas Huth 2018*fcf5ef2aSThomas Huth /* rlwnm & rlwnm. */ 2019*fcf5ef2aSThomas Huth static void gen_rlwnm(DisasContext *ctx) 2020*fcf5ef2aSThomas Huth { 2021*fcf5ef2aSThomas Huth TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; 2022*fcf5ef2aSThomas Huth TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; 2023*fcf5ef2aSThomas Huth TCGv t_rb = cpu_gpr[rB(ctx->opcode)]; 2024*fcf5ef2aSThomas Huth uint32_t mb = MB(ctx->opcode); 2025*fcf5ef2aSThomas Huth uint32_t me = ME(ctx->opcode); 2026*fcf5ef2aSThomas Huth target_ulong mask; 2027*fcf5ef2aSThomas Huth 2028*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2029*fcf5ef2aSThomas Huth mb += 32; 2030*fcf5ef2aSThomas Huth me += 32; 2031*fcf5ef2aSThomas Huth #endif 2032*fcf5ef2aSThomas Huth mask = MASK(mb, me); 2033*fcf5ef2aSThomas Huth 2034*fcf5ef2aSThomas Huth if (mask <= 0xffffffffu) { 2035*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 2036*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 2037*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, t_rb); 2038*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, t_rs); 2039*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t0, t0, 0x1f); 2040*fcf5ef2aSThomas Huth tcg_gen_rotl_i32(t1, t1, t0); 2041*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(t_ra, t1); 2042*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 2043*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 2044*fcf5ef2aSThomas Huth } else { 2045*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2046*fcf5ef2aSThomas Huth TCGv_i64 t0 = tcg_temp_new_i64(); 2047*fcf5ef2aSThomas Huth tcg_gen_andi_i64(t0, t_rb, 0x1f); 2048*fcf5ef2aSThomas Huth tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32); 2049*fcf5ef2aSThomas Huth tcg_gen_rotl_i64(t_ra, t_ra, t0); 2050*fcf5ef2aSThomas Huth tcg_temp_free_i64(t0); 2051*fcf5ef2aSThomas Huth #else 2052*fcf5ef2aSThomas Huth g_assert_not_reached(); 2053*fcf5ef2aSThomas Huth #endif 2054*fcf5ef2aSThomas Huth } 2055*fcf5ef2aSThomas Huth 2056*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t_ra, t_ra, mask); 2057*fcf5ef2aSThomas Huth 2058*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2059*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t_ra); 2060*fcf5ef2aSThomas Huth } 2061*fcf5ef2aSThomas Huth } 2062*fcf5ef2aSThomas Huth 2063*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2064*fcf5ef2aSThomas Huth #define GEN_PPC64_R2(name, opc1, opc2) \ 2065*fcf5ef2aSThomas Huth static void glue(gen_, name##0)(DisasContext *ctx) \ 2066*fcf5ef2aSThomas Huth { \ 2067*fcf5ef2aSThomas Huth gen_##name(ctx, 0); \ 2068*fcf5ef2aSThomas Huth } \ 2069*fcf5ef2aSThomas Huth \ 2070*fcf5ef2aSThomas Huth static void glue(gen_, name##1)(DisasContext *ctx) \ 2071*fcf5ef2aSThomas Huth { \ 2072*fcf5ef2aSThomas Huth gen_##name(ctx, 1); \ 2073*fcf5ef2aSThomas Huth } 2074*fcf5ef2aSThomas Huth #define GEN_PPC64_R4(name, opc1, opc2) \ 2075*fcf5ef2aSThomas Huth static void glue(gen_, name##0)(DisasContext *ctx) \ 2076*fcf5ef2aSThomas Huth { \ 2077*fcf5ef2aSThomas Huth gen_##name(ctx, 0, 0); \ 2078*fcf5ef2aSThomas Huth } \ 2079*fcf5ef2aSThomas Huth \ 2080*fcf5ef2aSThomas Huth static void glue(gen_, name##1)(DisasContext *ctx) \ 2081*fcf5ef2aSThomas Huth { \ 2082*fcf5ef2aSThomas Huth gen_##name(ctx, 0, 1); \ 2083*fcf5ef2aSThomas Huth } \ 2084*fcf5ef2aSThomas Huth \ 2085*fcf5ef2aSThomas Huth static void glue(gen_, name##2)(DisasContext *ctx) \ 2086*fcf5ef2aSThomas Huth { \ 2087*fcf5ef2aSThomas Huth gen_##name(ctx, 1, 0); \ 2088*fcf5ef2aSThomas Huth } \ 2089*fcf5ef2aSThomas Huth \ 2090*fcf5ef2aSThomas Huth static void glue(gen_, name##3)(DisasContext *ctx) \ 2091*fcf5ef2aSThomas Huth { \ 2092*fcf5ef2aSThomas Huth gen_##name(ctx, 1, 1); \ 2093*fcf5ef2aSThomas Huth } 2094*fcf5ef2aSThomas Huth 2095*fcf5ef2aSThomas Huth static void gen_rldinm(DisasContext *ctx, int mb, int me, int sh) 2096*fcf5ef2aSThomas Huth { 2097*fcf5ef2aSThomas Huth TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; 2098*fcf5ef2aSThomas Huth TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; 2099*fcf5ef2aSThomas Huth 2100*fcf5ef2aSThomas Huth if (sh != 0 && mb == 0 && me == (63 - sh)) { 2101*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t_ra, t_rs, sh); 2102*fcf5ef2aSThomas Huth } else if (sh != 0 && me == 63 && sh == (64 - mb)) { 2103*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t_ra, t_rs, mb); 2104*fcf5ef2aSThomas Huth } else { 2105*fcf5ef2aSThomas Huth tcg_gen_rotli_tl(t_ra, t_rs, sh); 2106*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me)); 2107*fcf5ef2aSThomas Huth } 2108*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2109*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t_ra); 2110*fcf5ef2aSThomas Huth } 2111*fcf5ef2aSThomas Huth } 2112*fcf5ef2aSThomas Huth 2113*fcf5ef2aSThomas Huth /* rldicl - rldicl. */ 2114*fcf5ef2aSThomas Huth static inline void gen_rldicl(DisasContext *ctx, int mbn, int shn) 2115*fcf5ef2aSThomas Huth { 2116*fcf5ef2aSThomas Huth uint32_t sh, mb; 2117*fcf5ef2aSThomas Huth 2118*fcf5ef2aSThomas Huth sh = SH(ctx->opcode) | (shn << 5); 2119*fcf5ef2aSThomas Huth mb = MB(ctx->opcode) | (mbn << 5); 2120*fcf5ef2aSThomas Huth gen_rldinm(ctx, mb, 63, sh); 2121*fcf5ef2aSThomas Huth } 2122*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldicl, 0x1E, 0x00); 2123*fcf5ef2aSThomas Huth 2124*fcf5ef2aSThomas Huth /* rldicr - rldicr. */ 2125*fcf5ef2aSThomas Huth static inline void gen_rldicr(DisasContext *ctx, int men, int shn) 2126*fcf5ef2aSThomas Huth { 2127*fcf5ef2aSThomas Huth uint32_t sh, me; 2128*fcf5ef2aSThomas Huth 2129*fcf5ef2aSThomas Huth sh = SH(ctx->opcode) | (shn << 5); 2130*fcf5ef2aSThomas Huth me = MB(ctx->opcode) | (men << 5); 2131*fcf5ef2aSThomas Huth gen_rldinm(ctx, 0, me, sh); 2132*fcf5ef2aSThomas Huth } 2133*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldicr, 0x1E, 0x02); 2134*fcf5ef2aSThomas Huth 2135*fcf5ef2aSThomas Huth /* rldic - rldic. */ 2136*fcf5ef2aSThomas Huth static inline void gen_rldic(DisasContext *ctx, int mbn, int shn) 2137*fcf5ef2aSThomas Huth { 2138*fcf5ef2aSThomas Huth uint32_t sh, mb; 2139*fcf5ef2aSThomas Huth 2140*fcf5ef2aSThomas Huth sh = SH(ctx->opcode) | (shn << 5); 2141*fcf5ef2aSThomas Huth mb = MB(ctx->opcode) | (mbn << 5); 2142*fcf5ef2aSThomas Huth gen_rldinm(ctx, mb, 63 - sh, sh); 2143*fcf5ef2aSThomas Huth } 2144*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldic, 0x1E, 0x04); 2145*fcf5ef2aSThomas Huth 2146*fcf5ef2aSThomas Huth static void gen_rldnm(DisasContext *ctx, int mb, int me) 2147*fcf5ef2aSThomas Huth { 2148*fcf5ef2aSThomas Huth TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; 2149*fcf5ef2aSThomas Huth TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; 2150*fcf5ef2aSThomas Huth TCGv t_rb = cpu_gpr[rB(ctx->opcode)]; 2151*fcf5ef2aSThomas Huth TCGv t0; 2152*fcf5ef2aSThomas Huth 2153*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2154*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t_rb, 0x3f); 2155*fcf5ef2aSThomas Huth tcg_gen_rotl_tl(t_ra, t_rs, t0); 2156*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2157*fcf5ef2aSThomas Huth 2158*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t_ra, t_ra, MASK(mb, me)); 2159*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2160*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t_ra); 2161*fcf5ef2aSThomas Huth } 2162*fcf5ef2aSThomas Huth } 2163*fcf5ef2aSThomas Huth 2164*fcf5ef2aSThomas Huth /* rldcl - rldcl. */ 2165*fcf5ef2aSThomas Huth static inline void gen_rldcl(DisasContext *ctx, int mbn) 2166*fcf5ef2aSThomas Huth { 2167*fcf5ef2aSThomas Huth uint32_t mb; 2168*fcf5ef2aSThomas Huth 2169*fcf5ef2aSThomas Huth mb = MB(ctx->opcode) | (mbn << 5); 2170*fcf5ef2aSThomas Huth gen_rldnm(ctx, mb, 63); 2171*fcf5ef2aSThomas Huth } 2172*fcf5ef2aSThomas Huth GEN_PPC64_R2(rldcl, 0x1E, 0x08); 2173*fcf5ef2aSThomas Huth 2174*fcf5ef2aSThomas Huth /* rldcr - rldcr. */ 2175*fcf5ef2aSThomas Huth static inline void gen_rldcr(DisasContext *ctx, int men) 2176*fcf5ef2aSThomas Huth { 2177*fcf5ef2aSThomas Huth uint32_t me; 2178*fcf5ef2aSThomas Huth 2179*fcf5ef2aSThomas Huth me = MB(ctx->opcode) | (men << 5); 2180*fcf5ef2aSThomas Huth gen_rldnm(ctx, 0, me); 2181*fcf5ef2aSThomas Huth } 2182*fcf5ef2aSThomas Huth GEN_PPC64_R2(rldcr, 0x1E, 0x09); 2183*fcf5ef2aSThomas Huth 2184*fcf5ef2aSThomas Huth /* rldimi - rldimi. */ 2185*fcf5ef2aSThomas Huth static void gen_rldimi(DisasContext *ctx, int mbn, int shn) 2186*fcf5ef2aSThomas Huth { 2187*fcf5ef2aSThomas Huth TCGv t_ra = cpu_gpr[rA(ctx->opcode)]; 2188*fcf5ef2aSThomas Huth TCGv t_rs = cpu_gpr[rS(ctx->opcode)]; 2189*fcf5ef2aSThomas Huth uint32_t sh = SH(ctx->opcode) | (shn << 5); 2190*fcf5ef2aSThomas Huth uint32_t mb = MB(ctx->opcode) | (mbn << 5); 2191*fcf5ef2aSThomas Huth uint32_t me = 63 - sh; 2192*fcf5ef2aSThomas Huth 2193*fcf5ef2aSThomas Huth if (mb <= me) { 2194*fcf5ef2aSThomas Huth tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1); 2195*fcf5ef2aSThomas Huth } else { 2196*fcf5ef2aSThomas Huth target_ulong mask = MASK(mb, me); 2197*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 2198*fcf5ef2aSThomas Huth 2199*fcf5ef2aSThomas Huth tcg_gen_rotli_tl(t1, t_rs, sh); 2200*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, t1, mask); 2201*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t_ra, t_ra, ~mask); 2202*fcf5ef2aSThomas Huth tcg_gen_or_tl(t_ra, t_ra, t1); 2203*fcf5ef2aSThomas Huth tcg_temp_free(t1); 2204*fcf5ef2aSThomas Huth } 2205*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2206*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t_ra); 2207*fcf5ef2aSThomas Huth } 2208*fcf5ef2aSThomas Huth } 2209*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldimi, 0x1E, 0x06); 2210*fcf5ef2aSThomas Huth #endif 2211*fcf5ef2aSThomas Huth 2212*fcf5ef2aSThomas Huth /*** Integer shift ***/ 2213*fcf5ef2aSThomas Huth 2214*fcf5ef2aSThomas Huth /* slw & slw. */ 2215*fcf5ef2aSThomas Huth static void gen_slw(DisasContext *ctx) 2216*fcf5ef2aSThomas Huth { 2217*fcf5ef2aSThomas Huth TCGv t0, t1; 2218*fcf5ef2aSThomas Huth 2219*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2220*fcf5ef2aSThomas Huth /* AND rS with a mask that is 0 when rB >= 0x20 */ 2221*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2222*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a); 2223*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, t0, 0x3f); 2224*fcf5ef2aSThomas Huth #else 2225*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a); 2226*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, t0, 0x1f); 2227*fcf5ef2aSThomas Huth #endif 2228*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 2229*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 2230*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f); 2231*fcf5ef2aSThomas Huth tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 2232*fcf5ef2aSThomas Huth tcg_temp_free(t1); 2233*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2234*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 2235*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 2236*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 2237*fcf5ef2aSThomas Huth } 2238*fcf5ef2aSThomas Huth 2239*fcf5ef2aSThomas Huth /* sraw & sraw. */ 2240*fcf5ef2aSThomas Huth static void gen_sraw(DisasContext *ctx) 2241*fcf5ef2aSThomas Huth { 2242*fcf5ef2aSThomas Huth gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env, 2243*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 2244*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 2245*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 2246*fcf5ef2aSThomas Huth } 2247*fcf5ef2aSThomas Huth 2248*fcf5ef2aSThomas Huth /* srawi & srawi. */ 2249*fcf5ef2aSThomas Huth static void gen_srawi(DisasContext *ctx) 2250*fcf5ef2aSThomas Huth { 2251*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode); 2252*fcf5ef2aSThomas Huth TCGv dst = cpu_gpr[rA(ctx->opcode)]; 2253*fcf5ef2aSThomas Huth TCGv src = cpu_gpr[rS(ctx->opcode)]; 2254*fcf5ef2aSThomas Huth if (sh == 0) { 2255*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(dst, src); 2256*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 0); 2257*fcf5ef2aSThomas Huth } else { 2258*fcf5ef2aSThomas Huth TCGv t0; 2259*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(dst, src); 2260*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_ca, dst, (1ULL << sh) - 1); 2261*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2262*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1); 2263*fcf5ef2aSThomas Huth tcg_gen_and_tl(cpu_ca, cpu_ca, t0); 2264*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2265*fcf5ef2aSThomas Huth tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); 2266*fcf5ef2aSThomas Huth tcg_gen_sari_tl(dst, dst, sh); 2267*fcf5ef2aSThomas Huth } 2268*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2269*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, dst); 2270*fcf5ef2aSThomas Huth } 2271*fcf5ef2aSThomas Huth } 2272*fcf5ef2aSThomas Huth 2273*fcf5ef2aSThomas Huth /* srw & srw. */ 2274*fcf5ef2aSThomas Huth static void gen_srw(DisasContext *ctx) 2275*fcf5ef2aSThomas Huth { 2276*fcf5ef2aSThomas Huth TCGv t0, t1; 2277*fcf5ef2aSThomas Huth 2278*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2279*fcf5ef2aSThomas Huth /* AND rS with a mask that is 0 when rB >= 0x20 */ 2280*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2281*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3a); 2282*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, t0, 0x3f); 2283*fcf5ef2aSThomas Huth #else 2284*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1a); 2285*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, t0, 0x1f); 2286*fcf5ef2aSThomas Huth #endif 2287*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 2288*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(t0, t0); 2289*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 2290*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1f); 2291*fcf5ef2aSThomas Huth tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 2292*fcf5ef2aSThomas Huth tcg_temp_free(t1); 2293*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2294*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 2295*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 2296*fcf5ef2aSThomas Huth } 2297*fcf5ef2aSThomas Huth 2298*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2299*fcf5ef2aSThomas Huth /* sld & sld. */ 2300*fcf5ef2aSThomas Huth static void gen_sld(DisasContext *ctx) 2301*fcf5ef2aSThomas Huth { 2302*fcf5ef2aSThomas Huth TCGv t0, t1; 2303*fcf5ef2aSThomas Huth 2304*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2305*fcf5ef2aSThomas Huth /* AND rS with a mask that is 0 when rB >= 0x40 */ 2306*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39); 2307*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, t0, 0x3f); 2308*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 2309*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 2310*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f); 2311*fcf5ef2aSThomas Huth tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 2312*fcf5ef2aSThomas Huth tcg_temp_free(t1); 2313*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2314*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 2315*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 2316*fcf5ef2aSThomas Huth } 2317*fcf5ef2aSThomas Huth 2318*fcf5ef2aSThomas Huth /* srad & srad. */ 2319*fcf5ef2aSThomas Huth static void gen_srad(DisasContext *ctx) 2320*fcf5ef2aSThomas Huth { 2321*fcf5ef2aSThomas Huth gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env, 2322*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 2323*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 2324*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 2325*fcf5ef2aSThomas Huth } 2326*fcf5ef2aSThomas Huth /* sradi & sradi. */ 2327*fcf5ef2aSThomas Huth static inline void gen_sradi(DisasContext *ctx, int n) 2328*fcf5ef2aSThomas Huth { 2329*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode) + (n << 5); 2330*fcf5ef2aSThomas Huth TCGv dst = cpu_gpr[rA(ctx->opcode)]; 2331*fcf5ef2aSThomas Huth TCGv src = cpu_gpr[rS(ctx->opcode)]; 2332*fcf5ef2aSThomas Huth if (sh == 0) { 2333*fcf5ef2aSThomas Huth tcg_gen_mov_tl(dst, src); 2334*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 0); 2335*fcf5ef2aSThomas Huth } else { 2336*fcf5ef2aSThomas Huth TCGv t0; 2337*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1); 2338*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2339*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1); 2340*fcf5ef2aSThomas Huth tcg_gen_and_tl(cpu_ca, cpu_ca, t0); 2341*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2342*fcf5ef2aSThomas Huth tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); 2343*fcf5ef2aSThomas Huth tcg_gen_sari_tl(dst, src, sh); 2344*fcf5ef2aSThomas Huth } 2345*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2346*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, dst); 2347*fcf5ef2aSThomas Huth } 2348*fcf5ef2aSThomas Huth } 2349*fcf5ef2aSThomas Huth 2350*fcf5ef2aSThomas Huth static void gen_sradi0(DisasContext *ctx) 2351*fcf5ef2aSThomas Huth { 2352*fcf5ef2aSThomas Huth gen_sradi(ctx, 0); 2353*fcf5ef2aSThomas Huth } 2354*fcf5ef2aSThomas Huth 2355*fcf5ef2aSThomas Huth static void gen_sradi1(DisasContext *ctx) 2356*fcf5ef2aSThomas Huth { 2357*fcf5ef2aSThomas Huth gen_sradi(ctx, 1); 2358*fcf5ef2aSThomas Huth } 2359*fcf5ef2aSThomas Huth 2360*fcf5ef2aSThomas Huth /* extswsli & extswsli. */ 2361*fcf5ef2aSThomas Huth static inline void gen_extswsli(DisasContext *ctx, int n) 2362*fcf5ef2aSThomas Huth { 2363*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode) + (n << 5); 2364*fcf5ef2aSThomas Huth TCGv dst = cpu_gpr[rA(ctx->opcode)]; 2365*fcf5ef2aSThomas Huth TCGv src = cpu_gpr[rS(ctx->opcode)]; 2366*fcf5ef2aSThomas Huth 2367*fcf5ef2aSThomas Huth tcg_gen_ext32s_tl(dst, src); 2368*fcf5ef2aSThomas Huth tcg_gen_shli_tl(dst, dst, sh); 2369*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) { 2370*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, dst); 2371*fcf5ef2aSThomas Huth } 2372*fcf5ef2aSThomas Huth } 2373*fcf5ef2aSThomas Huth 2374*fcf5ef2aSThomas Huth static void gen_extswsli0(DisasContext *ctx) 2375*fcf5ef2aSThomas Huth { 2376*fcf5ef2aSThomas Huth gen_extswsli(ctx, 0); 2377*fcf5ef2aSThomas Huth } 2378*fcf5ef2aSThomas Huth 2379*fcf5ef2aSThomas Huth static void gen_extswsli1(DisasContext *ctx) 2380*fcf5ef2aSThomas Huth { 2381*fcf5ef2aSThomas Huth gen_extswsli(ctx, 1); 2382*fcf5ef2aSThomas Huth } 2383*fcf5ef2aSThomas Huth 2384*fcf5ef2aSThomas Huth /* srd & srd. */ 2385*fcf5ef2aSThomas Huth static void gen_srd(DisasContext *ctx) 2386*fcf5ef2aSThomas Huth { 2387*fcf5ef2aSThomas Huth TCGv t0, t1; 2388*fcf5ef2aSThomas Huth 2389*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2390*fcf5ef2aSThomas Huth /* AND rS with a mask that is 0 when rB >= 0x40 */ 2391*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x39); 2392*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, t0, 0x3f); 2393*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 2394*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 2395*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x3f); 2396*fcf5ef2aSThomas Huth tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 2397*fcf5ef2aSThomas Huth tcg_temp_free(t1); 2398*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2399*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 2400*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 2401*fcf5ef2aSThomas Huth } 2402*fcf5ef2aSThomas Huth #endif 2403*fcf5ef2aSThomas Huth 2404*fcf5ef2aSThomas Huth /*** Addressing modes ***/ 2405*fcf5ef2aSThomas Huth /* Register indirect with immediate index : EA = (rA|0) + SIMM */ 2406*fcf5ef2aSThomas Huth static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA, 2407*fcf5ef2aSThomas Huth target_long maskl) 2408*fcf5ef2aSThomas Huth { 2409*fcf5ef2aSThomas Huth target_long simm = SIMM(ctx->opcode); 2410*fcf5ef2aSThomas Huth 2411*fcf5ef2aSThomas Huth simm &= ~maskl; 2412*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 2413*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 2414*fcf5ef2aSThomas Huth simm = (uint32_t)simm; 2415*fcf5ef2aSThomas Huth } 2416*fcf5ef2aSThomas Huth tcg_gen_movi_tl(EA, simm); 2417*fcf5ef2aSThomas Huth } else if (likely(simm != 0)) { 2418*fcf5ef2aSThomas Huth tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm); 2419*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 2420*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(EA, EA); 2421*fcf5ef2aSThomas Huth } 2422*fcf5ef2aSThomas Huth } else { 2423*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 2424*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]); 2425*fcf5ef2aSThomas Huth } else { 2426*fcf5ef2aSThomas Huth tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); 2427*fcf5ef2aSThomas Huth } 2428*fcf5ef2aSThomas Huth } 2429*fcf5ef2aSThomas Huth } 2430*fcf5ef2aSThomas Huth 2431*fcf5ef2aSThomas Huth static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA) 2432*fcf5ef2aSThomas Huth { 2433*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 2434*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 2435*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]); 2436*fcf5ef2aSThomas Huth } else { 2437*fcf5ef2aSThomas Huth tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]); 2438*fcf5ef2aSThomas Huth } 2439*fcf5ef2aSThomas Huth } else { 2440*fcf5ef2aSThomas Huth tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 2441*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 2442*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(EA, EA); 2443*fcf5ef2aSThomas Huth } 2444*fcf5ef2aSThomas Huth } 2445*fcf5ef2aSThomas Huth } 2446*fcf5ef2aSThomas Huth 2447*fcf5ef2aSThomas Huth static inline void gen_addr_register(DisasContext *ctx, TCGv EA) 2448*fcf5ef2aSThomas Huth { 2449*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 2450*fcf5ef2aSThomas Huth tcg_gen_movi_tl(EA, 0); 2451*fcf5ef2aSThomas Huth } else if (NARROW_MODE(ctx)) { 2452*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]); 2453*fcf5ef2aSThomas Huth } else { 2454*fcf5ef2aSThomas Huth tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); 2455*fcf5ef2aSThomas Huth } 2456*fcf5ef2aSThomas Huth } 2457*fcf5ef2aSThomas Huth 2458*fcf5ef2aSThomas Huth static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1, 2459*fcf5ef2aSThomas Huth target_long val) 2460*fcf5ef2aSThomas Huth { 2461*fcf5ef2aSThomas Huth tcg_gen_addi_tl(ret, arg1, val); 2462*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 2463*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(ret, ret); 2464*fcf5ef2aSThomas Huth } 2465*fcf5ef2aSThomas Huth } 2466*fcf5ef2aSThomas Huth 2467*fcf5ef2aSThomas Huth static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask) 2468*fcf5ef2aSThomas Huth { 2469*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 2470*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 2471*fcf5ef2aSThomas Huth TCGv_i32 t1, t2; 2472*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, EA, mask); 2473*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); 2474*fcf5ef2aSThomas Huth t1 = tcg_const_i32(POWERPC_EXCP_ALIGN); 2475*fcf5ef2aSThomas Huth t2 = tcg_const_i32(ctx->opcode & 0x03FF0000); 2476*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip - 4); 2477*fcf5ef2aSThomas Huth gen_helper_raise_exception_err(cpu_env, t1, t2); 2478*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 2479*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 2480*fcf5ef2aSThomas Huth gen_set_label(l1); 2481*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2482*fcf5ef2aSThomas Huth } 2483*fcf5ef2aSThomas Huth 2484*fcf5ef2aSThomas Huth static inline void gen_align_no_le(DisasContext *ctx) 2485*fcf5ef2aSThomas Huth { 2486*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_ALIGN, 2487*fcf5ef2aSThomas Huth (ctx->opcode & 0x03FF0000) | POWERPC_EXCP_ALIGN_LE); 2488*fcf5ef2aSThomas Huth } 2489*fcf5ef2aSThomas Huth 2490*fcf5ef2aSThomas Huth /*** Integer load ***/ 2491*fcf5ef2aSThomas Huth #define DEF_MEMOP(op) ((op) | ctx->default_tcg_memop_mask) 2492*fcf5ef2aSThomas Huth #define BSWAP_MEMOP(op) ((op) | (ctx->default_tcg_memop_mask ^ MO_BSWAP)) 2493*fcf5ef2aSThomas Huth 2494*fcf5ef2aSThomas Huth #define GEN_QEMU_LOAD_TL(ldop, op) \ 2495*fcf5ef2aSThomas Huth static void glue(gen_qemu_, ldop)(DisasContext *ctx, \ 2496*fcf5ef2aSThomas Huth TCGv val, \ 2497*fcf5ef2aSThomas Huth TCGv addr) \ 2498*fcf5ef2aSThomas Huth { \ 2499*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_tl(val, addr, ctx->mem_idx, op); \ 2500*fcf5ef2aSThomas Huth } 2501*fcf5ef2aSThomas Huth 2502*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld8u, DEF_MEMOP(MO_UB)) 2503*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld16u, DEF_MEMOP(MO_UW)) 2504*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld16s, DEF_MEMOP(MO_SW)) 2505*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld32u, DEF_MEMOP(MO_UL)) 2506*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld32s, DEF_MEMOP(MO_SL)) 2507*fcf5ef2aSThomas Huth 2508*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld16ur, BSWAP_MEMOP(MO_UW)) 2509*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_TL(ld32ur, BSWAP_MEMOP(MO_UL)) 2510*fcf5ef2aSThomas Huth 2511*fcf5ef2aSThomas Huth #define GEN_QEMU_LOAD_64(ldop, op) \ 2512*fcf5ef2aSThomas Huth static void glue(gen_qemu_, glue(ldop, _i64))(DisasContext *ctx, \ 2513*fcf5ef2aSThomas Huth TCGv_i64 val, \ 2514*fcf5ef2aSThomas Huth TCGv addr) \ 2515*fcf5ef2aSThomas Huth { \ 2516*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, op); \ 2517*fcf5ef2aSThomas Huth } 2518*fcf5ef2aSThomas Huth 2519*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_64(ld8u, DEF_MEMOP(MO_UB)) 2520*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW)) 2521*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL)) 2522*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL)) 2523*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_Q)) 2524*fcf5ef2aSThomas Huth 2525*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2526*fcf5ef2aSThomas Huth GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_Q)) 2527*fcf5ef2aSThomas Huth #endif 2528*fcf5ef2aSThomas Huth 2529*fcf5ef2aSThomas Huth #define GEN_QEMU_STORE_TL(stop, op) \ 2530*fcf5ef2aSThomas Huth static void glue(gen_qemu_, stop)(DisasContext *ctx, \ 2531*fcf5ef2aSThomas Huth TCGv val, \ 2532*fcf5ef2aSThomas Huth TCGv addr) \ 2533*fcf5ef2aSThomas Huth { \ 2534*fcf5ef2aSThomas Huth tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op); \ 2535*fcf5ef2aSThomas Huth } 2536*fcf5ef2aSThomas Huth 2537*fcf5ef2aSThomas Huth GEN_QEMU_STORE_TL(st8, DEF_MEMOP(MO_UB)) 2538*fcf5ef2aSThomas Huth GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW)) 2539*fcf5ef2aSThomas Huth GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL)) 2540*fcf5ef2aSThomas Huth 2541*fcf5ef2aSThomas Huth GEN_QEMU_STORE_TL(st16r, BSWAP_MEMOP(MO_UW)) 2542*fcf5ef2aSThomas Huth GEN_QEMU_STORE_TL(st32r, BSWAP_MEMOP(MO_UL)) 2543*fcf5ef2aSThomas Huth 2544*fcf5ef2aSThomas Huth #define GEN_QEMU_STORE_64(stop, op) \ 2545*fcf5ef2aSThomas Huth static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx, \ 2546*fcf5ef2aSThomas Huth TCGv_i64 val, \ 2547*fcf5ef2aSThomas Huth TCGv addr) \ 2548*fcf5ef2aSThomas Huth { \ 2549*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, op); \ 2550*fcf5ef2aSThomas Huth } 2551*fcf5ef2aSThomas Huth 2552*fcf5ef2aSThomas Huth GEN_QEMU_STORE_64(st8, DEF_MEMOP(MO_UB)) 2553*fcf5ef2aSThomas Huth GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW)) 2554*fcf5ef2aSThomas Huth GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL)) 2555*fcf5ef2aSThomas Huth GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q)) 2556*fcf5ef2aSThomas Huth 2557*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2558*fcf5ef2aSThomas Huth GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q)) 2559*fcf5ef2aSThomas Huth #endif 2560*fcf5ef2aSThomas Huth 2561*fcf5ef2aSThomas Huth #define GEN_LD(name, ldop, opc, type) \ 2562*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 2563*fcf5ef2aSThomas Huth { \ 2564*fcf5ef2aSThomas Huth TCGv EA; \ 2565*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2566*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2567*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0); \ 2568*fcf5ef2aSThomas Huth gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ 2569*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2570*fcf5ef2aSThomas Huth } 2571*fcf5ef2aSThomas Huth 2572*fcf5ef2aSThomas Huth #define GEN_LDU(name, ldop, opc, type) \ 2573*fcf5ef2aSThomas Huth static void glue(gen_, name##u)(DisasContext *ctx) \ 2574*fcf5ef2aSThomas Huth { \ 2575*fcf5ef2aSThomas Huth TCGv EA; \ 2576*fcf5ef2aSThomas Huth if (unlikely(rA(ctx->opcode) == 0 || \ 2577*fcf5ef2aSThomas Huth rA(ctx->opcode) == rD(ctx->opcode))) { \ 2578*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ 2579*fcf5ef2aSThomas Huth return; \ 2580*fcf5ef2aSThomas Huth } \ 2581*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2582*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2583*fcf5ef2aSThomas Huth if (type == PPC_64B) \ 2584*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0x03); \ 2585*fcf5ef2aSThomas Huth else \ 2586*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0); \ 2587*fcf5ef2aSThomas Huth gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ 2588*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ 2589*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2590*fcf5ef2aSThomas Huth } 2591*fcf5ef2aSThomas Huth 2592*fcf5ef2aSThomas Huth #define GEN_LDUX(name, ldop, opc2, opc3, type) \ 2593*fcf5ef2aSThomas Huth static void glue(gen_, name##ux)(DisasContext *ctx) \ 2594*fcf5ef2aSThomas Huth { \ 2595*fcf5ef2aSThomas Huth TCGv EA; \ 2596*fcf5ef2aSThomas Huth if (unlikely(rA(ctx->opcode) == 0 || \ 2597*fcf5ef2aSThomas Huth rA(ctx->opcode) == rD(ctx->opcode))) { \ 2598*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ 2599*fcf5ef2aSThomas Huth return; \ 2600*fcf5ef2aSThomas Huth } \ 2601*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2602*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2603*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); \ 2604*fcf5ef2aSThomas Huth gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ 2605*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ 2606*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2607*fcf5ef2aSThomas Huth } 2608*fcf5ef2aSThomas Huth 2609*fcf5ef2aSThomas Huth #define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \ 2610*fcf5ef2aSThomas Huth static void glue(gen_, name##x)(DisasContext *ctx) \ 2611*fcf5ef2aSThomas Huth { \ 2612*fcf5ef2aSThomas Huth TCGv EA; \ 2613*fcf5ef2aSThomas Huth chk; \ 2614*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2615*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2616*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); \ 2617*fcf5ef2aSThomas Huth gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ 2618*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2619*fcf5ef2aSThomas Huth } 2620*fcf5ef2aSThomas Huth 2621*fcf5ef2aSThomas Huth #define GEN_LDX(name, ldop, opc2, opc3, type) \ 2622*fcf5ef2aSThomas Huth GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_NONE) 2623*fcf5ef2aSThomas Huth 2624*fcf5ef2aSThomas Huth #define GEN_LDX_HVRM(name, ldop, opc2, opc3, type) \ 2625*fcf5ef2aSThomas Huth GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE, CHK_HVRM) 2626*fcf5ef2aSThomas Huth 2627*fcf5ef2aSThomas Huth #define GEN_LDS(name, ldop, op, type) \ 2628*fcf5ef2aSThomas Huth GEN_LD(name, ldop, op | 0x20, type); \ 2629*fcf5ef2aSThomas Huth GEN_LDU(name, ldop, op | 0x21, type); \ 2630*fcf5ef2aSThomas Huth GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \ 2631*fcf5ef2aSThomas Huth GEN_LDX(name, ldop, 0x17, op | 0x00, type) 2632*fcf5ef2aSThomas Huth 2633*fcf5ef2aSThomas Huth /* lbz lbzu lbzux lbzx */ 2634*fcf5ef2aSThomas Huth GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER); 2635*fcf5ef2aSThomas Huth /* lha lhau lhaux lhax */ 2636*fcf5ef2aSThomas Huth GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER); 2637*fcf5ef2aSThomas Huth /* lhz lhzu lhzux lhzx */ 2638*fcf5ef2aSThomas Huth GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER); 2639*fcf5ef2aSThomas Huth /* lwz lwzu lwzux lwzx */ 2640*fcf5ef2aSThomas Huth GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER); 2641*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2642*fcf5ef2aSThomas Huth /* lwaux */ 2643*fcf5ef2aSThomas Huth GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B); 2644*fcf5ef2aSThomas Huth /* lwax */ 2645*fcf5ef2aSThomas Huth GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B); 2646*fcf5ef2aSThomas Huth /* ldux */ 2647*fcf5ef2aSThomas Huth GEN_LDUX(ld, ld64_i64, 0x15, 0x01, PPC_64B); 2648*fcf5ef2aSThomas Huth /* ldx */ 2649*fcf5ef2aSThomas Huth GEN_LDX(ld, ld64_i64, 0x15, 0x00, PPC_64B); 2650*fcf5ef2aSThomas Huth 2651*fcf5ef2aSThomas Huth /* CI load/store variants */ 2652*fcf5ef2aSThomas Huth GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST) 2653*fcf5ef2aSThomas Huth GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x15, PPC_CILDST) 2654*fcf5ef2aSThomas Huth GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST) 2655*fcf5ef2aSThomas Huth GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST) 2656*fcf5ef2aSThomas Huth 2657*fcf5ef2aSThomas Huth static void gen_ld(DisasContext *ctx) 2658*fcf5ef2aSThomas Huth { 2659*fcf5ef2aSThomas Huth TCGv EA; 2660*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) { 2661*fcf5ef2aSThomas Huth if (unlikely(rA(ctx->opcode) == 0 || 2662*fcf5ef2aSThomas Huth rA(ctx->opcode) == rD(ctx->opcode))) { 2663*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 2664*fcf5ef2aSThomas Huth return; 2665*fcf5ef2aSThomas Huth } 2666*fcf5ef2aSThomas Huth } 2667*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2668*fcf5ef2aSThomas Huth EA = tcg_temp_new(); 2669*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0x03); 2670*fcf5ef2aSThomas Huth if (ctx->opcode & 0x02) { 2671*fcf5ef2aSThomas Huth /* lwa (lwau is undefined) */ 2672*fcf5ef2aSThomas Huth gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA); 2673*fcf5ef2aSThomas Huth } else { 2674*fcf5ef2aSThomas Huth /* ld - ldu */ 2675*fcf5ef2aSThomas Huth gen_qemu_ld64_i64(ctx, cpu_gpr[rD(ctx->opcode)], EA); 2676*fcf5ef2aSThomas Huth } 2677*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) 2678*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); 2679*fcf5ef2aSThomas Huth tcg_temp_free(EA); 2680*fcf5ef2aSThomas Huth } 2681*fcf5ef2aSThomas Huth 2682*fcf5ef2aSThomas Huth /* lq */ 2683*fcf5ef2aSThomas Huth static void gen_lq(DisasContext *ctx) 2684*fcf5ef2aSThomas Huth { 2685*fcf5ef2aSThomas Huth int ra, rd; 2686*fcf5ef2aSThomas Huth TCGv EA; 2687*fcf5ef2aSThomas Huth 2688*fcf5ef2aSThomas Huth /* lq is a legal user mode instruction starting in ISA 2.07 */ 2689*fcf5ef2aSThomas Huth bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0; 2690*fcf5ef2aSThomas Huth bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0; 2691*fcf5ef2aSThomas Huth 2692*fcf5ef2aSThomas Huth if (!legal_in_user_mode && ctx->pr) { 2693*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); 2694*fcf5ef2aSThomas Huth return; 2695*fcf5ef2aSThomas Huth } 2696*fcf5ef2aSThomas Huth 2697*fcf5ef2aSThomas Huth if (!le_is_supported && ctx->le_mode) { 2698*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 2699*fcf5ef2aSThomas Huth return; 2700*fcf5ef2aSThomas Huth } 2701*fcf5ef2aSThomas Huth ra = rA(ctx->opcode); 2702*fcf5ef2aSThomas Huth rd = rD(ctx->opcode); 2703*fcf5ef2aSThomas Huth if (unlikely((rd & 1) || rd == ra)) { 2704*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 2705*fcf5ef2aSThomas Huth return; 2706*fcf5ef2aSThomas Huth } 2707*fcf5ef2aSThomas Huth 2708*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2709*fcf5ef2aSThomas Huth EA = tcg_temp_new(); 2710*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0x0F); 2711*fcf5ef2aSThomas Huth 2712*fcf5ef2aSThomas Huth /* We only need to swap high and low halves. gen_qemu_ld64_i64 does 2713*fcf5ef2aSThomas Huth necessary 64-bit byteswap already. */ 2714*fcf5ef2aSThomas Huth if (unlikely(ctx->le_mode)) { 2715*fcf5ef2aSThomas Huth gen_qemu_ld64_i64(ctx, cpu_gpr[rd + 1], EA); 2716*fcf5ef2aSThomas Huth gen_addr_add(ctx, EA, EA, 8); 2717*fcf5ef2aSThomas Huth gen_qemu_ld64_i64(ctx, cpu_gpr[rd], EA); 2718*fcf5ef2aSThomas Huth } else { 2719*fcf5ef2aSThomas Huth gen_qemu_ld64_i64(ctx, cpu_gpr[rd], EA); 2720*fcf5ef2aSThomas Huth gen_addr_add(ctx, EA, EA, 8); 2721*fcf5ef2aSThomas Huth gen_qemu_ld64_i64(ctx, cpu_gpr[rd + 1], EA); 2722*fcf5ef2aSThomas Huth } 2723*fcf5ef2aSThomas Huth tcg_temp_free(EA); 2724*fcf5ef2aSThomas Huth } 2725*fcf5ef2aSThomas Huth #endif 2726*fcf5ef2aSThomas Huth 2727*fcf5ef2aSThomas Huth /*** Integer store ***/ 2728*fcf5ef2aSThomas Huth #define GEN_ST(name, stop, opc, type) \ 2729*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 2730*fcf5ef2aSThomas Huth { \ 2731*fcf5ef2aSThomas Huth TCGv EA; \ 2732*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2733*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2734*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0); \ 2735*fcf5ef2aSThomas Huth gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ 2736*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2737*fcf5ef2aSThomas Huth } 2738*fcf5ef2aSThomas Huth 2739*fcf5ef2aSThomas Huth #define GEN_STU(name, stop, opc, type) \ 2740*fcf5ef2aSThomas Huth static void glue(gen_, stop##u)(DisasContext *ctx) \ 2741*fcf5ef2aSThomas Huth { \ 2742*fcf5ef2aSThomas Huth TCGv EA; \ 2743*fcf5ef2aSThomas Huth if (unlikely(rA(ctx->opcode) == 0)) { \ 2744*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ 2745*fcf5ef2aSThomas Huth return; \ 2746*fcf5ef2aSThomas Huth } \ 2747*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2748*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2749*fcf5ef2aSThomas Huth if (type == PPC_64B) \ 2750*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0x03); \ 2751*fcf5ef2aSThomas Huth else \ 2752*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0); \ 2753*fcf5ef2aSThomas Huth gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ 2754*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ 2755*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2756*fcf5ef2aSThomas Huth } 2757*fcf5ef2aSThomas Huth 2758*fcf5ef2aSThomas Huth #define GEN_STUX(name, stop, opc2, opc3, type) \ 2759*fcf5ef2aSThomas Huth static void glue(gen_, name##ux)(DisasContext *ctx) \ 2760*fcf5ef2aSThomas Huth { \ 2761*fcf5ef2aSThomas Huth TCGv EA; \ 2762*fcf5ef2aSThomas Huth if (unlikely(rA(ctx->opcode) == 0)) { \ 2763*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \ 2764*fcf5ef2aSThomas Huth return; \ 2765*fcf5ef2aSThomas Huth } \ 2766*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2767*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2768*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); \ 2769*fcf5ef2aSThomas Huth gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ 2770*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \ 2771*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2772*fcf5ef2aSThomas Huth } 2773*fcf5ef2aSThomas Huth 2774*fcf5ef2aSThomas Huth #define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk) \ 2775*fcf5ef2aSThomas Huth static void glue(gen_, name##x)(DisasContext *ctx) \ 2776*fcf5ef2aSThomas Huth { \ 2777*fcf5ef2aSThomas Huth TCGv EA; \ 2778*fcf5ef2aSThomas Huth chk; \ 2779*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); \ 2780*fcf5ef2aSThomas Huth EA = tcg_temp_new(); \ 2781*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); \ 2782*fcf5ef2aSThomas Huth gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ 2783*fcf5ef2aSThomas Huth tcg_temp_free(EA); \ 2784*fcf5ef2aSThomas Huth } 2785*fcf5ef2aSThomas Huth #define GEN_STX(name, stop, opc2, opc3, type) \ 2786*fcf5ef2aSThomas Huth GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_NONE) 2787*fcf5ef2aSThomas Huth 2788*fcf5ef2aSThomas Huth #define GEN_STX_HVRM(name, stop, opc2, opc3, type) \ 2789*fcf5ef2aSThomas Huth GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE, CHK_HVRM) 2790*fcf5ef2aSThomas Huth 2791*fcf5ef2aSThomas Huth #define GEN_STS(name, stop, op, type) \ 2792*fcf5ef2aSThomas Huth GEN_ST(name, stop, op | 0x20, type); \ 2793*fcf5ef2aSThomas Huth GEN_STU(name, stop, op | 0x21, type); \ 2794*fcf5ef2aSThomas Huth GEN_STUX(name, stop, 0x17, op | 0x01, type); \ 2795*fcf5ef2aSThomas Huth GEN_STX(name, stop, 0x17, op | 0x00, type) 2796*fcf5ef2aSThomas Huth 2797*fcf5ef2aSThomas Huth /* stb stbu stbux stbx */ 2798*fcf5ef2aSThomas Huth GEN_STS(stb, st8, 0x06, PPC_INTEGER); 2799*fcf5ef2aSThomas Huth /* sth sthu sthux sthx */ 2800*fcf5ef2aSThomas Huth GEN_STS(sth, st16, 0x0C, PPC_INTEGER); 2801*fcf5ef2aSThomas Huth /* stw stwu stwux stwx */ 2802*fcf5ef2aSThomas Huth GEN_STS(stw, st32, 0x04, PPC_INTEGER); 2803*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2804*fcf5ef2aSThomas Huth GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B); 2805*fcf5ef2aSThomas Huth GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B); 2806*fcf5ef2aSThomas Huth GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST) 2807*fcf5ef2aSThomas Huth GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST) 2808*fcf5ef2aSThomas Huth GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST) 2809*fcf5ef2aSThomas Huth GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST) 2810*fcf5ef2aSThomas Huth 2811*fcf5ef2aSThomas Huth static void gen_std(DisasContext *ctx) 2812*fcf5ef2aSThomas Huth { 2813*fcf5ef2aSThomas Huth int rs; 2814*fcf5ef2aSThomas Huth TCGv EA; 2815*fcf5ef2aSThomas Huth 2816*fcf5ef2aSThomas Huth rs = rS(ctx->opcode); 2817*fcf5ef2aSThomas Huth if ((ctx->opcode & 0x3) == 0x2) { /* stq */ 2818*fcf5ef2aSThomas Huth bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0; 2819*fcf5ef2aSThomas Huth bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0; 2820*fcf5ef2aSThomas Huth 2821*fcf5ef2aSThomas Huth if (!(ctx->insns_flags & PPC_64BX)) { 2822*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 2823*fcf5ef2aSThomas Huth } 2824*fcf5ef2aSThomas Huth 2825*fcf5ef2aSThomas Huth if (!legal_in_user_mode && ctx->pr) { 2826*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); 2827*fcf5ef2aSThomas Huth return; 2828*fcf5ef2aSThomas Huth } 2829*fcf5ef2aSThomas Huth 2830*fcf5ef2aSThomas Huth if (!le_is_supported && ctx->le_mode) { 2831*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 2832*fcf5ef2aSThomas Huth return; 2833*fcf5ef2aSThomas Huth } 2834*fcf5ef2aSThomas Huth 2835*fcf5ef2aSThomas Huth if (unlikely(rs & 1)) { 2836*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 2837*fcf5ef2aSThomas Huth return; 2838*fcf5ef2aSThomas Huth } 2839*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2840*fcf5ef2aSThomas Huth EA = tcg_temp_new(); 2841*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0x03); 2842*fcf5ef2aSThomas Huth 2843*fcf5ef2aSThomas Huth /* We only need to swap high and low halves. gen_qemu_st64_i64 does 2844*fcf5ef2aSThomas Huth necessary 64-bit byteswap already. */ 2845*fcf5ef2aSThomas Huth if (unlikely(ctx->le_mode)) { 2846*fcf5ef2aSThomas Huth gen_qemu_st64_i64(ctx, cpu_gpr[rs + 1], EA); 2847*fcf5ef2aSThomas Huth gen_addr_add(ctx, EA, EA, 8); 2848*fcf5ef2aSThomas Huth gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA); 2849*fcf5ef2aSThomas Huth } else { 2850*fcf5ef2aSThomas Huth gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA); 2851*fcf5ef2aSThomas Huth gen_addr_add(ctx, EA, EA, 8); 2852*fcf5ef2aSThomas Huth gen_qemu_st64_i64(ctx, cpu_gpr[rs + 1], EA); 2853*fcf5ef2aSThomas Huth } 2854*fcf5ef2aSThomas Huth tcg_temp_free(EA); 2855*fcf5ef2aSThomas Huth } else { 2856*fcf5ef2aSThomas Huth /* std / stdu*/ 2857*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) { 2858*fcf5ef2aSThomas Huth if (unlikely(rA(ctx->opcode) == 0)) { 2859*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 2860*fcf5ef2aSThomas Huth return; 2861*fcf5ef2aSThomas Huth } 2862*fcf5ef2aSThomas Huth } 2863*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2864*fcf5ef2aSThomas Huth EA = tcg_temp_new(); 2865*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, EA, 0x03); 2866*fcf5ef2aSThomas Huth gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA); 2867*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) 2868*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); 2869*fcf5ef2aSThomas Huth tcg_temp_free(EA); 2870*fcf5ef2aSThomas Huth } 2871*fcf5ef2aSThomas Huth } 2872*fcf5ef2aSThomas Huth #endif 2873*fcf5ef2aSThomas Huth /*** Integer load and store with byte reverse ***/ 2874*fcf5ef2aSThomas Huth 2875*fcf5ef2aSThomas Huth /* lhbrx */ 2876*fcf5ef2aSThomas Huth GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER); 2877*fcf5ef2aSThomas Huth 2878*fcf5ef2aSThomas Huth /* lwbrx */ 2879*fcf5ef2aSThomas Huth GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER); 2880*fcf5ef2aSThomas Huth 2881*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 2882*fcf5ef2aSThomas Huth /* ldbrx */ 2883*fcf5ef2aSThomas Huth GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE); 2884*fcf5ef2aSThomas Huth /* stdbrx */ 2885*fcf5ef2aSThomas Huth GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE); 2886*fcf5ef2aSThomas Huth #endif /* TARGET_PPC64 */ 2887*fcf5ef2aSThomas Huth 2888*fcf5ef2aSThomas Huth /* sthbrx */ 2889*fcf5ef2aSThomas Huth GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER); 2890*fcf5ef2aSThomas Huth /* stwbrx */ 2891*fcf5ef2aSThomas Huth GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER); 2892*fcf5ef2aSThomas Huth 2893*fcf5ef2aSThomas Huth /*** Integer load and store multiple ***/ 2894*fcf5ef2aSThomas Huth 2895*fcf5ef2aSThomas Huth /* lmw */ 2896*fcf5ef2aSThomas Huth static void gen_lmw(DisasContext *ctx) 2897*fcf5ef2aSThomas Huth { 2898*fcf5ef2aSThomas Huth TCGv t0; 2899*fcf5ef2aSThomas Huth TCGv_i32 t1; 2900*fcf5ef2aSThomas Huth 2901*fcf5ef2aSThomas Huth if (ctx->le_mode) { 2902*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 2903*fcf5ef2aSThomas Huth return; 2904*fcf5ef2aSThomas Huth } 2905*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2906*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2907*fcf5ef2aSThomas Huth t1 = tcg_const_i32(rD(ctx->opcode)); 2908*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, t0, 0); 2909*fcf5ef2aSThomas Huth gen_helper_lmw(cpu_env, t0, t1); 2910*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2911*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 2912*fcf5ef2aSThomas Huth } 2913*fcf5ef2aSThomas Huth 2914*fcf5ef2aSThomas Huth /* stmw */ 2915*fcf5ef2aSThomas Huth static void gen_stmw(DisasContext *ctx) 2916*fcf5ef2aSThomas Huth { 2917*fcf5ef2aSThomas Huth TCGv t0; 2918*fcf5ef2aSThomas Huth TCGv_i32 t1; 2919*fcf5ef2aSThomas Huth 2920*fcf5ef2aSThomas Huth if (ctx->le_mode) { 2921*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 2922*fcf5ef2aSThomas Huth return; 2923*fcf5ef2aSThomas Huth } 2924*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2925*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2926*fcf5ef2aSThomas Huth t1 = tcg_const_i32(rS(ctx->opcode)); 2927*fcf5ef2aSThomas Huth gen_addr_imm_index(ctx, t0, 0); 2928*fcf5ef2aSThomas Huth gen_helper_stmw(cpu_env, t0, t1); 2929*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2930*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 2931*fcf5ef2aSThomas Huth } 2932*fcf5ef2aSThomas Huth 2933*fcf5ef2aSThomas Huth /*** Integer load and store strings ***/ 2934*fcf5ef2aSThomas Huth 2935*fcf5ef2aSThomas Huth /* lswi */ 2936*fcf5ef2aSThomas Huth /* PowerPC32 specification says we must generate an exception if 2937*fcf5ef2aSThomas Huth * rA is in the range of registers to be loaded. 2938*fcf5ef2aSThomas Huth * In an other hand, IBM says this is valid, but rA won't be loaded. 2939*fcf5ef2aSThomas Huth * For now, I'll follow the spec... 2940*fcf5ef2aSThomas Huth */ 2941*fcf5ef2aSThomas Huth static void gen_lswi(DisasContext *ctx) 2942*fcf5ef2aSThomas Huth { 2943*fcf5ef2aSThomas Huth TCGv t0; 2944*fcf5ef2aSThomas Huth TCGv_i32 t1, t2; 2945*fcf5ef2aSThomas Huth int nb = NB(ctx->opcode); 2946*fcf5ef2aSThomas Huth int start = rD(ctx->opcode); 2947*fcf5ef2aSThomas Huth int ra = rA(ctx->opcode); 2948*fcf5ef2aSThomas Huth int nr; 2949*fcf5ef2aSThomas Huth 2950*fcf5ef2aSThomas Huth if (ctx->le_mode) { 2951*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 2952*fcf5ef2aSThomas Huth return; 2953*fcf5ef2aSThomas Huth } 2954*fcf5ef2aSThomas Huth if (nb == 0) 2955*fcf5ef2aSThomas Huth nb = 32; 2956*fcf5ef2aSThomas Huth nr = (nb + 3) / 4; 2957*fcf5ef2aSThomas Huth if (unlikely(lsw_reg_in_range(start, nr, ra))) { 2958*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX); 2959*fcf5ef2aSThomas Huth return; 2960*fcf5ef2aSThomas Huth } 2961*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2962*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2963*fcf5ef2aSThomas Huth gen_addr_register(ctx, t0); 2964*fcf5ef2aSThomas Huth t1 = tcg_const_i32(nb); 2965*fcf5ef2aSThomas Huth t2 = tcg_const_i32(start); 2966*fcf5ef2aSThomas Huth gen_helper_lsw(cpu_env, t0, t1, t2); 2967*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2968*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 2969*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 2970*fcf5ef2aSThomas Huth } 2971*fcf5ef2aSThomas Huth 2972*fcf5ef2aSThomas Huth /* lswx */ 2973*fcf5ef2aSThomas Huth static void gen_lswx(DisasContext *ctx) 2974*fcf5ef2aSThomas Huth { 2975*fcf5ef2aSThomas Huth TCGv t0; 2976*fcf5ef2aSThomas Huth TCGv_i32 t1, t2, t3; 2977*fcf5ef2aSThomas Huth 2978*fcf5ef2aSThomas Huth if (ctx->le_mode) { 2979*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 2980*fcf5ef2aSThomas Huth return; 2981*fcf5ef2aSThomas Huth } 2982*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 2983*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 2984*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 2985*fcf5ef2aSThomas Huth t1 = tcg_const_i32(rD(ctx->opcode)); 2986*fcf5ef2aSThomas Huth t2 = tcg_const_i32(rA(ctx->opcode)); 2987*fcf5ef2aSThomas Huth t3 = tcg_const_i32(rB(ctx->opcode)); 2988*fcf5ef2aSThomas Huth gen_helper_lswx(cpu_env, t0, t1, t2, t3); 2989*fcf5ef2aSThomas Huth tcg_temp_free(t0); 2990*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 2991*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 2992*fcf5ef2aSThomas Huth tcg_temp_free_i32(t3); 2993*fcf5ef2aSThomas Huth } 2994*fcf5ef2aSThomas Huth 2995*fcf5ef2aSThomas Huth /* stswi */ 2996*fcf5ef2aSThomas Huth static void gen_stswi(DisasContext *ctx) 2997*fcf5ef2aSThomas Huth { 2998*fcf5ef2aSThomas Huth TCGv t0; 2999*fcf5ef2aSThomas Huth TCGv_i32 t1, t2; 3000*fcf5ef2aSThomas Huth int nb = NB(ctx->opcode); 3001*fcf5ef2aSThomas Huth 3002*fcf5ef2aSThomas Huth if (ctx->le_mode) { 3003*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 3004*fcf5ef2aSThomas Huth return; 3005*fcf5ef2aSThomas Huth } 3006*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 3007*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 3008*fcf5ef2aSThomas Huth gen_addr_register(ctx, t0); 3009*fcf5ef2aSThomas Huth if (nb == 0) 3010*fcf5ef2aSThomas Huth nb = 32; 3011*fcf5ef2aSThomas Huth t1 = tcg_const_i32(nb); 3012*fcf5ef2aSThomas Huth t2 = tcg_const_i32(rS(ctx->opcode)); 3013*fcf5ef2aSThomas Huth gen_helper_stsw(cpu_env, t0, t1, t2); 3014*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3015*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 3016*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 3017*fcf5ef2aSThomas Huth } 3018*fcf5ef2aSThomas Huth 3019*fcf5ef2aSThomas Huth /* stswx */ 3020*fcf5ef2aSThomas Huth static void gen_stswx(DisasContext *ctx) 3021*fcf5ef2aSThomas Huth { 3022*fcf5ef2aSThomas Huth TCGv t0; 3023*fcf5ef2aSThomas Huth TCGv_i32 t1, t2; 3024*fcf5ef2aSThomas Huth 3025*fcf5ef2aSThomas Huth if (ctx->le_mode) { 3026*fcf5ef2aSThomas Huth gen_align_no_le(ctx); 3027*fcf5ef2aSThomas Huth return; 3028*fcf5ef2aSThomas Huth } 3029*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_INT); 3030*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 3031*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 3032*fcf5ef2aSThomas Huth t1 = tcg_temp_new_i32(); 3033*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, cpu_xer); 3034*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t1, t1, 0x7F); 3035*fcf5ef2aSThomas Huth t2 = tcg_const_i32(rS(ctx->opcode)); 3036*fcf5ef2aSThomas Huth gen_helper_stsw(cpu_env, t0, t1, t2); 3037*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3038*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 3039*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 3040*fcf5ef2aSThomas Huth } 3041*fcf5ef2aSThomas Huth 3042*fcf5ef2aSThomas Huth /*** Memory synchronisation ***/ 3043*fcf5ef2aSThomas Huth /* eieio */ 3044*fcf5ef2aSThomas Huth static void gen_eieio(DisasContext *ctx) 3045*fcf5ef2aSThomas Huth { 3046*fcf5ef2aSThomas Huth } 3047*fcf5ef2aSThomas Huth 3048*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 3049*fcf5ef2aSThomas Huth static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) 3050*fcf5ef2aSThomas Huth { 3051*fcf5ef2aSThomas Huth TCGv_i32 t; 3052*fcf5ef2aSThomas Huth TCGLabel *l; 3053*fcf5ef2aSThomas Huth 3054*fcf5ef2aSThomas Huth if (!ctx->lazy_tlb_flush) { 3055*fcf5ef2aSThomas Huth return; 3056*fcf5ef2aSThomas Huth } 3057*fcf5ef2aSThomas Huth l = gen_new_label(); 3058*fcf5ef2aSThomas Huth t = tcg_temp_new_i32(); 3059*fcf5ef2aSThomas Huth tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush)); 3060*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l); 3061*fcf5ef2aSThomas Huth if (global) { 3062*fcf5ef2aSThomas Huth gen_helper_check_tlb_flush_global(cpu_env); 3063*fcf5ef2aSThomas Huth } else { 3064*fcf5ef2aSThomas Huth gen_helper_check_tlb_flush_local(cpu_env); 3065*fcf5ef2aSThomas Huth } 3066*fcf5ef2aSThomas Huth gen_set_label(l); 3067*fcf5ef2aSThomas Huth tcg_temp_free_i32(t); 3068*fcf5ef2aSThomas Huth } 3069*fcf5ef2aSThomas Huth #else 3070*fcf5ef2aSThomas Huth static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { } 3071*fcf5ef2aSThomas Huth #endif 3072*fcf5ef2aSThomas Huth 3073*fcf5ef2aSThomas Huth /* isync */ 3074*fcf5ef2aSThomas Huth static void gen_isync(DisasContext *ctx) 3075*fcf5ef2aSThomas Huth { 3076*fcf5ef2aSThomas Huth /* 3077*fcf5ef2aSThomas Huth * We need to check for a pending TLB flush. This can only happen in 3078*fcf5ef2aSThomas Huth * kernel mode however so check MSR_PR 3079*fcf5ef2aSThomas Huth */ 3080*fcf5ef2aSThomas Huth if (!ctx->pr) { 3081*fcf5ef2aSThomas Huth gen_check_tlb_flush(ctx, false); 3082*fcf5ef2aSThomas Huth } 3083*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3084*fcf5ef2aSThomas Huth } 3085*fcf5ef2aSThomas Huth 3086*fcf5ef2aSThomas Huth #define MEMOP_GET_SIZE(x) (1 << ((x) & MO_SIZE)) 3087*fcf5ef2aSThomas Huth 3088*fcf5ef2aSThomas Huth #define LARX(name, memop) \ 3089*fcf5ef2aSThomas Huth static void gen_##name(DisasContext *ctx) \ 3090*fcf5ef2aSThomas Huth { \ 3091*fcf5ef2aSThomas Huth TCGv t0; \ 3092*fcf5ef2aSThomas Huth TCGv gpr = cpu_gpr[rD(ctx->opcode)]; \ 3093*fcf5ef2aSThomas Huth int len = MEMOP_GET_SIZE(memop); \ 3094*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_RES); \ 3095*fcf5ef2aSThomas Huth t0 = tcg_temp_local_new(); \ 3096*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); \ 3097*fcf5ef2aSThomas Huth if ((len) > 1) { \ 3098*fcf5ef2aSThomas Huth gen_check_align(ctx, t0, (len)-1); \ 3099*fcf5ef2aSThomas Huth } \ 3100*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_tl(gpr, t0, ctx->mem_idx, memop); \ 3101*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_reserve, t0); \ 3102*fcf5ef2aSThomas Huth tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \ 3103*fcf5ef2aSThomas Huth tcg_temp_free(t0); \ 3104*fcf5ef2aSThomas Huth } 3105*fcf5ef2aSThomas Huth 3106*fcf5ef2aSThomas Huth /* lwarx */ 3107*fcf5ef2aSThomas Huth LARX(lbarx, DEF_MEMOP(MO_UB)) 3108*fcf5ef2aSThomas Huth LARX(lharx, DEF_MEMOP(MO_UW)) 3109*fcf5ef2aSThomas Huth LARX(lwarx, DEF_MEMOP(MO_UL)) 3110*fcf5ef2aSThomas Huth 3111*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3112*fcf5ef2aSThomas Huth static void gen_conditional_store(DisasContext *ctx, TCGv EA, 3113*fcf5ef2aSThomas Huth int reg, int memop) 3114*fcf5ef2aSThomas Huth { 3115*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 3116*fcf5ef2aSThomas Huth 3117*fcf5ef2aSThomas Huth tcg_gen_st_tl(EA, cpu_env, offsetof(CPUPPCState, reserve_ea)); 3118*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t0, (MEMOP_GET_SIZE(memop) << 5) | reg); 3119*fcf5ef2aSThomas Huth tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info)); 3120*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3121*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_STCX, 0); 3122*fcf5ef2aSThomas Huth } 3123*fcf5ef2aSThomas Huth #else 3124*fcf5ef2aSThomas Huth static void gen_conditional_store(DisasContext *ctx, TCGv EA, 3125*fcf5ef2aSThomas Huth int reg, int memop) 3126*fcf5ef2aSThomas Huth { 3127*fcf5ef2aSThomas Huth TCGLabel *l1; 3128*fcf5ef2aSThomas Huth 3129*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); 3130*fcf5ef2aSThomas Huth l1 = gen_new_label(); 3131*fcf5ef2aSThomas Huth tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1); 3132*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); 3133*fcf5ef2aSThomas Huth tcg_gen_qemu_st_tl(cpu_gpr[reg], EA, ctx->mem_idx, memop); 3134*fcf5ef2aSThomas Huth gen_set_label(l1); 3135*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_reserve, -1); 3136*fcf5ef2aSThomas Huth } 3137*fcf5ef2aSThomas Huth #endif 3138*fcf5ef2aSThomas Huth 3139*fcf5ef2aSThomas Huth #define STCX(name, memop) \ 3140*fcf5ef2aSThomas Huth static void gen_##name(DisasContext *ctx) \ 3141*fcf5ef2aSThomas Huth { \ 3142*fcf5ef2aSThomas Huth TCGv t0; \ 3143*fcf5ef2aSThomas Huth int len = MEMOP_GET_SIZE(memop); \ 3144*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_RES); \ 3145*fcf5ef2aSThomas Huth t0 = tcg_temp_local_new(); \ 3146*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); \ 3147*fcf5ef2aSThomas Huth if (len > 1) { \ 3148*fcf5ef2aSThomas Huth gen_check_align(ctx, t0, (len) - 1); \ 3149*fcf5ef2aSThomas Huth } \ 3150*fcf5ef2aSThomas Huth gen_conditional_store(ctx, t0, rS(ctx->opcode), memop); \ 3151*fcf5ef2aSThomas Huth tcg_temp_free(t0); \ 3152*fcf5ef2aSThomas Huth } 3153*fcf5ef2aSThomas Huth 3154*fcf5ef2aSThomas Huth STCX(stbcx_, DEF_MEMOP(MO_UB)) 3155*fcf5ef2aSThomas Huth STCX(sthcx_, DEF_MEMOP(MO_UW)) 3156*fcf5ef2aSThomas Huth STCX(stwcx_, DEF_MEMOP(MO_UL)) 3157*fcf5ef2aSThomas Huth 3158*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3159*fcf5ef2aSThomas Huth /* ldarx */ 3160*fcf5ef2aSThomas Huth LARX(ldarx, DEF_MEMOP(MO_Q)) 3161*fcf5ef2aSThomas Huth /* stdcx. */ 3162*fcf5ef2aSThomas Huth STCX(stdcx_, DEF_MEMOP(MO_Q)) 3163*fcf5ef2aSThomas Huth 3164*fcf5ef2aSThomas Huth /* lqarx */ 3165*fcf5ef2aSThomas Huth static void gen_lqarx(DisasContext *ctx) 3166*fcf5ef2aSThomas Huth { 3167*fcf5ef2aSThomas Huth TCGv EA; 3168*fcf5ef2aSThomas Huth int rd = rD(ctx->opcode); 3169*fcf5ef2aSThomas Huth TCGv gpr1, gpr2; 3170*fcf5ef2aSThomas Huth 3171*fcf5ef2aSThomas Huth if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) || 3172*fcf5ef2aSThomas Huth (rd == rB(ctx->opcode)))) { 3173*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 3174*fcf5ef2aSThomas Huth return; 3175*fcf5ef2aSThomas Huth } 3176*fcf5ef2aSThomas Huth 3177*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_RES); 3178*fcf5ef2aSThomas Huth EA = tcg_temp_local_new(); 3179*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); 3180*fcf5ef2aSThomas Huth gen_check_align(ctx, EA, 15); 3181*fcf5ef2aSThomas Huth if (unlikely(ctx->le_mode)) { 3182*fcf5ef2aSThomas Huth gpr1 = cpu_gpr[rd+1]; 3183*fcf5ef2aSThomas Huth gpr2 = cpu_gpr[rd]; 3184*fcf5ef2aSThomas Huth } else { 3185*fcf5ef2aSThomas Huth gpr1 = cpu_gpr[rd]; 3186*fcf5ef2aSThomas Huth gpr2 = cpu_gpr[rd+1]; 3187*fcf5ef2aSThomas Huth } 3188*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i64(gpr1, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); 3189*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_reserve, EA); 3190*fcf5ef2aSThomas Huth gen_addr_add(ctx, EA, EA, 8); 3191*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i64(gpr2, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); 3192*fcf5ef2aSThomas Huth 3193*fcf5ef2aSThomas Huth tcg_gen_st_tl(gpr1, cpu_env, offsetof(CPUPPCState, reserve_val)); 3194*fcf5ef2aSThomas Huth tcg_gen_st_tl(gpr2, cpu_env, offsetof(CPUPPCState, reserve_val2)); 3195*fcf5ef2aSThomas Huth tcg_temp_free(EA); 3196*fcf5ef2aSThomas Huth } 3197*fcf5ef2aSThomas Huth 3198*fcf5ef2aSThomas Huth /* stqcx. */ 3199*fcf5ef2aSThomas Huth static void gen_stqcx_(DisasContext *ctx) 3200*fcf5ef2aSThomas Huth { 3201*fcf5ef2aSThomas Huth TCGv EA; 3202*fcf5ef2aSThomas Huth int reg = rS(ctx->opcode); 3203*fcf5ef2aSThomas Huth int len = 16; 3204*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 3205*fcf5ef2aSThomas Huth TCGLabel *l1; 3206*fcf5ef2aSThomas Huth TCGv gpr1, gpr2; 3207*fcf5ef2aSThomas Huth #endif 3208*fcf5ef2aSThomas Huth 3209*fcf5ef2aSThomas Huth if (unlikely((rD(ctx->opcode) & 1))) { 3210*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 3211*fcf5ef2aSThomas Huth return; 3212*fcf5ef2aSThomas Huth } 3213*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_RES); 3214*fcf5ef2aSThomas Huth EA = tcg_temp_local_new(); 3215*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); 3216*fcf5ef2aSThomas Huth if (len > 1) { 3217*fcf5ef2aSThomas Huth gen_check_align(ctx, EA, (len) - 1); 3218*fcf5ef2aSThomas Huth } 3219*fcf5ef2aSThomas Huth 3220*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3221*fcf5ef2aSThomas Huth gen_conditional_store(ctx, EA, reg, 16); 3222*fcf5ef2aSThomas Huth #else 3223*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); 3224*fcf5ef2aSThomas Huth l1 = gen_new_label(); 3225*fcf5ef2aSThomas Huth tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1); 3226*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); 3227*fcf5ef2aSThomas Huth 3228*fcf5ef2aSThomas Huth if (unlikely(ctx->le_mode)) { 3229*fcf5ef2aSThomas Huth gpr1 = cpu_gpr[reg + 1]; 3230*fcf5ef2aSThomas Huth gpr2 = cpu_gpr[reg]; 3231*fcf5ef2aSThomas Huth } else { 3232*fcf5ef2aSThomas Huth gpr1 = cpu_gpr[reg]; 3233*fcf5ef2aSThomas Huth gpr2 = cpu_gpr[reg + 1]; 3234*fcf5ef2aSThomas Huth } 3235*fcf5ef2aSThomas Huth tcg_gen_qemu_st_tl(gpr1, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); 3236*fcf5ef2aSThomas Huth gen_addr_add(ctx, EA, EA, 8); 3237*fcf5ef2aSThomas Huth tcg_gen_qemu_st_tl(gpr2, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); 3238*fcf5ef2aSThomas Huth 3239*fcf5ef2aSThomas Huth gen_set_label(l1); 3240*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_reserve, -1); 3241*fcf5ef2aSThomas Huth #endif 3242*fcf5ef2aSThomas Huth tcg_temp_free(EA); 3243*fcf5ef2aSThomas Huth } 3244*fcf5ef2aSThomas Huth 3245*fcf5ef2aSThomas Huth #endif /* defined(TARGET_PPC64) */ 3246*fcf5ef2aSThomas Huth 3247*fcf5ef2aSThomas Huth /* sync */ 3248*fcf5ef2aSThomas Huth static void gen_sync(DisasContext *ctx) 3249*fcf5ef2aSThomas Huth { 3250*fcf5ef2aSThomas Huth uint32_t l = (ctx->opcode >> 21) & 3; 3251*fcf5ef2aSThomas Huth 3252*fcf5ef2aSThomas Huth /* 3253*fcf5ef2aSThomas Huth * We may need to check for a pending TLB flush. 3254*fcf5ef2aSThomas Huth * 3255*fcf5ef2aSThomas Huth * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32. 3256*fcf5ef2aSThomas Huth * 3257*fcf5ef2aSThomas Huth * Additionally, this can only happen in kernel mode however so 3258*fcf5ef2aSThomas Huth * check MSR_PR as well. 3259*fcf5ef2aSThomas Huth */ 3260*fcf5ef2aSThomas Huth if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) { 3261*fcf5ef2aSThomas Huth gen_check_tlb_flush(ctx, true); 3262*fcf5ef2aSThomas Huth } 3263*fcf5ef2aSThomas Huth } 3264*fcf5ef2aSThomas Huth 3265*fcf5ef2aSThomas Huth /* wait */ 3266*fcf5ef2aSThomas Huth static void gen_wait(DisasContext *ctx) 3267*fcf5ef2aSThomas Huth { 3268*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(1); 3269*fcf5ef2aSThomas Huth tcg_gen_st_i32(t0, cpu_env, 3270*fcf5ef2aSThomas Huth -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted)); 3271*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 3272*fcf5ef2aSThomas Huth /* Stop translation, as the CPU is supposed to sleep from now */ 3273*fcf5ef2aSThomas Huth gen_exception_nip(ctx, EXCP_HLT, ctx->nip); 3274*fcf5ef2aSThomas Huth } 3275*fcf5ef2aSThomas Huth 3276*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3277*fcf5ef2aSThomas Huth static void gen_doze(DisasContext *ctx) 3278*fcf5ef2aSThomas Huth { 3279*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3280*fcf5ef2aSThomas Huth GEN_PRIV; 3281*fcf5ef2aSThomas Huth #else 3282*fcf5ef2aSThomas Huth TCGv_i32 t; 3283*fcf5ef2aSThomas Huth 3284*fcf5ef2aSThomas Huth CHK_HV; 3285*fcf5ef2aSThomas Huth t = tcg_const_i32(PPC_PM_DOZE); 3286*fcf5ef2aSThomas Huth gen_helper_pminsn(cpu_env, t); 3287*fcf5ef2aSThomas Huth tcg_temp_free_i32(t); 3288*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3289*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 3290*fcf5ef2aSThomas Huth } 3291*fcf5ef2aSThomas Huth 3292*fcf5ef2aSThomas Huth static void gen_nap(DisasContext *ctx) 3293*fcf5ef2aSThomas Huth { 3294*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3295*fcf5ef2aSThomas Huth GEN_PRIV; 3296*fcf5ef2aSThomas Huth #else 3297*fcf5ef2aSThomas Huth TCGv_i32 t; 3298*fcf5ef2aSThomas Huth 3299*fcf5ef2aSThomas Huth CHK_HV; 3300*fcf5ef2aSThomas Huth t = tcg_const_i32(PPC_PM_NAP); 3301*fcf5ef2aSThomas Huth gen_helper_pminsn(cpu_env, t); 3302*fcf5ef2aSThomas Huth tcg_temp_free_i32(t); 3303*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3304*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 3305*fcf5ef2aSThomas Huth } 3306*fcf5ef2aSThomas Huth 3307*fcf5ef2aSThomas Huth static void gen_sleep(DisasContext *ctx) 3308*fcf5ef2aSThomas Huth { 3309*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3310*fcf5ef2aSThomas Huth GEN_PRIV; 3311*fcf5ef2aSThomas Huth #else 3312*fcf5ef2aSThomas Huth TCGv_i32 t; 3313*fcf5ef2aSThomas Huth 3314*fcf5ef2aSThomas Huth CHK_HV; 3315*fcf5ef2aSThomas Huth t = tcg_const_i32(PPC_PM_SLEEP); 3316*fcf5ef2aSThomas Huth gen_helper_pminsn(cpu_env, t); 3317*fcf5ef2aSThomas Huth tcg_temp_free_i32(t); 3318*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3319*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 3320*fcf5ef2aSThomas Huth } 3321*fcf5ef2aSThomas Huth 3322*fcf5ef2aSThomas Huth static void gen_rvwinkle(DisasContext *ctx) 3323*fcf5ef2aSThomas Huth { 3324*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3325*fcf5ef2aSThomas Huth GEN_PRIV; 3326*fcf5ef2aSThomas Huth #else 3327*fcf5ef2aSThomas Huth TCGv_i32 t; 3328*fcf5ef2aSThomas Huth 3329*fcf5ef2aSThomas Huth CHK_HV; 3330*fcf5ef2aSThomas Huth t = tcg_const_i32(PPC_PM_RVWINKLE); 3331*fcf5ef2aSThomas Huth gen_helper_pminsn(cpu_env, t); 3332*fcf5ef2aSThomas Huth tcg_temp_free_i32(t); 3333*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3334*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 3335*fcf5ef2aSThomas Huth } 3336*fcf5ef2aSThomas Huth #endif /* #if defined(TARGET_PPC64) */ 3337*fcf5ef2aSThomas Huth 3338*fcf5ef2aSThomas Huth static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip) 3339*fcf5ef2aSThomas Huth { 3340*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3341*fcf5ef2aSThomas Huth if (ctx->has_cfar) 3342*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_cfar, nip); 3343*fcf5ef2aSThomas Huth #endif 3344*fcf5ef2aSThomas Huth } 3345*fcf5ef2aSThomas Huth 3346*fcf5ef2aSThomas Huth static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) 3347*fcf5ef2aSThomas Huth { 3348*fcf5ef2aSThomas Huth if (unlikely(ctx->singlestep_enabled)) { 3349*fcf5ef2aSThomas Huth return false; 3350*fcf5ef2aSThomas Huth } 3351*fcf5ef2aSThomas Huth 3352*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY 3353*fcf5ef2aSThomas Huth return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); 3354*fcf5ef2aSThomas Huth #else 3355*fcf5ef2aSThomas Huth return true; 3356*fcf5ef2aSThomas Huth #endif 3357*fcf5ef2aSThomas Huth } 3358*fcf5ef2aSThomas Huth 3359*fcf5ef2aSThomas Huth /*** Branch ***/ 3360*fcf5ef2aSThomas Huth static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) 3361*fcf5ef2aSThomas Huth { 3362*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 3363*fcf5ef2aSThomas Huth dest = (uint32_t) dest; 3364*fcf5ef2aSThomas Huth } 3365*fcf5ef2aSThomas Huth if (use_goto_tb(ctx, dest)) { 3366*fcf5ef2aSThomas Huth tcg_gen_goto_tb(n); 3367*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_nip, dest & ~3); 3368*fcf5ef2aSThomas Huth tcg_gen_exit_tb((uintptr_t)ctx->tb + n); 3369*fcf5ef2aSThomas Huth } else { 3370*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_nip, dest & ~3); 3371*fcf5ef2aSThomas Huth if (unlikely(ctx->singlestep_enabled)) { 3372*fcf5ef2aSThomas Huth if ((ctx->singlestep_enabled & 3373*fcf5ef2aSThomas Huth (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) && 3374*fcf5ef2aSThomas Huth (ctx->exception == POWERPC_EXCP_BRANCH || 3375*fcf5ef2aSThomas Huth ctx->exception == POWERPC_EXCP_TRACE)) { 3376*fcf5ef2aSThomas Huth gen_exception_nip(ctx, POWERPC_EXCP_TRACE, dest); 3377*fcf5ef2aSThomas Huth } 3378*fcf5ef2aSThomas Huth if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) { 3379*fcf5ef2aSThomas Huth gen_debug_exception(ctx); 3380*fcf5ef2aSThomas Huth } 3381*fcf5ef2aSThomas Huth } 3382*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 3383*fcf5ef2aSThomas Huth } 3384*fcf5ef2aSThomas Huth } 3385*fcf5ef2aSThomas Huth 3386*fcf5ef2aSThomas Huth static inline void gen_setlr(DisasContext *ctx, target_ulong nip) 3387*fcf5ef2aSThomas Huth { 3388*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 3389*fcf5ef2aSThomas Huth nip = (uint32_t)nip; 3390*fcf5ef2aSThomas Huth } 3391*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_lr, nip); 3392*fcf5ef2aSThomas Huth } 3393*fcf5ef2aSThomas Huth 3394*fcf5ef2aSThomas Huth /* b ba bl bla */ 3395*fcf5ef2aSThomas Huth static void gen_b(DisasContext *ctx) 3396*fcf5ef2aSThomas Huth { 3397*fcf5ef2aSThomas Huth target_ulong li, target; 3398*fcf5ef2aSThomas Huth 3399*fcf5ef2aSThomas Huth ctx->exception = POWERPC_EXCP_BRANCH; 3400*fcf5ef2aSThomas Huth /* sign extend LI */ 3401*fcf5ef2aSThomas Huth li = LI(ctx->opcode); 3402*fcf5ef2aSThomas Huth li = (li ^ 0x02000000) - 0x02000000; 3403*fcf5ef2aSThomas Huth if (likely(AA(ctx->opcode) == 0)) { 3404*fcf5ef2aSThomas Huth target = ctx->nip + li - 4; 3405*fcf5ef2aSThomas Huth } else { 3406*fcf5ef2aSThomas Huth target = li; 3407*fcf5ef2aSThomas Huth } 3408*fcf5ef2aSThomas Huth if (LK(ctx->opcode)) { 3409*fcf5ef2aSThomas Huth gen_setlr(ctx, ctx->nip); 3410*fcf5ef2aSThomas Huth } 3411*fcf5ef2aSThomas Huth gen_update_cfar(ctx, ctx->nip - 4); 3412*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 0, target); 3413*fcf5ef2aSThomas Huth } 3414*fcf5ef2aSThomas Huth 3415*fcf5ef2aSThomas Huth #define BCOND_IM 0 3416*fcf5ef2aSThomas Huth #define BCOND_LR 1 3417*fcf5ef2aSThomas Huth #define BCOND_CTR 2 3418*fcf5ef2aSThomas Huth #define BCOND_TAR 3 3419*fcf5ef2aSThomas Huth 3420*fcf5ef2aSThomas Huth static inline void gen_bcond(DisasContext *ctx, int type) 3421*fcf5ef2aSThomas Huth { 3422*fcf5ef2aSThomas Huth uint32_t bo = BO(ctx->opcode); 3423*fcf5ef2aSThomas Huth TCGLabel *l1; 3424*fcf5ef2aSThomas Huth TCGv target; 3425*fcf5ef2aSThomas Huth 3426*fcf5ef2aSThomas Huth ctx->exception = POWERPC_EXCP_BRANCH; 3427*fcf5ef2aSThomas Huth if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) { 3428*fcf5ef2aSThomas Huth target = tcg_temp_local_new(); 3429*fcf5ef2aSThomas Huth if (type == BCOND_CTR) 3430*fcf5ef2aSThomas Huth tcg_gen_mov_tl(target, cpu_ctr); 3431*fcf5ef2aSThomas Huth else if (type == BCOND_TAR) 3432*fcf5ef2aSThomas Huth gen_load_spr(target, SPR_TAR); 3433*fcf5ef2aSThomas Huth else 3434*fcf5ef2aSThomas Huth tcg_gen_mov_tl(target, cpu_lr); 3435*fcf5ef2aSThomas Huth } else { 3436*fcf5ef2aSThomas Huth TCGV_UNUSED(target); 3437*fcf5ef2aSThomas Huth } 3438*fcf5ef2aSThomas Huth if (LK(ctx->opcode)) 3439*fcf5ef2aSThomas Huth gen_setlr(ctx, ctx->nip); 3440*fcf5ef2aSThomas Huth l1 = gen_new_label(); 3441*fcf5ef2aSThomas Huth if ((bo & 0x4) == 0) { 3442*fcf5ef2aSThomas Huth /* Decrement and test CTR */ 3443*fcf5ef2aSThomas Huth TCGv temp = tcg_temp_new(); 3444*fcf5ef2aSThomas Huth if (unlikely(type == BCOND_CTR)) { 3445*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 3446*fcf5ef2aSThomas Huth return; 3447*fcf5ef2aSThomas Huth } 3448*fcf5ef2aSThomas Huth tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1); 3449*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 3450*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(temp, cpu_ctr); 3451*fcf5ef2aSThomas Huth } else { 3452*fcf5ef2aSThomas Huth tcg_gen_mov_tl(temp, cpu_ctr); 3453*fcf5ef2aSThomas Huth } 3454*fcf5ef2aSThomas Huth if (bo & 0x2) { 3455*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1); 3456*fcf5ef2aSThomas Huth } else { 3457*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); 3458*fcf5ef2aSThomas Huth } 3459*fcf5ef2aSThomas Huth tcg_temp_free(temp); 3460*fcf5ef2aSThomas Huth } 3461*fcf5ef2aSThomas Huth if ((bo & 0x10) == 0) { 3462*fcf5ef2aSThomas Huth /* Test CR */ 3463*fcf5ef2aSThomas Huth uint32_t bi = BI(ctx->opcode); 3464*fcf5ef2aSThomas Huth uint32_t mask = 0x08 >> (bi & 0x03); 3465*fcf5ef2aSThomas Huth TCGv_i32 temp = tcg_temp_new_i32(); 3466*fcf5ef2aSThomas Huth 3467*fcf5ef2aSThomas Huth if (bo & 0x8) { 3468*fcf5ef2aSThomas Huth tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask); 3469*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1); 3470*fcf5ef2aSThomas Huth } else { 3471*fcf5ef2aSThomas Huth tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask); 3472*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1); 3473*fcf5ef2aSThomas Huth } 3474*fcf5ef2aSThomas Huth tcg_temp_free_i32(temp); 3475*fcf5ef2aSThomas Huth } 3476*fcf5ef2aSThomas Huth gen_update_cfar(ctx, ctx->nip - 4); 3477*fcf5ef2aSThomas Huth if (type == BCOND_IM) { 3478*fcf5ef2aSThomas Huth target_ulong li = (target_long)((int16_t)(BD(ctx->opcode))); 3479*fcf5ef2aSThomas Huth if (likely(AA(ctx->opcode) == 0)) { 3480*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 0, ctx->nip + li - 4); 3481*fcf5ef2aSThomas Huth } else { 3482*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 0, li); 3483*fcf5ef2aSThomas Huth } 3484*fcf5ef2aSThomas Huth if ((bo & 0x14) != 0x14) { 3485*fcf5ef2aSThomas Huth gen_set_label(l1); 3486*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 1, ctx->nip); 3487*fcf5ef2aSThomas Huth } 3488*fcf5ef2aSThomas Huth } else { 3489*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 3490*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3); 3491*fcf5ef2aSThomas Huth } else { 3492*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_nip, target, ~3); 3493*fcf5ef2aSThomas Huth } 3494*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 3495*fcf5ef2aSThomas Huth if ((bo & 0x14) != 0x14) { 3496*fcf5ef2aSThomas Huth gen_set_label(l1); 3497*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip); 3498*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 3499*fcf5ef2aSThomas Huth } 3500*fcf5ef2aSThomas Huth } 3501*fcf5ef2aSThomas Huth if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) { 3502*fcf5ef2aSThomas Huth tcg_temp_free(target); 3503*fcf5ef2aSThomas Huth } 3504*fcf5ef2aSThomas Huth } 3505*fcf5ef2aSThomas Huth 3506*fcf5ef2aSThomas Huth static void gen_bc(DisasContext *ctx) 3507*fcf5ef2aSThomas Huth { 3508*fcf5ef2aSThomas Huth gen_bcond(ctx, BCOND_IM); 3509*fcf5ef2aSThomas Huth } 3510*fcf5ef2aSThomas Huth 3511*fcf5ef2aSThomas Huth static void gen_bcctr(DisasContext *ctx) 3512*fcf5ef2aSThomas Huth { 3513*fcf5ef2aSThomas Huth gen_bcond(ctx, BCOND_CTR); 3514*fcf5ef2aSThomas Huth } 3515*fcf5ef2aSThomas Huth 3516*fcf5ef2aSThomas Huth static void gen_bclr(DisasContext *ctx) 3517*fcf5ef2aSThomas Huth { 3518*fcf5ef2aSThomas Huth gen_bcond(ctx, BCOND_LR); 3519*fcf5ef2aSThomas Huth } 3520*fcf5ef2aSThomas Huth 3521*fcf5ef2aSThomas Huth static void gen_bctar(DisasContext *ctx) 3522*fcf5ef2aSThomas Huth { 3523*fcf5ef2aSThomas Huth gen_bcond(ctx, BCOND_TAR); 3524*fcf5ef2aSThomas Huth } 3525*fcf5ef2aSThomas Huth 3526*fcf5ef2aSThomas Huth /*** Condition register logical ***/ 3527*fcf5ef2aSThomas Huth #define GEN_CRLOGIC(name, tcg_op, opc) \ 3528*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 3529*fcf5ef2aSThomas Huth { \ 3530*fcf5ef2aSThomas Huth uint8_t bitmask; \ 3531*fcf5ef2aSThomas Huth int sh; \ 3532*fcf5ef2aSThomas Huth TCGv_i32 t0, t1; \ 3533*fcf5ef2aSThomas Huth sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \ 3534*fcf5ef2aSThomas Huth t0 = tcg_temp_new_i32(); \ 3535*fcf5ef2aSThomas Huth if (sh > 0) \ 3536*fcf5ef2aSThomas Huth tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \ 3537*fcf5ef2aSThomas Huth else if (sh < 0) \ 3538*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \ 3539*fcf5ef2aSThomas Huth else \ 3540*fcf5ef2aSThomas Huth tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \ 3541*fcf5ef2aSThomas Huth t1 = tcg_temp_new_i32(); \ 3542*fcf5ef2aSThomas Huth sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \ 3543*fcf5ef2aSThomas Huth if (sh > 0) \ 3544*fcf5ef2aSThomas Huth tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \ 3545*fcf5ef2aSThomas Huth else if (sh < 0) \ 3546*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \ 3547*fcf5ef2aSThomas Huth else \ 3548*fcf5ef2aSThomas Huth tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \ 3549*fcf5ef2aSThomas Huth tcg_op(t0, t0, t1); \ 3550*fcf5ef2aSThomas Huth bitmask = 0x08 >> (crbD(ctx->opcode) & 0x03); \ 3551*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t0, t0, bitmask); \ 3552*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \ 3553*fcf5ef2aSThomas Huth tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \ 3554*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); \ 3555*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); \ 3556*fcf5ef2aSThomas Huth } 3557*fcf5ef2aSThomas Huth 3558*fcf5ef2aSThomas Huth /* crand */ 3559*fcf5ef2aSThomas Huth GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08); 3560*fcf5ef2aSThomas Huth /* crandc */ 3561*fcf5ef2aSThomas Huth GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04); 3562*fcf5ef2aSThomas Huth /* creqv */ 3563*fcf5ef2aSThomas Huth GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09); 3564*fcf5ef2aSThomas Huth /* crnand */ 3565*fcf5ef2aSThomas Huth GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07); 3566*fcf5ef2aSThomas Huth /* crnor */ 3567*fcf5ef2aSThomas Huth GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01); 3568*fcf5ef2aSThomas Huth /* cror */ 3569*fcf5ef2aSThomas Huth GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E); 3570*fcf5ef2aSThomas Huth /* crorc */ 3571*fcf5ef2aSThomas Huth GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D); 3572*fcf5ef2aSThomas Huth /* crxor */ 3573*fcf5ef2aSThomas Huth GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06); 3574*fcf5ef2aSThomas Huth 3575*fcf5ef2aSThomas Huth /* mcrf */ 3576*fcf5ef2aSThomas Huth static void gen_mcrf(DisasContext *ctx) 3577*fcf5ef2aSThomas Huth { 3578*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]); 3579*fcf5ef2aSThomas Huth } 3580*fcf5ef2aSThomas Huth 3581*fcf5ef2aSThomas Huth /*** System linkage ***/ 3582*fcf5ef2aSThomas Huth 3583*fcf5ef2aSThomas Huth /* rfi (supervisor only) */ 3584*fcf5ef2aSThomas Huth static void gen_rfi(DisasContext *ctx) 3585*fcf5ef2aSThomas Huth { 3586*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3587*fcf5ef2aSThomas Huth GEN_PRIV; 3588*fcf5ef2aSThomas Huth #else 3589*fcf5ef2aSThomas Huth /* This instruction doesn't exist anymore on 64-bit server 3590*fcf5ef2aSThomas Huth * processors compliant with arch 2.x 3591*fcf5ef2aSThomas Huth */ 3592*fcf5ef2aSThomas Huth if (ctx->insns_flags & PPC_SEGMENT_64B) { 3593*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 3594*fcf5ef2aSThomas Huth return; 3595*fcf5ef2aSThomas Huth } 3596*fcf5ef2aSThomas Huth /* Restore CPU state */ 3597*fcf5ef2aSThomas Huth CHK_SV; 3598*fcf5ef2aSThomas Huth gen_update_cfar(ctx, ctx->nip - 4); 3599*fcf5ef2aSThomas Huth gen_helper_rfi(cpu_env); 3600*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 3601*fcf5ef2aSThomas Huth #endif 3602*fcf5ef2aSThomas Huth } 3603*fcf5ef2aSThomas Huth 3604*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3605*fcf5ef2aSThomas Huth static void gen_rfid(DisasContext *ctx) 3606*fcf5ef2aSThomas Huth { 3607*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3608*fcf5ef2aSThomas Huth GEN_PRIV; 3609*fcf5ef2aSThomas Huth #else 3610*fcf5ef2aSThomas Huth /* Restore CPU state */ 3611*fcf5ef2aSThomas Huth CHK_SV; 3612*fcf5ef2aSThomas Huth gen_update_cfar(ctx, ctx->nip - 4); 3613*fcf5ef2aSThomas Huth gen_helper_rfid(cpu_env); 3614*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 3615*fcf5ef2aSThomas Huth #endif 3616*fcf5ef2aSThomas Huth } 3617*fcf5ef2aSThomas Huth 3618*fcf5ef2aSThomas Huth static void gen_hrfid(DisasContext *ctx) 3619*fcf5ef2aSThomas Huth { 3620*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3621*fcf5ef2aSThomas Huth GEN_PRIV; 3622*fcf5ef2aSThomas Huth #else 3623*fcf5ef2aSThomas Huth /* Restore CPU state */ 3624*fcf5ef2aSThomas Huth CHK_HV; 3625*fcf5ef2aSThomas Huth gen_helper_hrfid(cpu_env); 3626*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 3627*fcf5ef2aSThomas Huth #endif 3628*fcf5ef2aSThomas Huth } 3629*fcf5ef2aSThomas Huth #endif 3630*fcf5ef2aSThomas Huth 3631*fcf5ef2aSThomas Huth /* sc */ 3632*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3633*fcf5ef2aSThomas Huth #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER 3634*fcf5ef2aSThomas Huth #else 3635*fcf5ef2aSThomas Huth #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL 3636*fcf5ef2aSThomas Huth #endif 3637*fcf5ef2aSThomas Huth static void gen_sc(DisasContext *ctx) 3638*fcf5ef2aSThomas Huth { 3639*fcf5ef2aSThomas Huth uint32_t lev; 3640*fcf5ef2aSThomas Huth 3641*fcf5ef2aSThomas Huth lev = (ctx->opcode >> 5) & 0x7F; 3642*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_SYSCALL, lev); 3643*fcf5ef2aSThomas Huth } 3644*fcf5ef2aSThomas Huth 3645*fcf5ef2aSThomas Huth /*** Trap ***/ 3646*fcf5ef2aSThomas Huth 3647*fcf5ef2aSThomas Huth /* Check for unconditional traps (always or never) */ 3648*fcf5ef2aSThomas Huth static bool check_unconditional_trap(DisasContext *ctx) 3649*fcf5ef2aSThomas Huth { 3650*fcf5ef2aSThomas Huth /* Trap never */ 3651*fcf5ef2aSThomas Huth if (TO(ctx->opcode) == 0) { 3652*fcf5ef2aSThomas Huth return true; 3653*fcf5ef2aSThomas Huth } 3654*fcf5ef2aSThomas Huth /* Trap always */ 3655*fcf5ef2aSThomas Huth if (TO(ctx->opcode) == 31) { 3656*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); 3657*fcf5ef2aSThomas Huth return true; 3658*fcf5ef2aSThomas Huth } 3659*fcf5ef2aSThomas Huth return false; 3660*fcf5ef2aSThomas Huth } 3661*fcf5ef2aSThomas Huth 3662*fcf5ef2aSThomas Huth /* tw */ 3663*fcf5ef2aSThomas Huth static void gen_tw(DisasContext *ctx) 3664*fcf5ef2aSThomas Huth { 3665*fcf5ef2aSThomas Huth TCGv_i32 t0; 3666*fcf5ef2aSThomas Huth 3667*fcf5ef2aSThomas Huth if (check_unconditional_trap(ctx)) { 3668*fcf5ef2aSThomas Huth return; 3669*fcf5ef2aSThomas Huth } 3670*fcf5ef2aSThomas Huth t0 = tcg_const_i32(TO(ctx->opcode)); 3671*fcf5ef2aSThomas Huth gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], 3672*fcf5ef2aSThomas Huth t0); 3673*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 3674*fcf5ef2aSThomas Huth } 3675*fcf5ef2aSThomas Huth 3676*fcf5ef2aSThomas Huth /* twi */ 3677*fcf5ef2aSThomas Huth static void gen_twi(DisasContext *ctx) 3678*fcf5ef2aSThomas Huth { 3679*fcf5ef2aSThomas Huth TCGv t0; 3680*fcf5ef2aSThomas Huth TCGv_i32 t1; 3681*fcf5ef2aSThomas Huth 3682*fcf5ef2aSThomas Huth if (check_unconditional_trap(ctx)) { 3683*fcf5ef2aSThomas Huth return; 3684*fcf5ef2aSThomas Huth } 3685*fcf5ef2aSThomas Huth t0 = tcg_const_tl(SIMM(ctx->opcode)); 3686*fcf5ef2aSThomas Huth t1 = tcg_const_i32(TO(ctx->opcode)); 3687*fcf5ef2aSThomas Huth gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1); 3688*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3689*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 3690*fcf5ef2aSThomas Huth } 3691*fcf5ef2aSThomas Huth 3692*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3693*fcf5ef2aSThomas Huth /* td */ 3694*fcf5ef2aSThomas Huth static void gen_td(DisasContext *ctx) 3695*fcf5ef2aSThomas Huth { 3696*fcf5ef2aSThomas Huth TCGv_i32 t0; 3697*fcf5ef2aSThomas Huth 3698*fcf5ef2aSThomas Huth if (check_unconditional_trap(ctx)) { 3699*fcf5ef2aSThomas Huth return; 3700*fcf5ef2aSThomas Huth } 3701*fcf5ef2aSThomas Huth t0 = tcg_const_i32(TO(ctx->opcode)); 3702*fcf5ef2aSThomas Huth gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], 3703*fcf5ef2aSThomas Huth t0); 3704*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 3705*fcf5ef2aSThomas Huth } 3706*fcf5ef2aSThomas Huth 3707*fcf5ef2aSThomas Huth /* tdi */ 3708*fcf5ef2aSThomas Huth static void gen_tdi(DisasContext *ctx) 3709*fcf5ef2aSThomas Huth { 3710*fcf5ef2aSThomas Huth TCGv t0; 3711*fcf5ef2aSThomas Huth TCGv_i32 t1; 3712*fcf5ef2aSThomas Huth 3713*fcf5ef2aSThomas Huth if (check_unconditional_trap(ctx)) { 3714*fcf5ef2aSThomas Huth return; 3715*fcf5ef2aSThomas Huth } 3716*fcf5ef2aSThomas Huth t0 = tcg_const_tl(SIMM(ctx->opcode)); 3717*fcf5ef2aSThomas Huth t1 = tcg_const_i32(TO(ctx->opcode)); 3718*fcf5ef2aSThomas Huth gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1); 3719*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3720*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 3721*fcf5ef2aSThomas Huth } 3722*fcf5ef2aSThomas Huth #endif 3723*fcf5ef2aSThomas Huth 3724*fcf5ef2aSThomas Huth /*** Processor control ***/ 3725*fcf5ef2aSThomas Huth 3726*fcf5ef2aSThomas Huth static void gen_read_xer(TCGv dst) 3727*fcf5ef2aSThomas Huth { 3728*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 3729*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 3730*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 3731*fcf5ef2aSThomas Huth tcg_gen_mov_tl(dst, cpu_xer); 3732*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_so, XER_SO); 3733*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t1, cpu_ov, XER_OV); 3734*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t2, cpu_ca, XER_CA); 3735*fcf5ef2aSThomas Huth tcg_gen_or_tl(t0, t0, t1); 3736*fcf5ef2aSThomas Huth tcg_gen_or_tl(dst, dst, t2); 3737*fcf5ef2aSThomas Huth tcg_gen_or_tl(dst, dst, t0); 3738*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3739*fcf5ef2aSThomas Huth tcg_temp_free(t1); 3740*fcf5ef2aSThomas Huth tcg_temp_free(t2); 3741*fcf5ef2aSThomas Huth } 3742*fcf5ef2aSThomas Huth 3743*fcf5ef2aSThomas Huth static void gen_write_xer(TCGv src) 3744*fcf5ef2aSThomas Huth { 3745*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_xer, src, 3746*fcf5ef2aSThomas Huth ~((1u << XER_SO) | (1u << XER_OV) | (1u << XER_CA))); 3747*fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_so, src, XER_SO); 3748*fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_ov, src, XER_OV); 3749*fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_ca, src, XER_CA); 3750*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_so, cpu_so, 1); 3751*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_ov, cpu_ov, 1); 3752*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_ca, cpu_ca, 1); 3753*fcf5ef2aSThomas Huth } 3754*fcf5ef2aSThomas Huth 3755*fcf5ef2aSThomas Huth /* mcrxr */ 3756*fcf5ef2aSThomas Huth static void gen_mcrxr(DisasContext *ctx) 3757*fcf5ef2aSThomas Huth { 3758*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 3759*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_temp_new_i32(); 3760*fcf5ef2aSThomas Huth TCGv_i32 dst = cpu_crf[crfD(ctx->opcode)]; 3761*fcf5ef2aSThomas Huth 3762*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t0, cpu_so); 3763*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(t1, cpu_ov); 3764*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(dst, cpu_ca); 3765*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 3); 3766*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t1, t1, 2); 3767*fcf5ef2aSThomas Huth tcg_gen_shli_i32(dst, dst, 1); 3768*fcf5ef2aSThomas Huth tcg_gen_or_i32(dst, dst, t0); 3769*fcf5ef2aSThomas Huth tcg_gen_or_i32(dst, dst, t1); 3770*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 3771*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 3772*fcf5ef2aSThomas Huth 3773*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_so, 0); 3774*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 0); 3775*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 0); 3776*fcf5ef2aSThomas Huth } 3777*fcf5ef2aSThomas Huth 3778*fcf5ef2aSThomas Huth /* mfcr mfocrf */ 3779*fcf5ef2aSThomas Huth static void gen_mfcr(DisasContext *ctx) 3780*fcf5ef2aSThomas Huth { 3781*fcf5ef2aSThomas Huth uint32_t crm, crn; 3782*fcf5ef2aSThomas Huth 3783*fcf5ef2aSThomas Huth if (likely(ctx->opcode & 0x00100000)) { 3784*fcf5ef2aSThomas Huth crm = CRM(ctx->opcode); 3785*fcf5ef2aSThomas Huth if (likely(crm && ((crm & (crm - 1)) == 0))) { 3786*fcf5ef2aSThomas Huth crn = ctz32 (crm); 3787*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]); 3788*fcf5ef2aSThomas Huth tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], 3789*fcf5ef2aSThomas Huth cpu_gpr[rD(ctx->opcode)], crn * 4); 3790*fcf5ef2aSThomas Huth } 3791*fcf5ef2aSThomas Huth } else { 3792*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 3793*fcf5ef2aSThomas Huth tcg_gen_mov_i32(t0, cpu_crf[0]); 3794*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3795*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[1]); 3796*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3797*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[2]); 3798*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3799*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[3]); 3800*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3801*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[4]); 3802*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3803*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[5]); 3804*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3805*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[6]); 3806*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, t0, 4); 3807*fcf5ef2aSThomas Huth tcg_gen_or_i32(t0, t0, cpu_crf[7]); 3808*fcf5ef2aSThomas Huth tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); 3809*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 3810*fcf5ef2aSThomas Huth } 3811*fcf5ef2aSThomas Huth } 3812*fcf5ef2aSThomas Huth 3813*fcf5ef2aSThomas Huth /* mfmsr */ 3814*fcf5ef2aSThomas Huth static void gen_mfmsr(DisasContext *ctx) 3815*fcf5ef2aSThomas Huth { 3816*fcf5ef2aSThomas Huth CHK_SV; 3817*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr); 3818*fcf5ef2aSThomas Huth } 3819*fcf5ef2aSThomas Huth 3820*fcf5ef2aSThomas Huth static void spr_noaccess(DisasContext *ctx, int gprn, int sprn) 3821*fcf5ef2aSThomas Huth { 3822*fcf5ef2aSThomas Huth #if 0 3823*fcf5ef2aSThomas Huth sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5); 3824*fcf5ef2aSThomas Huth printf("ERROR: try to access SPR %d !\n", sprn); 3825*fcf5ef2aSThomas Huth #endif 3826*fcf5ef2aSThomas Huth } 3827*fcf5ef2aSThomas Huth #define SPR_NOACCESS (&spr_noaccess) 3828*fcf5ef2aSThomas Huth 3829*fcf5ef2aSThomas Huth /* mfspr */ 3830*fcf5ef2aSThomas Huth static inline void gen_op_mfspr(DisasContext *ctx) 3831*fcf5ef2aSThomas Huth { 3832*fcf5ef2aSThomas Huth void (*read_cb)(DisasContext *ctx, int gprn, int sprn); 3833*fcf5ef2aSThomas Huth uint32_t sprn = SPR(ctx->opcode); 3834*fcf5ef2aSThomas Huth 3835*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 3836*fcf5ef2aSThomas Huth read_cb = ctx->spr_cb[sprn].uea_read; 3837*fcf5ef2aSThomas Huth #else 3838*fcf5ef2aSThomas Huth if (ctx->pr) { 3839*fcf5ef2aSThomas Huth read_cb = ctx->spr_cb[sprn].uea_read; 3840*fcf5ef2aSThomas Huth } else if (ctx->hv) { 3841*fcf5ef2aSThomas Huth read_cb = ctx->spr_cb[sprn].hea_read; 3842*fcf5ef2aSThomas Huth } else { 3843*fcf5ef2aSThomas Huth read_cb = ctx->spr_cb[sprn].oea_read; 3844*fcf5ef2aSThomas Huth } 3845*fcf5ef2aSThomas Huth #endif 3846*fcf5ef2aSThomas Huth if (likely(read_cb != NULL)) { 3847*fcf5ef2aSThomas Huth if (likely(read_cb != SPR_NOACCESS)) { 3848*fcf5ef2aSThomas Huth (*read_cb)(ctx, rD(ctx->opcode), sprn); 3849*fcf5ef2aSThomas Huth } else { 3850*fcf5ef2aSThomas Huth /* Privilege exception */ 3851*fcf5ef2aSThomas Huth /* This is a hack to avoid warnings when running Linux: 3852*fcf5ef2aSThomas Huth * this OS breaks the PowerPC virtualisation model, 3853*fcf5ef2aSThomas Huth * allowing userland application to read the PVR 3854*fcf5ef2aSThomas Huth */ 3855*fcf5ef2aSThomas Huth if (sprn != SPR_PVR) { 3856*fcf5ef2aSThomas Huth fprintf(stderr, "Trying to read privileged spr %d (0x%03x) at " 3857*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 3858*fcf5ef2aSThomas Huth if (qemu_log_separate()) { 3859*fcf5ef2aSThomas Huth qemu_log("Trying to read privileged spr %d (0x%03x) at " 3860*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 3861*fcf5ef2aSThomas Huth } 3862*fcf5ef2aSThomas Huth } 3863*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG); 3864*fcf5ef2aSThomas Huth } 3865*fcf5ef2aSThomas Huth } else { 3866*fcf5ef2aSThomas Huth /* ISA 2.07 defines these as no-ops */ 3867*fcf5ef2aSThomas Huth if ((ctx->insns_flags2 & PPC2_ISA207S) && 3868*fcf5ef2aSThomas Huth (sprn >= 808 && sprn <= 811)) { 3869*fcf5ef2aSThomas Huth /* This is a nop */ 3870*fcf5ef2aSThomas Huth return; 3871*fcf5ef2aSThomas Huth } 3872*fcf5ef2aSThomas Huth /* Not defined */ 3873*fcf5ef2aSThomas Huth fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at " 3874*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 3875*fcf5ef2aSThomas Huth if (qemu_log_separate()) { 3876*fcf5ef2aSThomas Huth qemu_log("Trying to read invalid spr %d (0x%03x) at " 3877*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 3878*fcf5ef2aSThomas Huth } 3879*fcf5ef2aSThomas Huth 3880*fcf5ef2aSThomas Huth /* The behaviour depends on MSR:PR and SPR# bit 0x10, 3881*fcf5ef2aSThomas Huth * it can generate a priv, a hv emu or a no-op 3882*fcf5ef2aSThomas Huth */ 3883*fcf5ef2aSThomas Huth if (sprn & 0x10) { 3884*fcf5ef2aSThomas Huth if (ctx->pr) { 3885*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR); 3886*fcf5ef2aSThomas Huth } 3887*fcf5ef2aSThomas Huth } else { 3888*fcf5ef2aSThomas Huth if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 || sprn == 6) { 3889*fcf5ef2aSThomas Huth gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR); 3890*fcf5ef2aSThomas Huth } 3891*fcf5ef2aSThomas Huth } 3892*fcf5ef2aSThomas Huth } 3893*fcf5ef2aSThomas Huth } 3894*fcf5ef2aSThomas Huth 3895*fcf5ef2aSThomas Huth static void gen_mfspr(DisasContext *ctx) 3896*fcf5ef2aSThomas Huth { 3897*fcf5ef2aSThomas Huth gen_op_mfspr(ctx); 3898*fcf5ef2aSThomas Huth } 3899*fcf5ef2aSThomas Huth 3900*fcf5ef2aSThomas Huth /* mftb */ 3901*fcf5ef2aSThomas Huth static void gen_mftb(DisasContext *ctx) 3902*fcf5ef2aSThomas Huth { 3903*fcf5ef2aSThomas Huth gen_op_mfspr(ctx); 3904*fcf5ef2aSThomas Huth } 3905*fcf5ef2aSThomas Huth 3906*fcf5ef2aSThomas Huth /* mtcrf mtocrf*/ 3907*fcf5ef2aSThomas Huth static void gen_mtcrf(DisasContext *ctx) 3908*fcf5ef2aSThomas Huth { 3909*fcf5ef2aSThomas Huth uint32_t crm, crn; 3910*fcf5ef2aSThomas Huth 3911*fcf5ef2aSThomas Huth crm = CRM(ctx->opcode); 3912*fcf5ef2aSThomas Huth if (likely((ctx->opcode & 0x00100000))) { 3913*fcf5ef2aSThomas Huth if (crm && ((crm & (crm - 1)) == 0)) { 3914*fcf5ef2aSThomas Huth TCGv_i32 temp = tcg_temp_new_i32(); 3915*fcf5ef2aSThomas Huth crn = ctz32 (crm); 3916*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]); 3917*fcf5ef2aSThomas Huth tcg_gen_shri_i32(temp, temp, crn * 4); 3918*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf); 3919*fcf5ef2aSThomas Huth tcg_temp_free_i32(temp); 3920*fcf5ef2aSThomas Huth } 3921*fcf5ef2aSThomas Huth } else { 3922*fcf5ef2aSThomas Huth TCGv_i32 temp = tcg_temp_new_i32(); 3923*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]); 3924*fcf5ef2aSThomas Huth for (crn = 0 ; crn < 8 ; crn++) { 3925*fcf5ef2aSThomas Huth if (crm & (1 << crn)) { 3926*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4); 3927*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf); 3928*fcf5ef2aSThomas Huth } 3929*fcf5ef2aSThomas Huth } 3930*fcf5ef2aSThomas Huth tcg_temp_free_i32(temp); 3931*fcf5ef2aSThomas Huth } 3932*fcf5ef2aSThomas Huth } 3933*fcf5ef2aSThomas Huth 3934*fcf5ef2aSThomas Huth /* mtmsr */ 3935*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3936*fcf5ef2aSThomas Huth static void gen_mtmsrd(DisasContext *ctx) 3937*fcf5ef2aSThomas Huth { 3938*fcf5ef2aSThomas Huth CHK_SV; 3939*fcf5ef2aSThomas Huth 3940*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 3941*fcf5ef2aSThomas Huth if (ctx->opcode & 0x00010000) { 3942*fcf5ef2aSThomas Huth /* Special form that does not need any synchronisation */ 3943*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 3944*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE)); 3945*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE))); 3946*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_msr, cpu_msr, t0); 3947*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3948*fcf5ef2aSThomas Huth } else { 3949*fcf5ef2aSThomas Huth /* XXX: we need to update nip before the store 3950*fcf5ef2aSThomas Huth * if we enter power saving mode, we will exit the loop 3951*fcf5ef2aSThomas Huth * directly from ppc_store_msr 3952*fcf5ef2aSThomas Huth */ 3953*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip); 3954*fcf5ef2aSThomas Huth gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]); 3955*fcf5ef2aSThomas Huth /* Must stop the translation as machine state (may have) changed */ 3956*fcf5ef2aSThomas Huth /* Note that mtmsr is not always defined as context-synchronizing */ 3957*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3958*fcf5ef2aSThomas Huth } 3959*fcf5ef2aSThomas Huth #endif /* !defined(CONFIG_USER_ONLY) */ 3960*fcf5ef2aSThomas Huth } 3961*fcf5ef2aSThomas Huth #endif /* defined(TARGET_PPC64) */ 3962*fcf5ef2aSThomas Huth 3963*fcf5ef2aSThomas Huth static void gen_mtmsr(DisasContext *ctx) 3964*fcf5ef2aSThomas Huth { 3965*fcf5ef2aSThomas Huth CHK_SV; 3966*fcf5ef2aSThomas Huth 3967*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 3968*fcf5ef2aSThomas Huth if (ctx->opcode & 0x00010000) { 3969*fcf5ef2aSThomas Huth /* Special form that does not need any synchronisation */ 3970*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 3971*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE)); 3972*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE))); 3973*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_msr, cpu_msr, t0); 3974*fcf5ef2aSThomas Huth tcg_temp_free(t0); 3975*fcf5ef2aSThomas Huth } else { 3976*fcf5ef2aSThomas Huth TCGv msr = tcg_temp_new(); 3977*fcf5ef2aSThomas Huth 3978*fcf5ef2aSThomas Huth /* XXX: we need to update nip before the store 3979*fcf5ef2aSThomas Huth * if we enter power saving mode, we will exit the loop 3980*fcf5ef2aSThomas Huth * directly from ppc_store_msr 3981*fcf5ef2aSThomas Huth */ 3982*fcf5ef2aSThomas Huth gen_update_nip(ctx, ctx->nip); 3983*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 3984*fcf5ef2aSThomas Huth tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32); 3985*fcf5ef2aSThomas Huth #else 3986*fcf5ef2aSThomas Huth tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]); 3987*fcf5ef2aSThomas Huth #endif 3988*fcf5ef2aSThomas Huth gen_helper_store_msr(cpu_env, msr); 3989*fcf5ef2aSThomas Huth tcg_temp_free(msr); 3990*fcf5ef2aSThomas Huth /* Must stop the translation as machine state (may have) changed */ 3991*fcf5ef2aSThomas Huth /* Note that mtmsr is not always defined as context-synchronizing */ 3992*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 3993*fcf5ef2aSThomas Huth } 3994*fcf5ef2aSThomas Huth #endif 3995*fcf5ef2aSThomas Huth } 3996*fcf5ef2aSThomas Huth 3997*fcf5ef2aSThomas Huth /* mtspr */ 3998*fcf5ef2aSThomas Huth static void gen_mtspr(DisasContext *ctx) 3999*fcf5ef2aSThomas Huth { 4000*fcf5ef2aSThomas Huth void (*write_cb)(DisasContext *ctx, int sprn, int gprn); 4001*fcf5ef2aSThomas Huth uint32_t sprn = SPR(ctx->opcode); 4002*fcf5ef2aSThomas Huth 4003*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4004*fcf5ef2aSThomas Huth write_cb = ctx->spr_cb[sprn].uea_write; 4005*fcf5ef2aSThomas Huth #else 4006*fcf5ef2aSThomas Huth if (ctx->pr) { 4007*fcf5ef2aSThomas Huth write_cb = ctx->spr_cb[sprn].uea_write; 4008*fcf5ef2aSThomas Huth } else if (ctx->hv) { 4009*fcf5ef2aSThomas Huth write_cb = ctx->spr_cb[sprn].hea_write; 4010*fcf5ef2aSThomas Huth } else { 4011*fcf5ef2aSThomas Huth write_cb = ctx->spr_cb[sprn].oea_write; 4012*fcf5ef2aSThomas Huth } 4013*fcf5ef2aSThomas Huth #endif 4014*fcf5ef2aSThomas Huth if (likely(write_cb != NULL)) { 4015*fcf5ef2aSThomas Huth if (likely(write_cb != SPR_NOACCESS)) { 4016*fcf5ef2aSThomas Huth (*write_cb)(ctx, sprn, rS(ctx->opcode)); 4017*fcf5ef2aSThomas Huth } else { 4018*fcf5ef2aSThomas Huth /* Privilege exception */ 4019*fcf5ef2aSThomas Huth fprintf(stderr, "Trying to write privileged spr %d (0x%03x) at " 4020*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 4021*fcf5ef2aSThomas Huth if (qemu_log_separate()) { 4022*fcf5ef2aSThomas Huth qemu_log("Trying to write privileged spr %d (0x%03x) at " 4023*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 4024*fcf5ef2aSThomas Huth } 4025*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG); 4026*fcf5ef2aSThomas Huth } 4027*fcf5ef2aSThomas Huth } else { 4028*fcf5ef2aSThomas Huth /* ISA 2.07 defines these as no-ops */ 4029*fcf5ef2aSThomas Huth if ((ctx->insns_flags2 & PPC2_ISA207S) && 4030*fcf5ef2aSThomas Huth (sprn >= 808 && sprn <= 811)) { 4031*fcf5ef2aSThomas Huth /* This is a nop */ 4032*fcf5ef2aSThomas Huth return; 4033*fcf5ef2aSThomas Huth } 4034*fcf5ef2aSThomas Huth 4035*fcf5ef2aSThomas Huth /* Not defined */ 4036*fcf5ef2aSThomas Huth if (qemu_log_separate()) { 4037*fcf5ef2aSThomas Huth qemu_log("Trying to write invalid spr %d (0x%03x) at " 4038*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 4039*fcf5ef2aSThomas Huth } 4040*fcf5ef2aSThomas Huth fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at " 4041*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4); 4042*fcf5ef2aSThomas Huth 4043*fcf5ef2aSThomas Huth 4044*fcf5ef2aSThomas Huth /* The behaviour depends on MSR:PR and SPR# bit 0x10, 4045*fcf5ef2aSThomas Huth * it can generate a priv, a hv emu or a no-op 4046*fcf5ef2aSThomas Huth */ 4047*fcf5ef2aSThomas Huth if (sprn & 0x10) { 4048*fcf5ef2aSThomas Huth if (ctx->pr) { 4049*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR); 4050*fcf5ef2aSThomas Huth } 4051*fcf5ef2aSThomas Huth } else { 4052*fcf5ef2aSThomas Huth if (ctx->pr || sprn == 0) { 4053*fcf5ef2aSThomas Huth gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR); 4054*fcf5ef2aSThomas Huth } 4055*fcf5ef2aSThomas Huth } 4056*fcf5ef2aSThomas Huth } 4057*fcf5ef2aSThomas Huth } 4058*fcf5ef2aSThomas Huth 4059*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 4060*fcf5ef2aSThomas Huth /* setb */ 4061*fcf5ef2aSThomas Huth static void gen_setb(DisasContext *ctx) 4062*fcf5ef2aSThomas Huth { 4063*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_temp_new_i32(); 4064*fcf5ef2aSThomas Huth TCGv_i32 t8 = tcg_temp_new_i32(); 4065*fcf5ef2aSThomas Huth TCGv_i32 tm1 = tcg_temp_new_i32(); 4066*fcf5ef2aSThomas Huth int crf = crfS(ctx->opcode); 4067*fcf5ef2aSThomas Huth 4068*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_GEU, t0, cpu_crf[crf], 4); 4069*fcf5ef2aSThomas Huth tcg_gen_movi_i32(t8, 8); 4070*fcf5ef2aSThomas Huth tcg_gen_movi_i32(tm1, -1); 4071*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_GEU, t0, cpu_crf[crf], t8, tm1, t0); 4072*fcf5ef2aSThomas Huth tcg_gen_ext_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); 4073*fcf5ef2aSThomas Huth 4074*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 4075*fcf5ef2aSThomas Huth tcg_temp_free_i32(t8); 4076*fcf5ef2aSThomas Huth tcg_temp_free_i32(tm1); 4077*fcf5ef2aSThomas Huth } 4078*fcf5ef2aSThomas Huth #endif 4079*fcf5ef2aSThomas Huth 4080*fcf5ef2aSThomas Huth /*** Cache management ***/ 4081*fcf5ef2aSThomas Huth 4082*fcf5ef2aSThomas Huth /* dcbf */ 4083*fcf5ef2aSThomas Huth static void gen_dcbf(DisasContext *ctx) 4084*fcf5ef2aSThomas Huth { 4085*fcf5ef2aSThomas Huth /* XXX: specification says this is treated as a load by the MMU */ 4086*fcf5ef2aSThomas Huth TCGv t0; 4087*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_CACHE); 4088*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4089*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 4090*fcf5ef2aSThomas Huth gen_qemu_ld8u(ctx, t0, t0); 4091*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4092*fcf5ef2aSThomas Huth } 4093*fcf5ef2aSThomas Huth 4094*fcf5ef2aSThomas Huth /* dcbi (Supervisor only) */ 4095*fcf5ef2aSThomas Huth static void gen_dcbi(DisasContext *ctx) 4096*fcf5ef2aSThomas Huth { 4097*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4098*fcf5ef2aSThomas Huth GEN_PRIV; 4099*fcf5ef2aSThomas Huth #else 4100*fcf5ef2aSThomas Huth TCGv EA, val; 4101*fcf5ef2aSThomas Huth 4102*fcf5ef2aSThomas Huth CHK_SV; 4103*fcf5ef2aSThomas Huth EA = tcg_temp_new(); 4104*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_CACHE); 4105*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); 4106*fcf5ef2aSThomas Huth val = tcg_temp_new(); 4107*fcf5ef2aSThomas Huth /* XXX: specification says this should be treated as a store by the MMU */ 4108*fcf5ef2aSThomas Huth gen_qemu_ld8u(ctx, val, EA); 4109*fcf5ef2aSThomas Huth gen_qemu_st8(ctx, val, EA); 4110*fcf5ef2aSThomas Huth tcg_temp_free(val); 4111*fcf5ef2aSThomas Huth tcg_temp_free(EA); 4112*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4113*fcf5ef2aSThomas Huth } 4114*fcf5ef2aSThomas Huth 4115*fcf5ef2aSThomas Huth /* dcdst */ 4116*fcf5ef2aSThomas Huth static void gen_dcbst(DisasContext *ctx) 4117*fcf5ef2aSThomas Huth { 4118*fcf5ef2aSThomas Huth /* XXX: specification say this is treated as a load by the MMU */ 4119*fcf5ef2aSThomas Huth TCGv t0; 4120*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_CACHE); 4121*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4122*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 4123*fcf5ef2aSThomas Huth gen_qemu_ld8u(ctx, t0, t0); 4124*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4125*fcf5ef2aSThomas Huth } 4126*fcf5ef2aSThomas Huth 4127*fcf5ef2aSThomas Huth /* dcbt */ 4128*fcf5ef2aSThomas Huth static void gen_dcbt(DisasContext *ctx) 4129*fcf5ef2aSThomas Huth { 4130*fcf5ef2aSThomas Huth /* interpreted as no-op */ 4131*fcf5ef2aSThomas Huth /* XXX: specification say this is treated as a load by the MMU 4132*fcf5ef2aSThomas Huth * but does not generate any exception 4133*fcf5ef2aSThomas Huth */ 4134*fcf5ef2aSThomas Huth } 4135*fcf5ef2aSThomas Huth 4136*fcf5ef2aSThomas Huth /* dcbtst */ 4137*fcf5ef2aSThomas Huth static void gen_dcbtst(DisasContext *ctx) 4138*fcf5ef2aSThomas Huth { 4139*fcf5ef2aSThomas Huth /* interpreted as no-op */ 4140*fcf5ef2aSThomas Huth /* XXX: specification say this is treated as a load by the MMU 4141*fcf5ef2aSThomas Huth * but does not generate any exception 4142*fcf5ef2aSThomas Huth */ 4143*fcf5ef2aSThomas Huth } 4144*fcf5ef2aSThomas Huth 4145*fcf5ef2aSThomas Huth /* dcbtls */ 4146*fcf5ef2aSThomas Huth static void gen_dcbtls(DisasContext *ctx) 4147*fcf5ef2aSThomas Huth { 4148*fcf5ef2aSThomas Huth /* Always fails locking the cache */ 4149*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4150*fcf5ef2aSThomas Huth gen_load_spr(t0, SPR_Exxx_L1CSR0); 4151*fcf5ef2aSThomas Huth tcg_gen_ori_tl(t0, t0, L1CSR0_CUL); 4152*fcf5ef2aSThomas Huth gen_store_spr(SPR_Exxx_L1CSR0, t0); 4153*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4154*fcf5ef2aSThomas Huth } 4155*fcf5ef2aSThomas Huth 4156*fcf5ef2aSThomas Huth /* dcbz */ 4157*fcf5ef2aSThomas Huth static void gen_dcbz(DisasContext *ctx) 4158*fcf5ef2aSThomas Huth { 4159*fcf5ef2aSThomas Huth TCGv tcgv_addr; 4160*fcf5ef2aSThomas Huth TCGv_i32 tcgv_op; 4161*fcf5ef2aSThomas Huth 4162*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_CACHE); 4163*fcf5ef2aSThomas Huth tcgv_addr = tcg_temp_new(); 4164*fcf5ef2aSThomas Huth tcgv_op = tcg_const_i32(ctx->opcode & 0x03FF000); 4165*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, tcgv_addr); 4166*fcf5ef2aSThomas Huth gen_helper_dcbz(cpu_env, tcgv_addr, tcgv_op); 4167*fcf5ef2aSThomas Huth tcg_temp_free(tcgv_addr); 4168*fcf5ef2aSThomas Huth tcg_temp_free_i32(tcgv_op); 4169*fcf5ef2aSThomas Huth } 4170*fcf5ef2aSThomas Huth 4171*fcf5ef2aSThomas Huth /* dst / dstt */ 4172*fcf5ef2aSThomas Huth static void gen_dst(DisasContext *ctx) 4173*fcf5ef2aSThomas Huth { 4174*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 4175*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 4176*fcf5ef2aSThomas Huth } else { 4177*fcf5ef2aSThomas Huth /* interpreted as no-op */ 4178*fcf5ef2aSThomas Huth } 4179*fcf5ef2aSThomas Huth } 4180*fcf5ef2aSThomas Huth 4181*fcf5ef2aSThomas Huth /* dstst /dststt */ 4182*fcf5ef2aSThomas Huth static void gen_dstst(DisasContext *ctx) 4183*fcf5ef2aSThomas Huth { 4184*fcf5ef2aSThomas Huth if (rA(ctx->opcode) == 0) { 4185*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 4186*fcf5ef2aSThomas Huth } else { 4187*fcf5ef2aSThomas Huth /* interpreted as no-op */ 4188*fcf5ef2aSThomas Huth } 4189*fcf5ef2aSThomas Huth 4190*fcf5ef2aSThomas Huth } 4191*fcf5ef2aSThomas Huth 4192*fcf5ef2aSThomas Huth /* dss / dssall */ 4193*fcf5ef2aSThomas Huth static void gen_dss(DisasContext *ctx) 4194*fcf5ef2aSThomas Huth { 4195*fcf5ef2aSThomas Huth /* interpreted as no-op */ 4196*fcf5ef2aSThomas Huth } 4197*fcf5ef2aSThomas Huth 4198*fcf5ef2aSThomas Huth /* icbi */ 4199*fcf5ef2aSThomas Huth static void gen_icbi(DisasContext *ctx) 4200*fcf5ef2aSThomas Huth { 4201*fcf5ef2aSThomas Huth TCGv t0; 4202*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_CACHE); 4203*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4204*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 4205*fcf5ef2aSThomas Huth gen_helper_icbi(cpu_env, t0); 4206*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4207*fcf5ef2aSThomas Huth } 4208*fcf5ef2aSThomas Huth 4209*fcf5ef2aSThomas Huth /* Optional: */ 4210*fcf5ef2aSThomas Huth /* dcba */ 4211*fcf5ef2aSThomas Huth static void gen_dcba(DisasContext *ctx) 4212*fcf5ef2aSThomas Huth { 4213*fcf5ef2aSThomas Huth /* interpreted as no-op */ 4214*fcf5ef2aSThomas Huth /* XXX: specification say this is treated as a store by the MMU 4215*fcf5ef2aSThomas Huth * but does not generate any exception 4216*fcf5ef2aSThomas Huth */ 4217*fcf5ef2aSThomas Huth } 4218*fcf5ef2aSThomas Huth 4219*fcf5ef2aSThomas Huth /*** Segment register manipulation ***/ 4220*fcf5ef2aSThomas Huth /* Supervisor only: */ 4221*fcf5ef2aSThomas Huth 4222*fcf5ef2aSThomas Huth /* mfsr */ 4223*fcf5ef2aSThomas Huth static void gen_mfsr(DisasContext *ctx) 4224*fcf5ef2aSThomas Huth { 4225*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4226*fcf5ef2aSThomas Huth GEN_PRIV; 4227*fcf5ef2aSThomas Huth #else 4228*fcf5ef2aSThomas Huth TCGv t0; 4229*fcf5ef2aSThomas Huth 4230*fcf5ef2aSThomas Huth CHK_SV; 4231*fcf5ef2aSThomas Huth t0 = tcg_const_tl(SR(ctx->opcode)); 4232*fcf5ef2aSThomas Huth gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 4233*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4234*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4235*fcf5ef2aSThomas Huth } 4236*fcf5ef2aSThomas Huth 4237*fcf5ef2aSThomas Huth /* mfsrin */ 4238*fcf5ef2aSThomas Huth static void gen_mfsrin(DisasContext *ctx) 4239*fcf5ef2aSThomas Huth { 4240*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4241*fcf5ef2aSThomas Huth GEN_PRIV; 4242*fcf5ef2aSThomas Huth #else 4243*fcf5ef2aSThomas Huth TCGv t0; 4244*fcf5ef2aSThomas Huth 4245*fcf5ef2aSThomas Huth CHK_SV; 4246*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4247*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); 4248*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, 0xF); 4249*fcf5ef2aSThomas Huth gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 4250*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4251*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4252*fcf5ef2aSThomas Huth } 4253*fcf5ef2aSThomas Huth 4254*fcf5ef2aSThomas Huth /* mtsr */ 4255*fcf5ef2aSThomas Huth static void gen_mtsr(DisasContext *ctx) 4256*fcf5ef2aSThomas Huth { 4257*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4258*fcf5ef2aSThomas Huth GEN_PRIV; 4259*fcf5ef2aSThomas Huth #else 4260*fcf5ef2aSThomas Huth TCGv t0; 4261*fcf5ef2aSThomas Huth 4262*fcf5ef2aSThomas Huth CHK_SV; 4263*fcf5ef2aSThomas Huth t0 = tcg_const_tl(SR(ctx->opcode)); 4264*fcf5ef2aSThomas Huth gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]); 4265*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4266*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4267*fcf5ef2aSThomas Huth } 4268*fcf5ef2aSThomas Huth 4269*fcf5ef2aSThomas Huth /* mtsrin */ 4270*fcf5ef2aSThomas Huth static void gen_mtsrin(DisasContext *ctx) 4271*fcf5ef2aSThomas Huth { 4272*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4273*fcf5ef2aSThomas Huth GEN_PRIV; 4274*fcf5ef2aSThomas Huth #else 4275*fcf5ef2aSThomas Huth TCGv t0; 4276*fcf5ef2aSThomas Huth CHK_SV; 4277*fcf5ef2aSThomas Huth 4278*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4279*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); 4280*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, 0xF); 4281*fcf5ef2aSThomas Huth gen_helper_store_sr(cpu_env, t0, cpu_gpr[rD(ctx->opcode)]); 4282*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4283*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4284*fcf5ef2aSThomas Huth } 4285*fcf5ef2aSThomas Huth 4286*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 4287*fcf5ef2aSThomas Huth /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */ 4288*fcf5ef2aSThomas Huth 4289*fcf5ef2aSThomas Huth /* mfsr */ 4290*fcf5ef2aSThomas Huth static void gen_mfsr_64b(DisasContext *ctx) 4291*fcf5ef2aSThomas Huth { 4292*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4293*fcf5ef2aSThomas Huth GEN_PRIV; 4294*fcf5ef2aSThomas Huth #else 4295*fcf5ef2aSThomas Huth TCGv t0; 4296*fcf5ef2aSThomas Huth 4297*fcf5ef2aSThomas Huth CHK_SV; 4298*fcf5ef2aSThomas Huth t0 = tcg_const_tl(SR(ctx->opcode)); 4299*fcf5ef2aSThomas Huth gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 4300*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4301*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4302*fcf5ef2aSThomas Huth } 4303*fcf5ef2aSThomas Huth 4304*fcf5ef2aSThomas Huth /* mfsrin */ 4305*fcf5ef2aSThomas Huth static void gen_mfsrin_64b(DisasContext *ctx) 4306*fcf5ef2aSThomas Huth { 4307*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4308*fcf5ef2aSThomas Huth GEN_PRIV; 4309*fcf5ef2aSThomas Huth #else 4310*fcf5ef2aSThomas Huth TCGv t0; 4311*fcf5ef2aSThomas Huth 4312*fcf5ef2aSThomas Huth CHK_SV; 4313*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4314*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); 4315*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, 0xF); 4316*fcf5ef2aSThomas Huth gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 4317*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4318*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4319*fcf5ef2aSThomas Huth } 4320*fcf5ef2aSThomas Huth 4321*fcf5ef2aSThomas Huth /* mtsr */ 4322*fcf5ef2aSThomas Huth static void gen_mtsr_64b(DisasContext *ctx) 4323*fcf5ef2aSThomas Huth { 4324*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4325*fcf5ef2aSThomas Huth GEN_PRIV; 4326*fcf5ef2aSThomas Huth #else 4327*fcf5ef2aSThomas Huth TCGv t0; 4328*fcf5ef2aSThomas Huth 4329*fcf5ef2aSThomas Huth CHK_SV; 4330*fcf5ef2aSThomas Huth t0 = tcg_const_tl(SR(ctx->opcode)); 4331*fcf5ef2aSThomas Huth gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]); 4332*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4333*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4334*fcf5ef2aSThomas Huth } 4335*fcf5ef2aSThomas Huth 4336*fcf5ef2aSThomas Huth /* mtsrin */ 4337*fcf5ef2aSThomas Huth static void gen_mtsrin_64b(DisasContext *ctx) 4338*fcf5ef2aSThomas Huth { 4339*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4340*fcf5ef2aSThomas Huth GEN_PRIV; 4341*fcf5ef2aSThomas Huth #else 4342*fcf5ef2aSThomas Huth TCGv t0; 4343*fcf5ef2aSThomas Huth 4344*fcf5ef2aSThomas Huth CHK_SV; 4345*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4346*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); 4347*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, 0xF); 4348*fcf5ef2aSThomas Huth gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]); 4349*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4350*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4351*fcf5ef2aSThomas Huth } 4352*fcf5ef2aSThomas Huth 4353*fcf5ef2aSThomas Huth /* slbmte */ 4354*fcf5ef2aSThomas Huth static void gen_slbmte(DisasContext *ctx) 4355*fcf5ef2aSThomas Huth { 4356*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4357*fcf5ef2aSThomas Huth GEN_PRIV; 4358*fcf5ef2aSThomas Huth #else 4359*fcf5ef2aSThomas Huth CHK_SV; 4360*fcf5ef2aSThomas Huth 4361*fcf5ef2aSThomas Huth gen_helper_store_slb(cpu_env, cpu_gpr[rB(ctx->opcode)], 4362*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)]); 4363*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4364*fcf5ef2aSThomas Huth } 4365*fcf5ef2aSThomas Huth 4366*fcf5ef2aSThomas Huth static void gen_slbmfee(DisasContext *ctx) 4367*fcf5ef2aSThomas Huth { 4368*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4369*fcf5ef2aSThomas Huth GEN_PRIV; 4370*fcf5ef2aSThomas Huth #else 4371*fcf5ef2aSThomas Huth CHK_SV; 4372*fcf5ef2aSThomas Huth 4373*fcf5ef2aSThomas Huth gen_helper_load_slb_esid(cpu_gpr[rS(ctx->opcode)], cpu_env, 4374*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 4375*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4376*fcf5ef2aSThomas Huth } 4377*fcf5ef2aSThomas Huth 4378*fcf5ef2aSThomas Huth static void gen_slbmfev(DisasContext *ctx) 4379*fcf5ef2aSThomas Huth { 4380*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4381*fcf5ef2aSThomas Huth GEN_PRIV; 4382*fcf5ef2aSThomas Huth #else 4383*fcf5ef2aSThomas Huth CHK_SV; 4384*fcf5ef2aSThomas Huth 4385*fcf5ef2aSThomas Huth gen_helper_load_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env, 4386*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 4387*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4388*fcf5ef2aSThomas Huth } 4389*fcf5ef2aSThomas Huth 4390*fcf5ef2aSThomas Huth static void gen_slbfee_(DisasContext *ctx) 4391*fcf5ef2aSThomas Huth { 4392*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4393*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); 4394*fcf5ef2aSThomas Huth #else 4395*fcf5ef2aSThomas Huth TCGLabel *l1, *l2; 4396*fcf5ef2aSThomas Huth 4397*fcf5ef2aSThomas Huth if (unlikely(ctx->pr)) { 4398*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); 4399*fcf5ef2aSThomas Huth return; 4400*fcf5ef2aSThomas Huth } 4401*fcf5ef2aSThomas Huth gen_helper_find_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env, 4402*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 4403*fcf5ef2aSThomas Huth l1 = gen_new_label(); 4404*fcf5ef2aSThomas Huth l2 = gen_new_label(); 4405*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); 4406*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1); 4407*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); 4408*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4409*fcf5ef2aSThomas Huth gen_set_label(l1); 4410*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0); 4411*fcf5ef2aSThomas Huth gen_set_label(l2); 4412*fcf5ef2aSThomas Huth #endif 4413*fcf5ef2aSThomas Huth } 4414*fcf5ef2aSThomas Huth #endif /* defined(TARGET_PPC64) */ 4415*fcf5ef2aSThomas Huth 4416*fcf5ef2aSThomas Huth /*** Lookaside buffer management ***/ 4417*fcf5ef2aSThomas Huth /* Optional & supervisor only: */ 4418*fcf5ef2aSThomas Huth 4419*fcf5ef2aSThomas Huth /* tlbia */ 4420*fcf5ef2aSThomas Huth static void gen_tlbia(DisasContext *ctx) 4421*fcf5ef2aSThomas Huth { 4422*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4423*fcf5ef2aSThomas Huth GEN_PRIV; 4424*fcf5ef2aSThomas Huth #else 4425*fcf5ef2aSThomas Huth CHK_HV; 4426*fcf5ef2aSThomas Huth 4427*fcf5ef2aSThomas Huth gen_helper_tlbia(cpu_env); 4428*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4429*fcf5ef2aSThomas Huth } 4430*fcf5ef2aSThomas Huth 4431*fcf5ef2aSThomas Huth /* tlbiel */ 4432*fcf5ef2aSThomas Huth static void gen_tlbiel(DisasContext *ctx) 4433*fcf5ef2aSThomas Huth { 4434*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4435*fcf5ef2aSThomas Huth GEN_PRIV; 4436*fcf5ef2aSThomas Huth #else 4437*fcf5ef2aSThomas Huth CHK_SV; 4438*fcf5ef2aSThomas Huth 4439*fcf5ef2aSThomas Huth gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); 4440*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4441*fcf5ef2aSThomas Huth } 4442*fcf5ef2aSThomas Huth 4443*fcf5ef2aSThomas Huth /* tlbie */ 4444*fcf5ef2aSThomas Huth static void gen_tlbie(DisasContext *ctx) 4445*fcf5ef2aSThomas Huth { 4446*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4447*fcf5ef2aSThomas Huth GEN_PRIV; 4448*fcf5ef2aSThomas Huth #else 4449*fcf5ef2aSThomas Huth TCGv_i32 t1; 4450*fcf5ef2aSThomas Huth CHK_HV; 4451*fcf5ef2aSThomas Huth 4452*fcf5ef2aSThomas Huth if (NARROW_MODE(ctx)) { 4453*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4454*fcf5ef2aSThomas Huth tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]); 4455*fcf5ef2aSThomas Huth gen_helper_tlbie(cpu_env, t0); 4456*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4457*fcf5ef2aSThomas Huth } else { 4458*fcf5ef2aSThomas Huth gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); 4459*fcf5ef2aSThomas Huth } 4460*fcf5ef2aSThomas Huth t1 = tcg_temp_new_i32(); 4461*fcf5ef2aSThomas Huth tcg_gen_ld_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush)); 4462*fcf5ef2aSThomas Huth tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH); 4463*fcf5ef2aSThomas Huth tcg_gen_st_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush)); 4464*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 4465*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4466*fcf5ef2aSThomas Huth } 4467*fcf5ef2aSThomas Huth 4468*fcf5ef2aSThomas Huth /* tlbsync */ 4469*fcf5ef2aSThomas Huth static void gen_tlbsync(DisasContext *ctx) 4470*fcf5ef2aSThomas Huth { 4471*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4472*fcf5ef2aSThomas Huth GEN_PRIV; 4473*fcf5ef2aSThomas Huth #else 4474*fcf5ef2aSThomas Huth CHK_HV; 4475*fcf5ef2aSThomas Huth 4476*fcf5ef2aSThomas Huth /* BookS does both ptesync and tlbsync make tlbsync a nop for server */ 4477*fcf5ef2aSThomas Huth if (ctx->insns_flags & PPC_BOOKE) { 4478*fcf5ef2aSThomas Huth gen_check_tlb_flush(ctx, true); 4479*fcf5ef2aSThomas Huth } 4480*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4481*fcf5ef2aSThomas Huth } 4482*fcf5ef2aSThomas Huth 4483*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 4484*fcf5ef2aSThomas Huth /* slbia */ 4485*fcf5ef2aSThomas Huth static void gen_slbia(DisasContext *ctx) 4486*fcf5ef2aSThomas Huth { 4487*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4488*fcf5ef2aSThomas Huth GEN_PRIV; 4489*fcf5ef2aSThomas Huth #else 4490*fcf5ef2aSThomas Huth CHK_SV; 4491*fcf5ef2aSThomas Huth 4492*fcf5ef2aSThomas Huth gen_helper_slbia(cpu_env); 4493*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4494*fcf5ef2aSThomas Huth } 4495*fcf5ef2aSThomas Huth 4496*fcf5ef2aSThomas Huth /* slbie */ 4497*fcf5ef2aSThomas Huth static void gen_slbie(DisasContext *ctx) 4498*fcf5ef2aSThomas Huth { 4499*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 4500*fcf5ef2aSThomas Huth GEN_PRIV; 4501*fcf5ef2aSThomas Huth #else 4502*fcf5ef2aSThomas Huth CHK_SV; 4503*fcf5ef2aSThomas Huth 4504*fcf5ef2aSThomas Huth gen_helper_slbie(cpu_env, cpu_gpr[rB(ctx->opcode)]); 4505*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 4506*fcf5ef2aSThomas Huth } 4507*fcf5ef2aSThomas Huth #endif /* defined(TARGET_PPC64) */ 4508*fcf5ef2aSThomas Huth 4509*fcf5ef2aSThomas Huth /*** External control ***/ 4510*fcf5ef2aSThomas Huth /* Optional: */ 4511*fcf5ef2aSThomas Huth 4512*fcf5ef2aSThomas Huth /* eciwx */ 4513*fcf5ef2aSThomas Huth static void gen_eciwx(DisasContext *ctx) 4514*fcf5ef2aSThomas Huth { 4515*fcf5ef2aSThomas Huth TCGv t0; 4516*fcf5ef2aSThomas Huth /* Should check EAR[E] ! */ 4517*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_EXT); 4518*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4519*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 4520*fcf5ef2aSThomas Huth gen_check_align(ctx, t0, 0x03); 4521*fcf5ef2aSThomas Huth gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], t0); 4522*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4523*fcf5ef2aSThomas Huth } 4524*fcf5ef2aSThomas Huth 4525*fcf5ef2aSThomas Huth /* ecowx */ 4526*fcf5ef2aSThomas Huth static void gen_ecowx(DisasContext *ctx) 4527*fcf5ef2aSThomas Huth { 4528*fcf5ef2aSThomas Huth TCGv t0; 4529*fcf5ef2aSThomas Huth /* Should check EAR[E] ! */ 4530*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_EXT); 4531*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 4532*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 4533*fcf5ef2aSThomas Huth gen_check_align(ctx, t0, 0x03); 4534*fcf5ef2aSThomas Huth gen_qemu_st32(ctx, cpu_gpr[rD(ctx->opcode)], t0); 4535*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4536*fcf5ef2aSThomas Huth } 4537*fcf5ef2aSThomas Huth 4538*fcf5ef2aSThomas Huth /* PowerPC 601 specific instructions */ 4539*fcf5ef2aSThomas Huth 4540*fcf5ef2aSThomas Huth /* abs - abs. */ 4541*fcf5ef2aSThomas Huth static void gen_abs(DisasContext *ctx) 4542*fcf5ef2aSThomas Huth { 4543*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4544*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4545*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1); 4546*fcf5ef2aSThomas Huth tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4547*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4548*fcf5ef2aSThomas Huth gen_set_label(l1); 4549*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4550*fcf5ef2aSThomas Huth gen_set_label(l2); 4551*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4552*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4553*fcf5ef2aSThomas Huth } 4554*fcf5ef2aSThomas Huth 4555*fcf5ef2aSThomas Huth /* abso - abso. */ 4556*fcf5ef2aSThomas Huth static void gen_abso(DisasContext *ctx) 4557*fcf5ef2aSThomas Huth { 4558*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4559*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4560*fcf5ef2aSThomas Huth TCGLabel *l3 = gen_new_label(); 4561*fcf5ef2aSThomas Huth /* Start with XER OV disabled, the most likely case */ 4562*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 0); 4563*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2); 4564*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1); 4565*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 1); 4566*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_so, 1); 4567*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4568*fcf5ef2aSThomas Huth gen_set_label(l1); 4569*fcf5ef2aSThomas Huth tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4570*fcf5ef2aSThomas Huth tcg_gen_br(l3); 4571*fcf5ef2aSThomas Huth gen_set_label(l2); 4572*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4573*fcf5ef2aSThomas Huth gen_set_label(l3); 4574*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4575*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4576*fcf5ef2aSThomas Huth } 4577*fcf5ef2aSThomas Huth 4578*fcf5ef2aSThomas Huth /* clcs */ 4579*fcf5ef2aSThomas Huth static void gen_clcs(DisasContext *ctx) 4580*fcf5ef2aSThomas Huth { 4581*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode)); 4582*fcf5ef2aSThomas Huth gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 4583*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 4584*fcf5ef2aSThomas Huth /* Rc=1 sets CR0 to an undefined state */ 4585*fcf5ef2aSThomas Huth } 4586*fcf5ef2aSThomas Huth 4587*fcf5ef2aSThomas Huth /* div - div. */ 4588*fcf5ef2aSThomas Huth static void gen_div(DisasContext *ctx) 4589*fcf5ef2aSThomas Huth { 4590*fcf5ef2aSThomas Huth gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)], 4591*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 4592*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4593*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4594*fcf5ef2aSThomas Huth } 4595*fcf5ef2aSThomas Huth 4596*fcf5ef2aSThomas Huth /* divo - divo. */ 4597*fcf5ef2aSThomas Huth static void gen_divo(DisasContext *ctx) 4598*fcf5ef2aSThomas Huth { 4599*fcf5ef2aSThomas Huth gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)], 4600*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 4601*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4602*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4603*fcf5ef2aSThomas Huth } 4604*fcf5ef2aSThomas Huth 4605*fcf5ef2aSThomas Huth /* divs - divs. */ 4606*fcf5ef2aSThomas Huth static void gen_divs(DisasContext *ctx) 4607*fcf5ef2aSThomas Huth { 4608*fcf5ef2aSThomas Huth gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)], 4609*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 4610*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4611*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4612*fcf5ef2aSThomas Huth } 4613*fcf5ef2aSThomas Huth 4614*fcf5ef2aSThomas Huth /* divso - divso. */ 4615*fcf5ef2aSThomas Huth static void gen_divso(DisasContext *ctx) 4616*fcf5ef2aSThomas Huth { 4617*fcf5ef2aSThomas Huth gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env, 4618*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 4619*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4620*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4621*fcf5ef2aSThomas Huth } 4622*fcf5ef2aSThomas Huth 4623*fcf5ef2aSThomas Huth /* doz - doz. */ 4624*fcf5ef2aSThomas Huth static void gen_doz(DisasContext *ctx) 4625*fcf5ef2aSThomas Huth { 4626*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4627*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4628*fcf5ef2aSThomas Huth tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1); 4629*fcf5ef2aSThomas Huth tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4630*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4631*fcf5ef2aSThomas Huth gen_set_label(l1); 4632*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0); 4633*fcf5ef2aSThomas Huth gen_set_label(l2); 4634*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4635*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4636*fcf5ef2aSThomas Huth } 4637*fcf5ef2aSThomas Huth 4638*fcf5ef2aSThomas Huth /* dozo - dozo. */ 4639*fcf5ef2aSThomas Huth static void gen_dozo(DisasContext *ctx) 4640*fcf5ef2aSThomas Huth { 4641*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4642*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4643*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4644*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4645*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 4646*fcf5ef2aSThomas Huth /* Start with XER OV disabled, the most likely case */ 4647*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 0); 4648*fcf5ef2aSThomas Huth tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1); 4649*fcf5ef2aSThomas Huth tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4650*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4651*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0); 4652*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t1, t1, t2); 4653*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0); 4654*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2); 4655*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 1); 4656*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_so, 1); 4657*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4658*fcf5ef2aSThomas Huth gen_set_label(l1); 4659*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0); 4660*fcf5ef2aSThomas Huth gen_set_label(l2); 4661*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4662*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4663*fcf5ef2aSThomas Huth tcg_temp_free(t2); 4664*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4665*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4666*fcf5ef2aSThomas Huth } 4667*fcf5ef2aSThomas Huth 4668*fcf5ef2aSThomas Huth /* dozi */ 4669*fcf5ef2aSThomas Huth static void gen_dozi(DisasContext *ctx) 4670*fcf5ef2aSThomas Huth { 4671*fcf5ef2aSThomas Huth target_long simm = SIMM(ctx->opcode); 4672*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4673*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4674*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1); 4675*fcf5ef2aSThomas Huth tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]); 4676*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4677*fcf5ef2aSThomas Huth gen_set_label(l1); 4678*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0); 4679*fcf5ef2aSThomas Huth gen_set_label(l2); 4680*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4681*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4682*fcf5ef2aSThomas Huth } 4683*fcf5ef2aSThomas Huth 4684*fcf5ef2aSThomas Huth /* lscbx - lscbx. */ 4685*fcf5ef2aSThomas Huth static void gen_lscbx(DisasContext *ctx) 4686*fcf5ef2aSThomas Huth { 4687*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4688*fcf5ef2aSThomas Huth TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode)); 4689*fcf5ef2aSThomas Huth TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode)); 4690*fcf5ef2aSThomas Huth TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode)); 4691*fcf5ef2aSThomas Huth 4692*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 4693*fcf5ef2aSThomas Huth gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3); 4694*fcf5ef2aSThomas Huth tcg_temp_free_i32(t1); 4695*fcf5ef2aSThomas Huth tcg_temp_free_i32(t2); 4696*fcf5ef2aSThomas Huth tcg_temp_free_i32(t3); 4697*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F); 4698*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_xer, cpu_xer, t0); 4699*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4700*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, t0); 4701*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4702*fcf5ef2aSThomas Huth } 4703*fcf5ef2aSThomas Huth 4704*fcf5ef2aSThomas Huth /* maskg - maskg. */ 4705*fcf5ef2aSThomas Huth static void gen_maskg(DisasContext *ctx) 4706*fcf5ef2aSThomas Huth { 4707*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4708*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4709*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4710*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 4711*fcf5ef2aSThomas Huth TCGv t3 = tcg_temp_new(); 4712*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t3, 0xFFFFFFFF); 4713*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); 4714*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F); 4715*fcf5ef2aSThomas Huth tcg_gen_addi_tl(t2, t0, 1); 4716*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t2, t3, t2); 4717*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t3, t3, t1); 4718*fcf5ef2aSThomas Huth tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3); 4719*fcf5ef2aSThomas Huth tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1); 4720*fcf5ef2aSThomas Huth tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4721*fcf5ef2aSThomas Huth gen_set_label(l1); 4722*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4723*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4724*fcf5ef2aSThomas Huth tcg_temp_free(t2); 4725*fcf5ef2aSThomas Huth tcg_temp_free(t3); 4726*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4727*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4728*fcf5ef2aSThomas Huth } 4729*fcf5ef2aSThomas Huth 4730*fcf5ef2aSThomas Huth /* maskir - maskir. */ 4731*fcf5ef2aSThomas Huth static void gen_maskir(DisasContext *ctx) 4732*fcf5ef2aSThomas Huth { 4733*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4734*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4735*fcf5ef2aSThomas Huth tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 4736*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 4737*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 4738*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4739*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4740*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4741*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4742*fcf5ef2aSThomas Huth } 4743*fcf5ef2aSThomas Huth 4744*fcf5ef2aSThomas Huth /* mul - mul. */ 4745*fcf5ef2aSThomas Huth static void gen_mul(DisasContext *ctx) 4746*fcf5ef2aSThomas Huth { 4747*fcf5ef2aSThomas Huth TCGv_i64 t0 = tcg_temp_new_i64(); 4748*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 4749*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 4750*fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]); 4751*fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]); 4752*fcf5ef2aSThomas Huth tcg_gen_mul_i64(t0, t0, t1); 4753*fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(t2, t0); 4754*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t2); 4755*fcf5ef2aSThomas Huth tcg_gen_shri_i64(t1, t0, 32); 4756*fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1); 4757*fcf5ef2aSThomas Huth tcg_temp_free_i64(t0); 4758*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 4759*fcf5ef2aSThomas Huth tcg_temp_free(t2); 4760*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4761*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4762*fcf5ef2aSThomas Huth } 4763*fcf5ef2aSThomas Huth 4764*fcf5ef2aSThomas Huth /* mulo - mulo. */ 4765*fcf5ef2aSThomas Huth static void gen_mulo(DisasContext *ctx) 4766*fcf5ef2aSThomas Huth { 4767*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4768*fcf5ef2aSThomas Huth TCGv_i64 t0 = tcg_temp_new_i64(); 4769*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 4770*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 4771*fcf5ef2aSThomas Huth /* Start with XER OV disabled, the most likely case */ 4772*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 0); 4773*fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]); 4774*fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]); 4775*fcf5ef2aSThomas Huth tcg_gen_mul_i64(t0, t0, t1); 4776*fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(t2, t0); 4777*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t2); 4778*fcf5ef2aSThomas Huth tcg_gen_shri_i64(t1, t0, 32); 4779*fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1); 4780*fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t1, t0); 4781*fcf5ef2aSThomas Huth tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1); 4782*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 1); 4783*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_so, 1); 4784*fcf5ef2aSThomas Huth gen_set_label(l1); 4785*fcf5ef2aSThomas Huth tcg_temp_free_i64(t0); 4786*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 4787*fcf5ef2aSThomas Huth tcg_temp_free(t2); 4788*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4789*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4790*fcf5ef2aSThomas Huth } 4791*fcf5ef2aSThomas Huth 4792*fcf5ef2aSThomas Huth /* nabs - nabs. */ 4793*fcf5ef2aSThomas Huth static void gen_nabs(DisasContext *ctx) 4794*fcf5ef2aSThomas Huth { 4795*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4796*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4797*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1); 4798*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4799*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4800*fcf5ef2aSThomas Huth gen_set_label(l1); 4801*fcf5ef2aSThomas Huth tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4802*fcf5ef2aSThomas Huth gen_set_label(l2); 4803*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4804*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4805*fcf5ef2aSThomas Huth } 4806*fcf5ef2aSThomas Huth 4807*fcf5ef2aSThomas Huth /* nabso - nabso. */ 4808*fcf5ef2aSThomas Huth static void gen_nabso(DisasContext *ctx) 4809*fcf5ef2aSThomas Huth { 4810*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4811*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4812*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1); 4813*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4814*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4815*fcf5ef2aSThomas Huth gen_set_label(l1); 4816*fcf5ef2aSThomas Huth tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 4817*fcf5ef2aSThomas Huth gen_set_label(l2); 4818*fcf5ef2aSThomas Huth /* nabs never overflows */ 4819*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 0); 4820*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4821*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); 4822*fcf5ef2aSThomas Huth } 4823*fcf5ef2aSThomas Huth 4824*fcf5ef2aSThomas Huth /* rlmi - rlmi. */ 4825*fcf5ef2aSThomas Huth static void gen_rlmi(DisasContext *ctx) 4826*fcf5ef2aSThomas Huth { 4827*fcf5ef2aSThomas Huth uint32_t mb = MB(ctx->opcode); 4828*fcf5ef2aSThomas Huth uint32_t me = ME(ctx->opcode); 4829*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4830*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); 4831*fcf5ef2aSThomas Huth tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 4832*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, MASK(mb, me)); 4833*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me)); 4834*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0); 4835*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4836*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4837*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4838*fcf5ef2aSThomas Huth } 4839*fcf5ef2aSThomas Huth 4840*fcf5ef2aSThomas Huth /* rrib - rrib. */ 4841*fcf5ef2aSThomas Huth static void gen_rrib(DisasContext *ctx) 4842*fcf5ef2aSThomas Huth { 4843*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4844*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4845*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); 4846*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t1, 0x80000000); 4847*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t1, t1, t0); 4848*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 4849*fcf5ef2aSThomas Huth tcg_gen_and_tl(t0, t0, t1); 4850*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1); 4851*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 4852*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4853*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4854*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4855*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4856*fcf5ef2aSThomas Huth } 4857*fcf5ef2aSThomas Huth 4858*fcf5ef2aSThomas Huth /* sle - sle. */ 4859*fcf5ef2aSThomas Huth static void gen_sle(DisasContext *ctx) 4860*fcf5ef2aSThomas Huth { 4861*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4862*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4863*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); 4864*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); 4865*fcf5ef2aSThomas Huth tcg_gen_subfi_tl(t1, 32, t1); 4866*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); 4867*fcf5ef2aSThomas Huth tcg_gen_or_tl(t1, t0, t1); 4868*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); 4869*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t1); 4870*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4871*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4872*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4873*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4874*fcf5ef2aSThomas Huth } 4875*fcf5ef2aSThomas Huth 4876*fcf5ef2aSThomas Huth /* sleq - sleq. */ 4877*fcf5ef2aSThomas Huth static void gen_sleq(DisasContext *ctx) 4878*fcf5ef2aSThomas Huth { 4879*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4880*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4881*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 4882*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); 4883*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t2, 0xFFFFFFFF); 4884*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t2, t2, t0); 4885*fcf5ef2aSThomas Huth tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 4886*fcf5ef2aSThomas Huth gen_load_spr(t1, SPR_MQ); 4887*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 4888*fcf5ef2aSThomas Huth tcg_gen_and_tl(t0, t0, t2); 4889*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t1, t1, t2); 4890*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 4891*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4892*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4893*fcf5ef2aSThomas Huth tcg_temp_free(t2); 4894*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4895*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4896*fcf5ef2aSThomas Huth } 4897*fcf5ef2aSThomas Huth 4898*fcf5ef2aSThomas Huth /* sliq - sliq. */ 4899*fcf5ef2aSThomas Huth static void gen_sliq(DisasContext *ctx) 4900*fcf5ef2aSThomas Huth { 4901*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode); 4902*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4903*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4904*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); 4905*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh); 4906*fcf5ef2aSThomas Huth tcg_gen_or_tl(t1, t0, t1); 4907*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); 4908*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t1); 4909*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4910*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4911*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4912*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4913*fcf5ef2aSThomas Huth } 4914*fcf5ef2aSThomas Huth 4915*fcf5ef2aSThomas Huth /* slliq - slliq. */ 4916*fcf5ef2aSThomas Huth static void gen_slliq(DisasContext *ctx) 4917*fcf5ef2aSThomas Huth { 4918*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode); 4919*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4920*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4921*fcf5ef2aSThomas Huth tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); 4922*fcf5ef2aSThomas Huth gen_load_spr(t1, SPR_MQ); 4923*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 4924*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh)); 4925*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh)); 4926*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 4927*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4928*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4929*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4930*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4931*fcf5ef2aSThomas Huth } 4932*fcf5ef2aSThomas Huth 4933*fcf5ef2aSThomas Huth /* sllq - sllq. */ 4934*fcf5ef2aSThomas Huth static void gen_sllq(DisasContext *ctx) 4935*fcf5ef2aSThomas Huth { 4936*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4937*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 4938*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_local_new(); 4939*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_local_new(); 4940*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_local_new(); 4941*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F); 4942*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t1, 0xFFFFFFFF); 4943*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t1, t1, t2); 4944*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20); 4945*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); 4946*fcf5ef2aSThomas Huth gen_load_spr(t0, SPR_MQ); 4947*fcf5ef2aSThomas Huth tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 4948*fcf5ef2aSThomas Huth tcg_gen_br(l2); 4949*fcf5ef2aSThomas Huth gen_set_label(l1); 4950*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2); 4951*fcf5ef2aSThomas Huth gen_load_spr(t2, SPR_MQ); 4952*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t1, t2, t1); 4953*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 4954*fcf5ef2aSThomas Huth gen_set_label(l2); 4955*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4956*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4957*fcf5ef2aSThomas Huth tcg_temp_free(t2); 4958*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4959*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4960*fcf5ef2aSThomas Huth } 4961*fcf5ef2aSThomas Huth 4962*fcf5ef2aSThomas Huth /* slq - slq. */ 4963*fcf5ef2aSThomas Huth static void gen_slq(DisasContext *ctx) 4964*fcf5ef2aSThomas Huth { 4965*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4966*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4967*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4968*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); 4969*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); 4970*fcf5ef2aSThomas Huth tcg_gen_subfi_tl(t1, 32, t1); 4971*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); 4972*fcf5ef2aSThomas Huth tcg_gen_or_tl(t1, t0, t1); 4973*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t1); 4974*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20); 4975*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); 4976*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); 4977*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); 4978*fcf5ef2aSThomas Huth gen_set_label(l1); 4979*fcf5ef2aSThomas Huth tcg_temp_free(t0); 4980*fcf5ef2aSThomas Huth tcg_temp_free(t1); 4981*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 4982*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 4983*fcf5ef2aSThomas Huth } 4984*fcf5ef2aSThomas Huth 4985*fcf5ef2aSThomas Huth /* sraiq - sraiq. */ 4986*fcf5ef2aSThomas Huth static void gen_sraiq(DisasContext *ctx) 4987*fcf5ef2aSThomas Huth { 4988*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode); 4989*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 4990*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 4991*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 4992*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); 4993*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh); 4994*fcf5ef2aSThomas Huth tcg_gen_or_tl(t0, t0, t1); 4995*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 4996*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 0); 4997*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); 4998*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1); 4999*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 1); 5000*fcf5ef2aSThomas Huth gen_set_label(l1); 5001*fcf5ef2aSThomas Huth tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh); 5002*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5003*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5004*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5005*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5006*fcf5ef2aSThomas Huth } 5007*fcf5ef2aSThomas Huth 5008*fcf5ef2aSThomas Huth /* sraq - sraq. */ 5009*fcf5ef2aSThomas Huth static void gen_sraq(DisasContext *ctx) 5010*fcf5ef2aSThomas Huth { 5011*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 5012*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 5013*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5014*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_local_new(); 5015*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_local_new(); 5016*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F); 5017*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2); 5018*fcf5ef2aSThomas Huth tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2); 5019*fcf5ef2aSThomas Huth tcg_gen_subfi_tl(t2, 32, t2); 5020*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2); 5021*fcf5ef2aSThomas Huth tcg_gen_or_tl(t0, t0, t2); 5022*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 5023*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20); 5024*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1); 5025*fcf5ef2aSThomas Huth tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]); 5026*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31); 5027*fcf5ef2aSThomas Huth gen_set_label(l1); 5028*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5029*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1); 5030*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 0); 5031*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2); 5032*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2); 5033*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ca, 1); 5034*fcf5ef2aSThomas Huth gen_set_label(l2); 5035*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5036*fcf5ef2aSThomas Huth tcg_temp_free(t2); 5037*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5038*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5039*fcf5ef2aSThomas Huth } 5040*fcf5ef2aSThomas Huth 5041*fcf5ef2aSThomas Huth /* sre - sre. */ 5042*fcf5ef2aSThomas Huth static void gen_sre(DisasContext *ctx) 5043*fcf5ef2aSThomas Huth { 5044*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5045*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 5046*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); 5047*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); 5048*fcf5ef2aSThomas Huth tcg_gen_subfi_tl(t1, 32, t1); 5049*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); 5050*fcf5ef2aSThomas Huth tcg_gen_or_tl(t1, t0, t1); 5051*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); 5052*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t1); 5053*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5054*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5055*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5056*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5057*fcf5ef2aSThomas Huth } 5058*fcf5ef2aSThomas Huth 5059*fcf5ef2aSThomas Huth /* srea - srea. */ 5060*fcf5ef2aSThomas Huth static void gen_srea(DisasContext *ctx) 5061*fcf5ef2aSThomas Huth { 5062*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5063*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 5064*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); 5065*fcf5ef2aSThomas Huth tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); 5066*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 5067*fcf5ef2aSThomas Huth tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1); 5068*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5069*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5070*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5071*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5072*fcf5ef2aSThomas Huth } 5073*fcf5ef2aSThomas Huth 5074*fcf5ef2aSThomas Huth /* sreq */ 5075*fcf5ef2aSThomas Huth static void gen_sreq(DisasContext *ctx) 5076*fcf5ef2aSThomas Huth { 5077*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5078*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 5079*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 5080*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); 5081*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t1, 0xFFFFFFFF); 5082*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t1, t1, t0); 5083*fcf5ef2aSThomas Huth tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); 5084*fcf5ef2aSThomas Huth gen_load_spr(t2, SPR_MQ); 5085*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 5086*fcf5ef2aSThomas Huth tcg_gen_and_tl(t0, t0, t1); 5087*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t2, t2, t1); 5088*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2); 5089*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5090*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5091*fcf5ef2aSThomas Huth tcg_temp_free(t2); 5092*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5093*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5094*fcf5ef2aSThomas Huth } 5095*fcf5ef2aSThomas Huth 5096*fcf5ef2aSThomas Huth /* sriq */ 5097*fcf5ef2aSThomas Huth static void gen_sriq(DisasContext *ctx) 5098*fcf5ef2aSThomas Huth { 5099*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode); 5100*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5101*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 5102*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); 5103*fcf5ef2aSThomas Huth tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh); 5104*fcf5ef2aSThomas Huth tcg_gen_or_tl(t1, t0, t1); 5105*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); 5106*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t1); 5107*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5108*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5109*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5110*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5111*fcf5ef2aSThomas Huth } 5112*fcf5ef2aSThomas Huth 5113*fcf5ef2aSThomas Huth /* srliq */ 5114*fcf5ef2aSThomas Huth static void gen_srliq(DisasContext *ctx) 5115*fcf5ef2aSThomas Huth { 5116*fcf5ef2aSThomas Huth int sh = SH(ctx->opcode); 5117*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5118*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 5119*fcf5ef2aSThomas Huth tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); 5120*fcf5ef2aSThomas Huth gen_load_spr(t1, SPR_MQ); 5121*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t0); 5122*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh)); 5123*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh)); 5124*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 5125*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5126*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5127*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5128*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5129*fcf5ef2aSThomas Huth } 5130*fcf5ef2aSThomas Huth 5131*fcf5ef2aSThomas Huth /* srlq */ 5132*fcf5ef2aSThomas Huth static void gen_srlq(DisasContext *ctx) 5133*fcf5ef2aSThomas Huth { 5134*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 5135*fcf5ef2aSThomas Huth TCGLabel *l2 = gen_new_label(); 5136*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_local_new(); 5137*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_local_new(); 5138*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_local_new(); 5139*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F); 5140*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t1, 0xFFFFFFFF); 5141*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t2, t1, t2); 5142*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20); 5143*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); 5144*fcf5ef2aSThomas Huth gen_load_spr(t0, SPR_MQ); 5145*fcf5ef2aSThomas Huth tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2); 5146*fcf5ef2aSThomas Huth tcg_gen_br(l2); 5147*fcf5ef2aSThomas Huth gen_set_label(l1); 5148*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2); 5149*fcf5ef2aSThomas Huth tcg_gen_and_tl(t0, t0, t2); 5150*fcf5ef2aSThomas Huth gen_load_spr(t1, SPR_MQ); 5151*fcf5ef2aSThomas Huth tcg_gen_andc_tl(t1, t1, t2); 5152*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); 5153*fcf5ef2aSThomas Huth gen_set_label(l2); 5154*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5155*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5156*fcf5ef2aSThomas Huth tcg_temp_free(t2); 5157*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5158*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5159*fcf5ef2aSThomas Huth } 5160*fcf5ef2aSThomas Huth 5161*fcf5ef2aSThomas Huth /* srq */ 5162*fcf5ef2aSThomas Huth static void gen_srq(DisasContext *ctx) 5163*fcf5ef2aSThomas Huth { 5164*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 5165*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 5166*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 5167*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); 5168*fcf5ef2aSThomas Huth tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); 5169*fcf5ef2aSThomas Huth tcg_gen_subfi_tl(t1, 32, t1); 5170*fcf5ef2aSThomas Huth tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); 5171*fcf5ef2aSThomas Huth tcg_gen_or_tl(t1, t0, t1); 5172*fcf5ef2aSThomas Huth gen_store_spr(SPR_MQ, t1); 5173*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20); 5174*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); 5175*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); 5176*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); 5177*fcf5ef2aSThomas Huth gen_set_label(l1); 5178*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5179*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5180*fcf5ef2aSThomas Huth if (unlikely(Rc(ctx->opcode) != 0)) 5181*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); 5182*fcf5ef2aSThomas Huth } 5183*fcf5ef2aSThomas Huth 5184*fcf5ef2aSThomas Huth /* PowerPC 602 specific instructions */ 5185*fcf5ef2aSThomas Huth 5186*fcf5ef2aSThomas Huth /* dsa */ 5187*fcf5ef2aSThomas Huth static void gen_dsa(DisasContext *ctx) 5188*fcf5ef2aSThomas Huth { 5189*fcf5ef2aSThomas Huth /* XXX: TODO */ 5190*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5191*fcf5ef2aSThomas Huth } 5192*fcf5ef2aSThomas Huth 5193*fcf5ef2aSThomas Huth /* esa */ 5194*fcf5ef2aSThomas Huth static void gen_esa(DisasContext *ctx) 5195*fcf5ef2aSThomas Huth { 5196*fcf5ef2aSThomas Huth /* XXX: TODO */ 5197*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5198*fcf5ef2aSThomas Huth } 5199*fcf5ef2aSThomas Huth 5200*fcf5ef2aSThomas Huth /* mfrom */ 5201*fcf5ef2aSThomas Huth static void gen_mfrom(DisasContext *ctx) 5202*fcf5ef2aSThomas Huth { 5203*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5204*fcf5ef2aSThomas Huth GEN_PRIV; 5205*fcf5ef2aSThomas Huth #else 5206*fcf5ef2aSThomas Huth CHK_SV; 5207*fcf5ef2aSThomas Huth gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 5208*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5209*fcf5ef2aSThomas Huth } 5210*fcf5ef2aSThomas Huth 5211*fcf5ef2aSThomas Huth /* 602 - 603 - G2 TLB management */ 5212*fcf5ef2aSThomas Huth 5213*fcf5ef2aSThomas Huth /* tlbld */ 5214*fcf5ef2aSThomas Huth static void gen_tlbld_6xx(DisasContext *ctx) 5215*fcf5ef2aSThomas Huth { 5216*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5217*fcf5ef2aSThomas Huth GEN_PRIV; 5218*fcf5ef2aSThomas Huth #else 5219*fcf5ef2aSThomas Huth CHK_SV; 5220*fcf5ef2aSThomas Huth gen_helper_6xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]); 5221*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5222*fcf5ef2aSThomas Huth } 5223*fcf5ef2aSThomas Huth 5224*fcf5ef2aSThomas Huth /* tlbli */ 5225*fcf5ef2aSThomas Huth static void gen_tlbli_6xx(DisasContext *ctx) 5226*fcf5ef2aSThomas Huth { 5227*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5228*fcf5ef2aSThomas Huth GEN_PRIV; 5229*fcf5ef2aSThomas Huth #else 5230*fcf5ef2aSThomas Huth CHK_SV; 5231*fcf5ef2aSThomas Huth gen_helper_6xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]); 5232*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5233*fcf5ef2aSThomas Huth } 5234*fcf5ef2aSThomas Huth 5235*fcf5ef2aSThomas Huth /* 74xx TLB management */ 5236*fcf5ef2aSThomas Huth 5237*fcf5ef2aSThomas Huth /* tlbld */ 5238*fcf5ef2aSThomas Huth static void gen_tlbld_74xx(DisasContext *ctx) 5239*fcf5ef2aSThomas Huth { 5240*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5241*fcf5ef2aSThomas Huth GEN_PRIV; 5242*fcf5ef2aSThomas Huth #else 5243*fcf5ef2aSThomas Huth CHK_SV; 5244*fcf5ef2aSThomas Huth gen_helper_74xx_tlbd(cpu_env, cpu_gpr[rB(ctx->opcode)]); 5245*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5246*fcf5ef2aSThomas Huth } 5247*fcf5ef2aSThomas Huth 5248*fcf5ef2aSThomas Huth /* tlbli */ 5249*fcf5ef2aSThomas Huth static void gen_tlbli_74xx(DisasContext *ctx) 5250*fcf5ef2aSThomas Huth { 5251*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5252*fcf5ef2aSThomas Huth GEN_PRIV; 5253*fcf5ef2aSThomas Huth #else 5254*fcf5ef2aSThomas Huth CHK_SV; 5255*fcf5ef2aSThomas Huth gen_helper_74xx_tlbi(cpu_env, cpu_gpr[rB(ctx->opcode)]); 5256*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5257*fcf5ef2aSThomas Huth } 5258*fcf5ef2aSThomas Huth 5259*fcf5ef2aSThomas Huth /* POWER instructions not in PowerPC 601 */ 5260*fcf5ef2aSThomas Huth 5261*fcf5ef2aSThomas Huth /* clf */ 5262*fcf5ef2aSThomas Huth static void gen_clf(DisasContext *ctx) 5263*fcf5ef2aSThomas Huth { 5264*fcf5ef2aSThomas Huth /* Cache line flush: implemented as no-op */ 5265*fcf5ef2aSThomas Huth } 5266*fcf5ef2aSThomas Huth 5267*fcf5ef2aSThomas Huth /* cli */ 5268*fcf5ef2aSThomas Huth static void gen_cli(DisasContext *ctx) 5269*fcf5ef2aSThomas Huth { 5270*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5271*fcf5ef2aSThomas Huth GEN_PRIV; 5272*fcf5ef2aSThomas Huth #else 5273*fcf5ef2aSThomas Huth /* Cache line invalidate: privileged and treated as no-op */ 5274*fcf5ef2aSThomas Huth CHK_SV; 5275*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5276*fcf5ef2aSThomas Huth } 5277*fcf5ef2aSThomas Huth 5278*fcf5ef2aSThomas Huth /* dclst */ 5279*fcf5ef2aSThomas Huth static void gen_dclst(DisasContext *ctx) 5280*fcf5ef2aSThomas Huth { 5281*fcf5ef2aSThomas Huth /* Data cache line store: treated as no-op */ 5282*fcf5ef2aSThomas Huth } 5283*fcf5ef2aSThomas Huth 5284*fcf5ef2aSThomas Huth static void gen_mfsri(DisasContext *ctx) 5285*fcf5ef2aSThomas Huth { 5286*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5287*fcf5ef2aSThomas Huth GEN_PRIV; 5288*fcf5ef2aSThomas Huth #else 5289*fcf5ef2aSThomas Huth int ra = rA(ctx->opcode); 5290*fcf5ef2aSThomas Huth int rd = rD(ctx->opcode); 5291*fcf5ef2aSThomas Huth TCGv t0; 5292*fcf5ef2aSThomas Huth 5293*fcf5ef2aSThomas Huth CHK_SV; 5294*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5295*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5296*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, t0, 28); 5297*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, t0, 0xF); 5298*fcf5ef2aSThomas Huth gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0); 5299*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5300*fcf5ef2aSThomas Huth if (ra != 0 && ra != rd) 5301*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]); 5302*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5303*fcf5ef2aSThomas Huth } 5304*fcf5ef2aSThomas Huth 5305*fcf5ef2aSThomas Huth static void gen_rac(DisasContext *ctx) 5306*fcf5ef2aSThomas Huth { 5307*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5308*fcf5ef2aSThomas Huth GEN_PRIV; 5309*fcf5ef2aSThomas Huth #else 5310*fcf5ef2aSThomas Huth TCGv t0; 5311*fcf5ef2aSThomas Huth 5312*fcf5ef2aSThomas Huth CHK_SV; 5313*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5314*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5315*fcf5ef2aSThomas Huth gen_helper_rac(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 5316*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5317*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5318*fcf5ef2aSThomas Huth } 5319*fcf5ef2aSThomas Huth 5320*fcf5ef2aSThomas Huth static void gen_rfsvc(DisasContext *ctx) 5321*fcf5ef2aSThomas Huth { 5322*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5323*fcf5ef2aSThomas Huth GEN_PRIV; 5324*fcf5ef2aSThomas Huth #else 5325*fcf5ef2aSThomas Huth CHK_SV; 5326*fcf5ef2aSThomas Huth 5327*fcf5ef2aSThomas Huth gen_helper_rfsvc(cpu_env); 5328*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 5329*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5330*fcf5ef2aSThomas Huth } 5331*fcf5ef2aSThomas Huth 5332*fcf5ef2aSThomas Huth /* svc is not implemented for now */ 5333*fcf5ef2aSThomas Huth 5334*fcf5ef2aSThomas Huth /* BookE specific instructions */ 5335*fcf5ef2aSThomas Huth 5336*fcf5ef2aSThomas Huth /* XXX: not implemented on 440 ? */ 5337*fcf5ef2aSThomas Huth static void gen_mfapidi(DisasContext *ctx) 5338*fcf5ef2aSThomas Huth { 5339*fcf5ef2aSThomas Huth /* XXX: TODO */ 5340*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5341*fcf5ef2aSThomas Huth } 5342*fcf5ef2aSThomas Huth 5343*fcf5ef2aSThomas Huth /* XXX: not implemented on 440 ? */ 5344*fcf5ef2aSThomas Huth static void gen_tlbiva(DisasContext *ctx) 5345*fcf5ef2aSThomas Huth { 5346*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5347*fcf5ef2aSThomas Huth GEN_PRIV; 5348*fcf5ef2aSThomas Huth #else 5349*fcf5ef2aSThomas Huth TCGv t0; 5350*fcf5ef2aSThomas Huth 5351*fcf5ef2aSThomas Huth CHK_SV; 5352*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5353*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5354*fcf5ef2aSThomas Huth gen_helper_tlbiva(cpu_env, cpu_gpr[rB(ctx->opcode)]); 5355*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5356*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5357*fcf5ef2aSThomas Huth } 5358*fcf5ef2aSThomas Huth 5359*fcf5ef2aSThomas Huth /* All 405 MAC instructions are translated here */ 5360*fcf5ef2aSThomas Huth static inline void gen_405_mulladd_insn(DisasContext *ctx, int opc2, int opc3, 5361*fcf5ef2aSThomas Huth int ra, int rb, int rt, int Rc) 5362*fcf5ef2aSThomas Huth { 5363*fcf5ef2aSThomas Huth TCGv t0, t1; 5364*fcf5ef2aSThomas Huth 5365*fcf5ef2aSThomas Huth t0 = tcg_temp_local_new(); 5366*fcf5ef2aSThomas Huth t1 = tcg_temp_local_new(); 5367*fcf5ef2aSThomas Huth 5368*fcf5ef2aSThomas Huth switch (opc3 & 0x0D) { 5369*fcf5ef2aSThomas Huth case 0x05: 5370*fcf5ef2aSThomas Huth /* macchw - macchw. - macchwo - macchwo. */ 5371*fcf5ef2aSThomas Huth /* macchws - macchws. - macchwso - macchwso. */ 5372*fcf5ef2aSThomas Huth /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */ 5373*fcf5ef2aSThomas Huth /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */ 5374*fcf5ef2aSThomas Huth /* mulchw - mulchw. */ 5375*fcf5ef2aSThomas Huth tcg_gen_ext16s_tl(t0, cpu_gpr[ra]); 5376*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t1, cpu_gpr[rb], 16); 5377*fcf5ef2aSThomas Huth tcg_gen_ext16s_tl(t1, t1); 5378*fcf5ef2aSThomas Huth break; 5379*fcf5ef2aSThomas Huth case 0x04: 5380*fcf5ef2aSThomas Huth /* macchwu - macchwu. - macchwuo - macchwuo. */ 5381*fcf5ef2aSThomas Huth /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */ 5382*fcf5ef2aSThomas Huth /* mulchwu - mulchwu. */ 5383*fcf5ef2aSThomas Huth tcg_gen_ext16u_tl(t0, cpu_gpr[ra]); 5384*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t1, cpu_gpr[rb], 16); 5385*fcf5ef2aSThomas Huth tcg_gen_ext16u_tl(t1, t1); 5386*fcf5ef2aSThomas Huth break; 5387*fcf5ef2aSThomas Huth case 0x01: 5388*fcf5ef2aSThomas Huth /* machhw - machhw. - machhwo - machhwo. */ 5389*fcf5ef2aSThomas Huth /* machhws - machhws. - machhwso - machhwso. */ 5390*fcf5ef2aSThomas Huth /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */ 5391*fcf5ef2aSThomas Huth /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */ 5392*fcf5ef2aSThomas Huth /* mulhhw - mulhhw. */ 5393*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, cpu_gpr[ra], 16); 5394*fcf5ef2aSThomas Huth tcg_gen_ext16s_tl(t0, t0); 5395*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t1, cpu_gpr[rb], 16); 5396*fcf5ef2aSThomas Huth tcg_gen_ext16s_tl(t1, t1); 5397*fcf5ef2aSThomas Huth break; 5398*fcf5ef2aSThomas Huth case 0x00: 5399*fcf5ef2aSThomas Huth /* machhwu - machhwu. - machhwuo - machhwuo. */ 5400*fcf5ef2aSThomas Huth /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */ 5401*fcf5ef2aSThomas Huth /* mulhhwu - mulhhwu. */ 5402*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t0, cpu_gpr[ra], 16); 5403*fcf5ef2aSThomas Huth tcg_gen_ext16u_tl(t0, t0); 5404*fcf5ef2aSThomas Huth tcg_gen_shri_tl(t1, cpu_gpr[rb], 16); 5405*fcf5ef2aSThomas Huth tcg_gen_ext16u_tl(t1, t1); 5406*fcf5ef2aSThomas Huth break; 5407*fcf5ef2aSThomas Huth case 0x0D: 5408*fcf5ef2aSThomas Huth /* maclhw - maclhw. - maclhwo - maclhwo. */ 5409*fcf5ef2aSThomas Huth /* maclhws - maclhws. - maclhwso - maclhwso. */ 5410*fcf5ef2aSThomas Huth /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */ 5411*fcf5ef2aSThomas Huth /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */ 5412*fcf5ef2aSThomas Huth /* mullhw - mullhw. */ 5413*fcf5ef2aSThomas Huth tcg_gen_ext16s_tl(t0, cpu_gpr[ra]); 5414*fcf5ef2aSThomas Huth tcg_gen_ext16s_tl(t1, cpu_gpr[rb]); 5415*fcf5ef2aSThomas Huth break; 5416*fcf5ef2aSThomas Huth case 0x0C: 5417*fcf5ef2aSThomas Huth /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */ 5418*fcf5ef2aSThomas Huth /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */ 5419*fcf5ef2aSThomas Huth /* mullhwu - mullhwu. */ 5420*fcf5ef2aSThomas Huth tcg_gen_ext16u_tl(t0, cpu_gpr[ra]); 5421*fcf5ef2aSThomas Huth tcg_gen_ext16u_tl(t1, cpu_gpr[rb]); 5422*fcf5ef2aSThomas Huth break; 5423*fcf5ef2aSThomas Huth } 5424*fcf5ef2aSThomas Huth if (opc2 & 0x04) { 5425*fcf5ef2aSThomas Huth /* (n)multiply-and-accumulate (0x0C / 0x0E) */ 5426*fcf5ef2aSThomas Huth tcg_gen_mul_tl(t1, t0, t1); 5427*fcf5ef2aSThomas Huth if (opc2 & 0x02) { 5428*fcf5ef2aSThomas Huth /* nmultiply-and-accumulate (0x0E) */ 5429*fcf5ef2aSThomas Huth tcg_gen_sub_tl(t0, cpu_gpr[rt], t1); 5430*fcf5ef2aSThomas Huth } else { 5431*fcf5ef2aSThomas Huth /* multiply-and-accumulate (0x0C) */ 5432*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, cpu_gpr[rt], t1); 5433*fcf5ef2aSThomas Huth } 5434*fcf5ef2aSThomas Huth 5435*fcf5ef2aSThomas Huth if (opc3 & 0x12) { 5436*fcf5ef2aSThomas Huth /* Check overflow and/or saturate */ 5437*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 5438*fcf5ef2aSThomas Huth 5439*fcf5ef2aSThomas Huth if (opc3 & 0x10) { 5440*fcf5ef2aSThomas Huth /* Start with XER OV disabled, the most likely case */ 5441*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 0); 5442*fcf5ef2aSThomas Huth } 5443*fcf5ef2aSThomas Huth if (opc3 & 0x01) { 5444*fcf5ef2aSThomas Huth /* Signed */ 5445*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t1, cpu_gpr[rt], t1); 5446*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); 5447*fcf5ef2aSThomas Huth tcg_gen_xor_tl(t1, cpu_gpr[rt], t0); 5448*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1); 5449*fcf5ef2aSThomas Huth if (opc3 & 0x02) { 5450*fcf5ef2aSThomas Huth /* Saturate */ 5451*fcf5ef2aSThomas Huth tcg_gen_sari_tl(t0, cpu_gpr[rt], 31); 5452*fcf5ef2aSThomas Huth tcg_gen_xori_tl(t0, t0, 0x7fffffff); 5453*fcf5ef2aSThomas Huth } 5454*fcf5ef2aSThomas Huth } else { 5455*fcf5ef2aSThomas Huth /* Unsigned */ 5456*fcf5ef2aSThomas Huth tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1); 5457*fcf5ef2aSThomas Huth if (opc3 & 0x02) { 5458*fcf5ef2aSThomas Huth /* Saturate */ 5459*fcf5ef2aSThomas Huth tcg_gen_movi_tl(t0, UINT32_MAX); 5460*fcf5ef2aSThomas Huth } 5461*fcf5ef2aSThomas Huth } 5462*fcf5ef2aSThomas Huth if (opc3 & 0x10) { 5463*fcf5ef2aSThomas Huth /* Check overflow */ 5464*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_ov, 1); 5465*fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_so, 1); 5466*fcf5ef2aSThomas Huth } 5467*fcf5ef2aSThomas Huth gen_set_label(l1); 5468*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rt], t0); 5469*fcf5ef2aSThomas Huth } 5470*fcf5ef2aSThomas Huth } else { 5471*fcf5ef2aSThomas Huth tcg_gen_mul_tl(cpu_gpr[rt], t0, t1); 5472*fcf5ef2aSThomas Huth } 5473*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5474*fcf5ef2aSThomas Huth tcg_temp_free(t1); 5475*fcf5ef2aSThomas Huth if (unlikely(Rc) != 0) { 5476*fcf5ef2aSThomas Huth /* Update Rc0 */ 5477*fcf5ef2aSThomas Huth gen_set_Rc0(ctx, cpu_gpr[rt]); 5478*fcf5ef2aSThomas Huth } 5479*fcf5ef2aSThomas Huth } 5480*fcf5ef2aSThomas Huth 5481*fcf5ef2aSThomas Huth #define GEN_MAC_HANDLER(name, opc2, opc3) \ 5482*fcf5ef2aSThomas Huth static void glue(gen_, name)(DisasContext *ctx) \ 5483*fcf5ef2aSThomas Huth { \ 5484*fcf5ef2aSThomas Huth gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \ 5485*fcf5ef2aSThomas Huth rD(ctx->opcode), Rc(ctx->opcode)); \ 5486*fcf5ef2aSThomas Huth } 5487*fcf5ef2aSThomas Huth 5488*fcf5ef2aSThomas Huth /* macchw - macchw. */ 5489*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchw, 0x0C, 0x05); 5490*fcf5ef2aSThomas Huth /* macchwo - macchwo. */ 5491*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwo, 0x0C, 0x15); 5492*fcf5ef2aSThomas Huth /* macchws - macchws. */ 5493*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchws, 0x0C, 0x07); 5494*fcf5ef2aSThomas Huth /* macchwso - macchwso. */ 5495*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwso, 0x0C, 0x17); 5496*fcf5ef2aSThomas Huth /* macchwsu - macchwsu. */ 5497*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06); 5498*fcf5ef2aSThomas Huth /* macchwsuo - macchwsuo. */ 5499*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16); 5500*fcf5ef2aSThomas Huth /* macchwu - macchwu. */ 5501*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwu, 0x0C, 0x04); 5502*fcf5ef2aSThomas Huth /* macchwuo - macchwuo. */ 5503*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14); 5504*fcf5ef2aSThomas Huth /* machhw - machhw. */ 5505*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhw, 0x0C, 0x01); 5506*fcf5ef2aSThomas Huth /* machhwo - machhwo. */ 5507*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwo, 0x0C, 0x11); 5508*fcf5ef2aSThomas Huth /* machhws - machhws. */ 5509*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhws, 0x0C, 0x03); 5510*fcf5ef2aSThomas Huth /* machhwso - machhwso. */ 5511*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwso, 0x0C, 0x13); 5512*fcf5ef2aSThomas Huth /* machhwsu - machhwsu. */ 5513*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02); 5514*fcf5ef2aSThomas Huth /* machhwsuo - machhwsuo. */ 5515*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12); 5516*fcf5ef2aSThomas Huth /* machhwu - machhwu. */ 5517*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwu, 0x0C, 0x00); 5518*fcf5ef2aSThomas Huth /* machhwuo - machhwuo. */ 5519*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10); 5520*fcf5ef2aSThomas Huth /* maclhw - maclhw. */ 5521*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D); 5522*fcf5ef2aSThomas Huth /* maclhwo - maclhwo. */ 5523*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D); 5524*fcf5ef2aSThomas Huth /* maclhws - maclhws. */ 5525*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F); 5526*fcf5ef2aSThomas Huth /* maclhwso - maclhwso. */ 5527*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F); 5528*fcf5ef2aSThomas Huth /* maclhwu - maclhwu. */ 5529*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C); 5530*fcf5ef2aSThomas Huth /* maclhwuo - maclhwuo. */ 5531*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C); 5532*fcf5ef2aSThomas Huth /* maclhwsu - maclhwsu. */ 5533*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E); 5534*fcf5ef2aSThomas Huth /* maclhwsuo - maclhwsuo. */ 5535*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E); 5536*fcf5ef2aSThomas Huth /* nmacchw - nmacchw. */ 5537*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05); 5538*fcf5ef2aSThomas Huth /* nmacchwo - nmacchwo. */ 5539*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15); 5540*fcf5ef2aSThomas Huth /* nmacchws - nmacchws. */ 5541*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07); 5542*fcf5ef2aSThomas Huth /* nmacchwso - nmacchwso. */ 5543*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17); 5544*fcf5ef2aSThomas Huth /* nmachhw - nmachhw. */ 5545*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01); 5546*fcf5ef2aSThomas Huth /* nmachhwo - nmachhwo. */ 5547*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11); 5548*fcf5ef2aSThomas Huth /* nmachhws - nmachhws. */ 5549*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03); 5550*fcf5ef2aSThomas Huth /* nmachhwso - nmachhwso. */ 5551*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13); 5552*fcf5ef2aSThomas Huth /* nmaclhw - nmaclhw. */ 5553*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D); 5554*fcf5ef2aSThomas Huth /* nmaclhwo - nmaclhwo. */ 5555*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D); 5556*fcf5ef2aSThomas Huth /* nmaclhws - nmaclhws. */ 5557*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F); 5558*fcf5ef2aSThomas Huth /* nmaclhwso - nmaclhwso. */ 5559*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F); 5560*fcf5ef2aSThomas Huth 5561*fcf5ef2aSThomas Huth /* mulchw - mulchw. */ 5562*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulchw, 0x08, 0x05); 5563*fcf5ef2aSThomas Huth /* mulchwu - mulchwu. */ 5564*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulchwu, 0x08, 0x04); 5565*fcf5ef2aSThomas Huth /* mulhhw - mulhhw. */ 5566*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulhhw, 0x08, 0x01); 5567*fcf5ef2aSThomas Huth /* mulhhwu - mulhhwu. */ 5568*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00); 5569*fcf5ef2aSThomas Huth /* mullhw - mullhw. */ 5570*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mullhw, 0x08, 0x0D); 5571*fcf5ef2aSThomas Huth /* mullhwu - mullhwu. */ 5572*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C); 5573*fcf5ef2aSThomas Huth 5574*fcf5ef2aSThomas Huth /* mfdcr */ 5575*fcf5ef2aSThomas Huth static void gen_mfdcr(DisasContext *ctx) 5576*fcf5ef2aSThomas Huth { 5577*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5578*fcf5ef2aSThomas Huth GEN_PRIV; 5579*fcf5ef2aSThomas Huth #else 5580*fcf5ef2aSThomas Huth TCGv dcrn; 5581*fcf5ef2aSThomas Huth 5582*fcf5ef2aSThomas Huth CHK_SV; 5583*fcf5ef2aSThomas Huth dcrn = tcg_const_tl(SPR(ctx->opcode)); 5584*fcf5ef2aSThomas Huth gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, dcrn); 5585*fcf5ef2aSThomas Huth tcg_temp_free(dcrn); 5586*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5587*fcf5ef2aSThomas Huth } 5588*fcf5ef2aSThomas Huth 5589*fcf5ef2aSThomas Huth /* mtdcr */ 5590*fcf5ef2aSThomas Huth static void gen_mtdcr(DisasContext *ctx) 5591*fcf5ef2aSThomas Huth { 5592*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5593*fcf5ef2aSThomas Huth GEN_PRIV; 5594*fcf5ef2aSThomas Huth #else 5595*fcf5ef2aSThomas Huth TCGv dcrn; 5596*fcf5ef2aSThomas Huth 5597*fcf5ef2aSThomas Huth CHK_SV; 5598*fcf5ef2aSThomas Huth dcrn = tcg_const_tl(SPR(ctx->opcode)); 5599*fcf5ef2aSThomas Huth gen_helper_store_dcr(cpu_env, dcrn, cpu_gpr[rS(ctx->opcode)]); 5600*fcf5ef2aSThomas Huth tcg_temp_free(dcrn); 5601*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5602*fcf5ef2aSThomas Huth } 5603*fcf5ef2aSThomas Huth 5604*fcf5ef2aSThomas Huth /* mfdcrx */ 5605*fcf5ef2aSThomas Huth /* XXX: not implemented on 440 ? */ 5606*fcf5ef2aSThomas Huth static void gen_mfdcrx(DisasContext *ctx) 5607*fcf5ef2aSThomas Huth { 5608*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5609*fcf5ef2aSThomas Huth GEN_PRIV; 5610*fcf5ef2aSThomas Huth #else 5611*fcf5ef2aSThomas Huth CHK_SV; 5612*fcf5ef2aSThomas Huth gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, 5613*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)]); 5614*fcf5ef2aSThomas Huth /* Note: Rc update flag set leads to undefined state of Rc0 */ 5615*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5616*fcf5ef2aSThomas Huth } 5617*fcf5ef2aSThomas Huth 5618*fcf5ef2aSThomas Huth /* mtdcrx */ 5619*fcf5ef2aSThomas Huth /* XXX: not implemented on 440 ? */ 5620*fcf5ef2aSThomas Huth static void gen_mtdcrx(DisasContext *ctx) 5621*fcf5ef2aSThomas Huth { 5622*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5623*fcf5ef2aSThomas Huth GEN_PRIV; 5624*fcf5ef2aSThomas Huth #else 5625*fcf5ef2aSThomas Huth CHK_SV; 5626*fcf5ef2aSThomas Huth gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)], 5627*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)]); 5628*fcf5ef2aSThomas Huth /* Note: Rc update flag set leads to undefined state of Rc0 */ 5629*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5630*fcf5ef2aSThomas Huth } 5631*fcf5ef2aSThomas Huth 5632*fcf5ef2aSThomas Huth /* mfdcrux (PPC 460) : user-mode access to DCR */ 5633*fcf5ef2aSThomas Huth static void gen_mfdcrux(DisasContext *ctx) 5634*fcf5ef2aSThomas Huth { 5635*fcf5ef2aSThomas Huth gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_env, 5636*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)]); 5637*fcf5ef2aSThomas Huth /* Note: Rc update flag set leads to undefined state of Rc0 */ 5638*fcf5ef2aSThomas Huth } 5639*fcf5ef2aSThomas Huth 5640*fcf5ef2aSThomas Huth /* mtdcrux (PPC 460) : user-mode access to DCR */ 5641*fcf5ef2aSThomas Huth static void gen_mtdcrux(DisasContext *ctx) 5642*fcf5ef2aSThomas Huth { 5643*fcf5ef2aSThomas Huth gen_helper_store_dcr(cpu_env, cpu_gpr[rA(ctx->opcode)], 5644*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)]); 5645*fcf5ef2aSThomas Huth /* Note: Rc update flag set leads to undefined state of Rc0 */ 5646*fcf5ef2aSThomas Huth } 5647*fcf5ef2aSThomas Huth 5648*fcf5ef2aSThomas Huth /* dccci */ 5649*fcf5ef2aSThomas Huth static void gen_dccci(DisasContext *ctx) 5650*fcf5ef2aSThomas Huth { 5651*fcf5ef2aSThomas Huth CHK_SV; 5652*fcf5ef2aSThomas Huth /* interpreted as no-op */ 5653*fcf5ef2aSThomas Huth } 5654*fcf5ef2aSThomas Huth 5655*fcf5ef2aSThomas Huth /* dcread */ 5656*fcf5ef2aSThomas Huth static void gen_dcread(DisasContext *ctx) 5657*fcf5ef2aSThomas Huth { 5658*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5659*fcf5ef2aSThomas Huth GEN_PRIV; 5660*fcf5ef2aSThomas Huth #else 5661*fcf5ef2aSThomas Huth TCGv EA, val; 5662*fcf5ef2aSThomas Huth 5663*fcf5ef2aSThomas Huth CHK_SV; 5664*fcf5ef2aSThomas Huth gen_set_access_type(ctx, ACCESS_CACHE); 5665*fcf5ef2aSThomas Huth EA = tcg_temp_new(); 5666*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, EA); 5667*fcf5ef2aSThomas Huth val = tcg_temp_new(); 5668*fcf5ef2aSThomas Huth gen_qemu_ld32u(ctx, val, EA); 5669*fcf5ef2aSThomas Huth tcg_temp_free(val); 5670*fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA); 5671*fcf5ef2aSThomas Huth tcg_temp_free(EA); 5672*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5673*fcf5ef2aSThomas Huth } 5674*fcf5ef2aSThomas Huth 5675*fcf5ef2aSThomas Huth /* icbt */ 5676*fcf5ef2aSThomas Huth static void gen_icbt_40x(DisasContext *ctx) 5677*fcf5ef2aSThomas Huth { 5678*fcf5ef2aSThomas Huth /* interpreted as no-op */ 5679*fcf5ef2aSThomas Huth /* XXX: specification say this is treated as a load by the MMU 5680*fcf5ef2aSThomas Huth * but does not generate any exception 5681*fcf5ef2aSThomas Huth */ 5682*fcf5ef2aSThomas Huth } 5683*fcf5ef2aSThomas Huth 5684*fcf5ef2aSThomas Huth /* iccci */ 5685*fcf5ef2aSThomas Huth static void gen_iccci(DisasContext *ctx) 5686*fcf5ef2aSThomas Huth { 5687*fcf5ef2aSThomas Huth CHK_SV; 5688*fcf5ef2aSThomas Huth /* interpreted as no-op */ 5689*fcf5ef2aSThomas Huth } 5690*fcf5ef2aSThomas Huth 5691*fcf5ef2aSThomas Huth /* icread */ 5692*fcf5ef2aSThomas Huth static void gen_icread(DisasContext *ctx) 5693*fcf5ef2aSThomas Huth { 5694*fcf5ef2aSThomas Huth CHK_SV; 5695*fcf5ef2aSThomas Huth /* interpreted as no-op */ 5696*fcf5ef2aSThomas Huth } 5697*fcf5ef2aSThomas Huth 5698*fcf5ef2aSThomas Huth /* rfci (supervisor only) */ 5699*fcf5ef2aSThomas Huth static void gen_rfci_40x(DisasContext *ctx) 5700*fcf5ef2aSThomas Huth { 5701*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5702*fcf5ef2aSThomas Huth GEN_PRIV; 5703*fcf5ef2aSThomas Huth #else 5704*fcf5ef2aSThomas Huth CHK_SV; 5705*fcf5ef2aSThomas Huth /* Restore CPU state */ 5706*fcf5ef2aSThomas Huth gen_helper_40x_rfci(cpu_env); 5707*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 5708*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5709*fcf5ef2aSThomas Huth } 5710*fcf5ef2aSThomas Huth 5711*fcf5ef2aSThomas Huth static void gen_rfci(DisasContext *ctx) 5712*fcf5ef2aSThomas Huth { 5713*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5714*fcf5ef2aSThomas Huth GEN_PRIV; 5715*fcf5ef2aSThomas Huth #else 5716*fcf5ef2aSThomas Huth CHK_SV; 5717*fcf5ef2aSThomas Huth /* Restore CPU state */ 5718*fcf5ef2aSThomas Huth gen_helper_rfci(cpu_env); 5719*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 5720*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5721*fcf5ef2aSThomas Huth } 5722*fcf5ef2aSThomas Huth 5723*fcf5ef2aSThomas Huth /* BookE specific */ 5724*fcf5ef2aSThomas Huth 5725*fcf5ef2aSThomas Huth /* XXX: not implemented on 440 ? */ 5726*fcf5ef2aSThomas Huth static void gen_rfdi(DisasContext *ctx) 5727*fcf5ef2aSThomas Huth { 5728*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5729*fcf5ef2aSThomas Huth GEN_PRIV; 5730*fcf5ef2aSThomas Huth #else 5731*fcf5ef2aSThomas Huth CHK_SV; 5732*fcf5ef2aSThomas Huth /* Restore CPU state */ 5733*fcf5ef2aSThomas Huth gen_helper_rfdi(cpu_env); 5734*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 5735*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5736*fcf5ef2aSThomas Huth } 5737*fcf5ef2aSThomas Huth 5738*fcf5ef2aSThomas Huth /* XXX: not implemented on 440 ? */ 5739*fcf5ef2aSThomas Huth static void gen_rfmci(DisasContext *ctx) 5740*fcf5ef2aSThomas Huth { 5741*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5742*fcf5ef2aSThomas Huth GEN_PRIV; 5743*fcf5ef2aSThomas Huth #else 5744*fcf5ef2aSThomas Huth CHK_SV; 5745*fcf5ef2aSThomas Huth /* Restore CPU state */ 5746*fcf5ef2aSThomas Huth gen_helper_rfmci(cpu_env); 5747*fcf5ef2aSThomas Huth gen_sync_exception(ctx); 5748*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5749*fcf5ef2aSThomas Huth } 5750*fcf5ef2aSThomas Huth 5751*fcf5ef2aSThomas Huth /* TLB management - PowerPC 405 implementation */ 5752*fcf5ef2aSThomas Huth 5753*fcf5ef2aSThomas Huth /* tlbre */ 5754*fcf5ef2aSThomas Huth static void gen_tlbre_40x(DisasContext *ctx) 5755*fcf5ef2aSThomas Huth { 5756*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5757*fcf5ef2aSThomas Huth GEN_PRIV; 5758*fcf5ef2aSThomas Huth #else 5759*fcf5ef2aSThomas Huth CHK_SV; 5760*fcf5ef2aSThomas Huth switch (rB(ctx->opcode)) { 5761*fcf5ef2aSThomas Huth case 0: 5762*fcf5ef2aSThomas Huth gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_env, 5763*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)]); 5764*fcf5ef2aSThomas Huth break; 5765*fcf5ef2aSThomas Huth case 1: 5766*fcf5ef2aSThomas Huth gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_env, 5767*fcf5ef2aSThomas Huth cpu_gpr[rA(ctx->opcode)]); 5768*fcf5ef2aSThomas Huth break; 5769*fcf5ef2aSThomas Huth default: 5770*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5771*fcf5ef2aSThomas Huth break; 5772*fcf5ef2aSThomas Huth } 5773*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5774*fcf5ef2aSThomas Huth } 5775*fcf5ef2aSThomas Huth 5776*fcf5ef2aSThomas Huth /* tlbsx - tlbsx. */ 5777*fcf5ef2aSThomas Huth static void gen_tlbsx_40x(DisasContext *ctx) 5778*fcf5ef2aSThomas Huth { 5779*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5780*fcf5ef2aSThomas Huth GEN_PRIV; 5781*fcf5ef2aSThomas Huth #else 5782*fcf5ef2aSThomas Huth TCGv t0; 5783*fcf5ef2aSThomas Huth 5784*fcf5ef2aSThomas Huth CHK_SV; 5785*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5786*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5787*fcf5ef2aSThomas Huth gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 5788*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5789*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) { 5790*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 5791*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); 5792*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1); 5793*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); 5794*fcf5ef2aSThomas Huth gen_set_label(l1); 5795*fcf5ef2aSThomas Huth } 5796*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5797*fcf5ef2aSThomas Huth } 5798*fcf5ef2aSThomas Huth 5799*fcf5ef2aSThomas Huth /* tlbwe */ 5800*fcf5ef2aSThomas Huth static void gen_tlbwe_40x(DisasContext *ctx) 5801*fcf5ef2aSThomas Huth { 5802*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5803*fcf5ef2aSThomas Huth GEN_PRIV; 5804*fcf5ef2aSThomas Huth #else 5805*fcf5ef2aSThomas Huth CHK_SV; 5806*fcf5ef2aSThomas Huth 5807*fcf5ef2aSThomas Huth switch (rB(ctx->opcode)) { 5808*fcf5ef2aSThomas Huth case 0: 5809*fcf5ef2aSThomas Huth gen_helper_4xx_tlbwe_hi(cpu_env, cpu_gpr[rA(ctx->opcode)], 5810*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)]); 5811*fcf5ef2aSThomas Huth break; 5812*fcf5ef2aSThomas Huth case 1: 5813*fcf5ef2aSThomas Huth gen_helper_4xx_tlbwe_lo(cpu_env, cpu_gpr[rA(ctx->opcode)], 5814*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)]); 5815*fcf5ef2aSThomas Huth break; 5816*fcf5ef2aSThomas Huth default: 5817*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5818*fcf5ef2aSThomas Huth break; 5819*fcf5ef2aSThomas Huth } 5820*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5821*fcf5ef2aSThomas Huth } 5822*fcf5ef2aSThomas Huth 5823*fcf5ef2aSThomas Huth /* TLB management - PowerPC 440 implementation */ 5824*fcf5ef2aSThomas Huth 5825*fcf5ef2aSThomas Huth /* tlbre */ 5826*fcf5ef2aSThomas Huth static void gen_tlbre_440(DisasContext *ctx) 5827*fcf5ef2aSThomas Huth { 5828*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5829*fcf5ef2aSThomas Huth GEN_PRIV; 5830*fcf5ef2aSThomas Huth #else 5831*fcf5ef2aSThomas Huth CHK_SV; 5832*fcf5ef2aSThomas Huth 5833*fcf5ef2aSThomas Huth switch (rB(ctx->opcode)) { 5834*fcf5ef2aSThomas Huth case 0: 5835*fcf5ef2aSThomas Huth case 1: 5836*fcf5ef2aSThomas Huth case 2: 5837*fcf5ef2aSThomas Huth { 5838*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode)); 5839*fcf5ef2aSThomas Huth gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], cpu_env, 5840*fcf5ef2aSThomas Huth t0, cpu_gpr[rA(ctx->opcode)]); 5841*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 5842*fcf5ef2aSThomas Huth } 5843*fcf5ef2aSThomas Huth break; 5844*fcf5ef2aSThomas Huth default: 5845*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5846*fcf5ef2aSThomas Huth break; 5847*fcf5ef2aSThomas Huth } 5848*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5849*fcf5ef2aSThomas Huth } 5850*fcf5ef2aSThomas Huth 5851*fcf5ef2aSThomas Huth /* tlbsx - tlbsx. */ 5852*fcf5ef2aSThomas Huth static void gen_tlbsx_440(DisasContext *ctx) 5853*fcf5ef2aSThomas Huth { 5854*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5855*fcf5ef2aSThomas Huth GEN_PRIV; 5856*fcf5ef2aSThomas Huth #else 5857*fcf5ef2aSThomas Huth TCGv t0; 5858*fcf5ef2aSThomas Huth 5859*fcf5ef2aSThomas Huth CHK_SV; 5860*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5861*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5862*fcf5ef2aSThomas Huth gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); 5863*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5864*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) { 5865*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 5866*fcf5ef2aSThomas Huth tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); 5867*fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1); 5868*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); 5869*fcf5ef2aSThomas Huth gen_set_label(l1); 5870*fcf5ef2aSThomas Huth } 5871*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5872*fcf5ef2aSThomas Huth } 5873*fcf5ef2aSThomas Huth 5874*fcf5ef2aSThomas Huth /* tlbwe */ 5875*fcf5ef2aSThomas Huth static void gen_tlbwe_440(DisasContext *ctx) 5876*fcf5ef2aSThomas Huth { 5877*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5878*fcf5ef2aSThomas Huth GEN_PRIV; 5879*fcf5ef2aSThomas Huth #else 5880*fcf5ef2aSThomas Huth CHK_SV; 5881*fcf5ef2aSThomas Huth switch (rB(ctx->opcode)) { 5882*fcf5ef2aSThomas Huth case 0: 5883*fcf5ef2aSThomas Huth case 1: 5884*fcf5ef2aSThomas Huth case 2: 5885*fcf5ef2aSThomas Huth { 5886*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode)); 5887*fcf5ef2aSThomas Huth gen_helper_440_tlbwe(cpu_env, t0, cpu_gpr[rA(ctx->opcode)], 5888*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)]); 5889*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 5890*fcf5ef2aSThomas Huth } 5891*fcf5ef2aSThomas Huth break; 5892*fcf5ef2aSThomas Huth default: 5893*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5894*fcf5ef2aSThomas Huth break; 5895*fcf5ef2aSThomas Huth } 5896*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5897*fcf5ef2aSThomas Huth } 5898*fcf5ef2aSThomas Huth 5899*fcf5ef2aSThomas Huth /* TLB management - PowerPC BookE 2.06 implementation */ 5900*fcf5ef2aSThomas Huth 5901*fcf5ef2aSThomas Huth /* tlbre */ 5902*fcf5ef2aSThomas Huth static void gen_tlbre_booke206(DisasContext *ctx) 5903*fcf5ef2aSThomas Huth { 5904*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5905*fcf5ef2aSThomas Huth GEN_PRIV; 5906*fcf5ef2aSThomas Huth #else 5907*fcf5ef2aSThomas Huth CHK_SV; 5908*fcf5ef2aSThomas Huth gen_helper_booke206_tlbre(cpu_env); 5909*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5910*fcf5ef2aSThomas Huth } 5911*fcf5ef2aSThomas Huth 5912*fcf5ef2aSThomas Huth /* tlbsx - tlbsx. */ 5913*fcf5ef2aSThomas Huth static void gen_tlbsx_booke206(DisasContext *ctx) 5914*fcf5ef2aSThomas Huth { 5915*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5916*fcf5ef2aSThomas Huth GEN_PRIV; 5917*fcf5ef2aSThomas Huth #else 5918*fcf5ef2aSThomas Huth TCGv t0; 5919*fcf5ef2aSThomas Huth 5920*fcf5ef2aSThomas Huth CHK_SV; 5921*fcf5ef2aSThomas Huth if (rA(ctx->opcode)) { 5922*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5923*fcf5ef2aSThomas Huth tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]); 5924*fcf5ef2aSThomas Huth } else { 5925*fcf5ef2aSThomas Huth t0 = tcg_const_tl(0); 5926*fcf5ef2aSThomas Huth } 5927*fcf5ef2aSThomas Huth 5928*fcf5ef2aSThomas Huth tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]); 5929*fcf5ef2aSThomas Huth gen_helper_booke206_tlbsx(cpu_env, t0); 5930*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5931*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5932*fcf5ef2aSThomas Huth } 5933*fcf5ef2aSThomas Huth 5934*fcf5ef2aSThomas Huth /* tlbwe */ 5935*fcf5ef2aSThomas Huth static void gen_tlbwe_booke206(DisasContext *ctx) 5936*fcf5ef2aSThomas Huth { 5937*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5938*fcf5ef2aSThomas Huth GEN_PRIV; 5939*fcf5ef2aSThomas Huth #else 5940*fcf5ef2aSThomas Huth CHK_SV; 5941*fcf5ef2aSThomas Huth gen_helper_booke206_tlbwe(cpu_env); 5942*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5943*fcf5ef2aSThomas Huth } 5944*fcf5ef2aSThomas Huth 5945*fcf5ef2aSThomas Huth static void gen_tlbivax_booke206(DisasContext *ctx) 5946*fcf5ef2aSThomas Huth { 5947*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5948*fcf5ef2aSThomas Huth GEN_PRIV; 5949*fcf5ef2aSThomas Huth #else 5950*fcf5ef2aSThomas Huth TCGv t0; 5951*fcf5ef2aSThomas Huth 5952*fcf5ef2aSThomas Huth CHK_SV; 5953*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5954*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5955*fcf5ef2aSThomas Huth gen_helper_booke206_tlbivax(cpu_env, t0); 5956*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5957*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5958*fcf5ef2aSThomas Huth } 5959*fcf5ef2aSThomas Huth 5960*fcf5ef2aSThomas Huth static void gen_tlbilx_booke206(DisasContext *ctx) 5961*fcf5ef2aSThomas Huth { 5962*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5963*fcf5ef2aSThomas Huth GEN_PRIV; 5964*fcf5ef2aSThomas Huth #else 5965*fcf5ef2aSThomas Huth TCGv t0; 5966*fcf5ef2aSThomas Huth 5967*fcf5ef2aSThomas Huth CHK_SV; 5968*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 5969*fcf5ef2aSThomas Huth gen_addr_reg_index(ctx, t0); 5970*fcf5ef2aSThomas Huth 5971*fcf5ef2aSThomas Huth switch((ctx->opcode >> 21) & 0x3) { 5972*fcf5ef2aSThomas Huth case 0: 5973*fcf5ef2aSThomas Huth gen_helper_booke206_tlbilx0(cpu_env, t0); 5974*fcf5ef2aSThomas Huth break; 5975*fcf5ef2aSThomas Huth case 1: 5976*fcf5ef2aSThomas Huth gen_helper_booke206_tlbilx1(cpu_env, t0); 5977*fcf5ef2aSThomas Huth break; 5978*fcf5ef2aSThomas Huth case 3: 5979*fcf5ef2aSThomas Huth gen_helper_booke206_tlbilx3(cpu_env, t0); 5980*fcf5ef2aSThomas Huth break; 5981*fcf5ef2aSThomas Huth default: 5982*fcf5ef2aSThomas Huth gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 5983*fcf5ef2aSThomas Huth break; 5984*fcf5ef2aSThomas Huth } 5985*fcf5ef2aSThomas Huth 5986*fcf5ef2aSThomas Huth tcg_temp_free(t0); 5987*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 5988*fcf5ef2aSThomas Huth } 5989*fcf5ef2aSThomas Huth 5990*fcf5ef2aSThomas Huth 5991*fcf5ef2aSThomas Huth /* wrtee */ 5992*fcf5ef2aSThomas Huth static void gen_wrtee(DisasContext *ctx) 5993*fcf5ef2aSThomas Huth { 5994*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 5995*fcf5ef2aSThomas Huth GEN_PRIV; 5996*fcf5ef2aSThomas Huth #else 5997*fcf5ef2aSThomas Huth TCGv t0; 5998*fcf5ef2aSThomas Huth 5999*fcf5ef2aSThomas Huth CHK_SV; 6000*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 6001*fcf5ef2aSThomas Huth tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE)); 6002*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE)); 6003*fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_msr, cpu_msr, t0); 6004*fcf5ef2aSThomas Huth tcg_temp_free(t0); 6005*fcf5ef2aSThomas Huth /* Stop translation to have a chance to raise an exception 6006*fcf5ef2aSThomas Huth * if we just set msr_ee to 1 6007*fcf5ef2aSThomas Huth */ 6008*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 6009*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 6010*fcf5ef2aSThomas Huth } 6011*fcf5ef2aSThomas Huth 6012*fcf5ef2aSThomas Huth /* wrteei */ 6013*fcf5ef2aSThomas Huth static void gen_wrteei(DisasContext *ctx) 6014*fcf5ef2aSThomas Huth { 6015*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 6016*fcf5ef2aSThomas Huth GEN_PRIV; 6017*fcf5ef2aSThomas Huth #else 6018*fcf5ef2aSThomas Huth CHK_SV; 6019*fcf5ef2aSThomas Huth if (ctx->opcode & 0x00008000) { 6020*fcf5ef2aSThomas Huth tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE)); 6021*fcf5ef2aSThomas Huth /* Stop translation to have a chance to raise an exception */ 6022*fcf5ef2aSThomas Huth gen_stop_exception(ctx); 6023*fcf5ef2aSThomas Huth } else { 6024*fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE)); 6025*fcf5ef2aSThomas Huth } 6026*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 6027*fcf5ef2aSThomas Huth } 6028*fcf5ef2aSThomas Huth 6029*fcf5ef2aSThomas Huth /* PowerPC 440 specific instructions */ 6030*fcf5ef2aSThomas Huth 6031*fcf5ef2aSThomas Huth /* dlmzb */ 6032*fcf5ef2aSThomas Huth static void gen_dlmzb(DisasContext *ctx) 6033*fcf5ef2aSThomas Huth { 6034*fcf5ef2aSThomas Huth TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode)); 6035*fcf5ef2aSThomas Huth gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_env, 6036*fcf5ef2aSThomas Huth cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); 6037*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 6038*fcf5ef2aSThomas Huth } 6039*fcf5ef2aSThomas Huth 6040*fcf5ef2aSThomas Huth /* mbar replaces eieio on 440 */ 6041*fcf5ef2aSThomas Huth static void gen_mbar(DisasContext *ctx) 6042*fcf5ef2aSThomas Huth { 6043*fcf5ef2aSThomas Huth /* interpreted as no-op */ 6044*fcf5ef2aSThomas Huth } 6045*fcf5ef2aSThomas Huth 6046*fcf5ef2aSThomas Huth /* msync replaces sync on 440 */ 6047*fcf5ef2aSThomas Huth static void gen_msync_4xx(DisasContext *ctx) 6048*fcf5ef2aSThomas Huth { 6049*fcf5ef2aSThomas Huth /* interpreted as no-op */ 6050*fcf5ef2aSThomas Huth } 6051*fcf5ef2aSThomas Huth 6052*fcf5ef2aSThomas Huth /* icbt */ 6053*fcf5ef2aSThomas Huth static void gen_icbt_440(DisasContext *ctx) 6054*fcf5ef2aSThomas Huth { 6055*fcf5ef2aSThomas Huth /* interpreted as no-op */ 6056*fcf5ef2aSThomas Huth /* XXX: specification say this is treated as a load by the MMU 6057*fcf5ef2aSThomas Huth * but does not generate any exception 6058*fcf5ef2aSThomas Huth */ 6059*fcf5ef2aSThomas Huth } 6060*fcf5ef2aSThomas Huth 6061*fcf5ef2aSThomas Huth /* Embedded.Processor Control */ 6062*fcf5ef2aSThomas Huth 6063*fcf5ef2aSThomas Huth static void gen_msgclr(DisasContext *ctx) 6064*fcf5ef2aSThomas Huth { 6065*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 6066*fcf5ef2aSThomas Huth GEN_PRIV; 6067*fcf5ef2aSThomas Huth #else 6068*fcf5ef2aSThomas Huth CHK_SV; 6069*fcf5ef2aSThomas Huth gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]); 6070*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 6071*fcf5ef2aSThomas Huth } 6072*fcf5ef2aSThomas Huth 6073*fcf5ef2aSThomas Huth static void gen_msgsnd(DisasContext *ctx) 6074*fcf5ef2aSThomas Huth { 6075*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 6076*fcf5ef2aSThomas Huth GEN_PRIV; 6077*fcf5ef2aSThomas Huth #else 6078*fcf5ef2aSThomas Huth CHK_SV; 6079*fcf5ef2aSThomas Huth gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]); 6080*fcf5ef2aSThomas Huth #endif /* defined(CONFIG_USER_ONLY) */ 6081*fcf5ef2aSThomas Huth } 6082*fcf5ef2aSThomas Huth 6083*fcf5ef2aSThomas Huth 6084*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6085*fcf5ef2aSThomas Huth static void gen_maddld(DisasContext *ctx) 6086*fcf5ef2aSThomas Huth { 6087*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 6088*fcf5ef2aSThomas Huth 6089*fcf5ef2aSThomas Huth tcg_gen_mul_i64(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 6090*fcf5ef2aSThomas Huth tcg_gen_add_i64(cpu_gpr[rD(ctx->opcode)], t1, cpu_gpr[rC(ctx->opcode)]); 6091*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 6092*fcf5ef2aSThomas Huth } 6093*fcf5ef2aSThomas Huth 6094*fcf5ef2aSThomas Huth /* maddhd maddhdu */ 6095*fcf5ef2aSThomas Huth static void gen_maddhd_maddhdu(DisasContext *ctx) 6096*fcf5ef2aSThomas Huth { 6097*fcf5ef2aSThomas Huth TCGv_i64 lo = tcg_temp_new_i64(); 6098*fcf5ef2aSThomas Huth TCGv_i64 hi = tcg_temp_new_i64(); 6099*fcf5ef2aSThomas Huth TCGv_i64 t1 = tcg_temp_new_i64(); 6100*fcf5ef2aSThomas Huth 6101*fcf5ef2aSThomas Huth if (Rc(ctx->opcode)) { 6102*fcf5ef2aSThomas Huth tcg_gen_mulu2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)], 6103*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 6104*fcf5ef2aSThomas Huth tcg_gen_movi_i64(t1, 0); 6105*fcf5ef2aSThomas Huth } else { 6106*fcf5ef2aSThomas Huth tcg_gen_muls2_i64(lo, hi, cpu_gpr[rA(ctx->opcode)], 6107*fcf5ef2aSThomas Huth cpu_gpr[rB(ctx->opcode)]); 6108*fcf5ef2aSThomas Huth tcg_gen_sari_i64(t1, cpu_gpr[rC(ctx->opcode)], 63); 6109*fcf5ef2aSThomas Huth } 6110*fcf5ef2aSThomas Huth tcg_gen_add2_i64(t1, cpu_gpr[rD(ctx->opcode)], lo, hi, 6111*fcf5ef2aSThomas Huth cpu_gpr[rC(ctx->opcode)], t1); 6112*fcf5ef2aSThomas Huth tcg_temp_free_i64(lo); 6113*fcf5ef2aSThomas Huth tcg_temp_free_i64(hi); 6114*fcf5ef2aSThomas Huth tcg_temp_free_i64(t1); 6115*fcf5ef2aSThomas Huth } 6116*fcf5ef2aSThomas Huth #endif /* defined(TARGET_PPC64) */ 6117*fcf5ef2aSThomas Huth 6118*fcf5ef2aSThomas Huth static void gen_tbegin(DisasContext *ctx) 6119*fcf5ef2aSThomas Huth { 6120*fcf5ef2aSThomas Huth if (unlikely(!ctx->tm_enabled)) { 6121*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); 6122*fcf5ef2aSThomas Huth return; 6123*fcf5ef2aSThomas Huth } 6124*fcf5ef2aSThomas Huth gen_helper_tbegin(cpu_env); 6125*fcf5ef2aSThomas Huth } 6126*fcf5ef2aSThomas Huth 6127*fcf5ef2aSThomas Huth #define GEN_TM_NOOP(name) \ 6128*fcf5ef2aSThomas Huth static inline void gen_##name(DisasContext *ctx) \ 6129*fcf5ef2aSThomas Huth { \ 6130*fcf5ef2aSThomas Huth if (unlikely(!ctx->tm_enabled)) { \ 6131*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \ 6132*fcf5ef2aSThomas Huth return; \ 6133*fcf5ef2aSThomas Huth } \ 6134*fcf5ef2aSThomas Huth /* Because tbegin always fails in QEMU, these user \ 6135*fcf5ef2aSThomas Huth * space instructions all have a simple implementation: \ 6136*fcf5ef2aSThomas Huth * \ 6137*fcf5ef2aSThomas Huth * CR[0] = 0b0 || MSR[TS] || 0b0 \ 6138*fcf5ef2aSThomas Huth * = 0b0 || 0b00 || 0b0 \ 6139*fcf5ef2aSThomas Huth */ \ 6140*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_crf[0], 0); \ 6141*fcf5ef2aSThomas Huth } 6142*fcf5ef2aSThomas Huth 6143*fcf5ef2aSThomas Huth GEN_TM_NOOP(tend); 6144*fcf5ef2aSThomas Huth GEN_TM_NOOP(tabort); 6145*fcf5ef2aSThomas Huth GEN_TM_NOOP(tabortwc); 6146*fcf5ef2aSThomas Huth GEN_TM_NOOP(tabortwci); 6147*fcf5ef2aSThomas Huth GEN_TM_NOOP(tabortdc); 6148*fcf5ef2aSThomas Huth GEN_TM_NOOP(tabortdci); 6149*fcf5ef2aSThomas Huth GEN_TM_NOOP(tsr); 6150*fcf5ef2aSThomas Huth 6151*fcf5ef2aSThomas Huth static void gen_tcheck(DisasContext *ctx) 6152*fcf5ef2aSThomas Huth { 6153*fcf5ef2aSThomas Huth if (unlikely(!ctx->tm_enabled)) { 6154*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); 6155*fcf5ef2aSThomas Huth return; 6156*fcf5ef2aSThomas Huth } 6157*fcf5ef2aSThomas Huth /* Because tbegin always fails, the tcheck implementation 6158*fcf5ef2aSThomas Huth * is simple: 6159*fcf5ef2aSThomas Huth * 6160*fcf5ef2aSThomas Huth * CR[CRF] = TDOOMED || MSR[TS] || 0b0 6161*fcf5ef2aSThomas Huth * = 0b1 || 0b00 || 0b0 6162*fcf5ef2aSThomas Huth */ 6163*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8); 6164*fcf5ef2aSThomas Huth } 6165*fcf5ef2aSThomas Huth 6166*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 6167*fcf5ef2aSThomas Huth #define GEN_TM_PRIV_NOOP(name) \ 6168*fcf5ef2aSThomas Huth static inline void gen_##name(DisasContext *ctx) \ 6169*fcf5ef2aSThomas Huth { \ 6170*fcf5ef2aSThomas Huth gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); \ 6171*fcf5ef2aSThomas Huth } 6172*fcf5ef2aSThomas Huth 6173*fcf5ef2aSThomas Huth #else 6174*fcf5ef2aSThomas Huth 6175*fcf5ef2aSThomas Huth #define GEN_TM_PRIV_NOOP(name) \ 6176*fcf5ef2aSThomas Huth static inline void gen_##name(DisasContext *ctx) \ 6177*fcf5ef2aSThomas Huth { \ 6178*fcf5ef2aSThomas Huth CHK_SV; \ 6179*fcf5ef2aSThomas Huth if (unlikely(!ctx->tm_enabled)) { \ 6180*fcf5ef2aSThomas Huth gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \ 6181*fcf5ef2aSThomas Huth return; \ 6182*fcf5ef2aSThomas Huth } \ 6183*fcf5ef2aSThomas Huth /* Because tbegin always fails, the implementation is \ 6184*fcf5ef2aSThomas Huth * simple: \ 6185*fcf5ef2aSThomas Huth * \ 6186*fcf5ef2aSThomas Huth * CR[0] = 0b0 || MSR[TS] || 0b0 \ 6187*fcf5ef2aSThomas Huth * = 0b0 || 0b00 | 0b0 \ 6188*fcf5ef2aSThomas Huth */ \ 6189*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_crf[0], 0); \ 6190*fcf5ef2aSThomas Huth } 6191*fcf5ef2aSThomas Huth 6192*fcf5ef2aSThomas Huth #endif 6193*fcf5ef2aSThomas Huth 6194*fcf5ef2aSThomas Huth GEN_TM_PRIV_NOOP(treclaim); 6195*fcf5ef2aSThomas Huth GEN_TM_PRIV_NOOP(trechkpt); 6196*fcf5ef2aSThomas Huth 6197*fcf5ef2aSThomas Huth #include "translate/fp-impl.inc.c" 6198*fcf5ef2aSThomas Huth 6199*fcf5ef2aSThomas Huth #include "translate/vmx-impl.inc.c" 6200*fcf5ef2aSThomas Huth 6201*fcf5ef2aSThomas Huth #include "translate/vsx-impl.inc.c" 6202*fcf5ef2aSThomas Huth 6203*fcf5ef2aSThomas Huth #include "translate/dfp-impl.inc.c" 6204*fcf5ef2aSThomas Huth 6205*fcf5ef2aSThomas Huth #include "translate/spe-impl.inc.c" 6206*fcf5ef2aSThomas Huth 6207*fcf5ef2aSThomas Huth static opcode_t opcodes[] = { 6208*fcf5ef2aSThomas Huth GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE), 6209*fcf5ef2aSThomas Huth GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER), 6210*fcf5ef2aSThomas Huth GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER), 6211*fcf5ef2aSThomas Huth GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400001, PPC_INTEGER), 6212*fcf5ef2aSThomas Huth GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER), 6213*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6214*fcf5ef2aSThomas Huth GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300), 6215*fcf5ef2aSThomas Huth #endif 6216*fcf5ef2aSThomas Huth GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205), 6217*fcf5ef2aSThomas Huth GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300), 6218*fcf5ef2aSThomas Huth GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL), 6219*fcf5ef2aSThomas Huth GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6220*fcf5ef2aSThomas Huth GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6221*fcf5ef2aSThomas Huth GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6222*fcf5ef2aSThomas Huth GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6223*fcf5ef2aSThomas Huth GEN_HANDLER_E(addpcis, 0x13, 0x2, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300), 6224*fcf5ef2aSThomas Huth GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER), 6225*fcf5ef2aSThomas Huth GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER), 6226*fcf5ef2aSThomas Huth GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER), 6227*fcf5ef2aSThomas Huth GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER), 6228*fcf5ef2aSThomas Huth GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6229*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6230*fcf5ef2aSThomas Huth GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B), 6231*fcf5ef2aSThomas Huth #endif 6232*fcf5ef2aSThomas Huth GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER), 6233*fcf5ef2aSThomas Huth GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER), 6234*fcf5ef2aSThomas Huth GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6235*fcf5ef2aSThomas Huth GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6236*fcf5ef2aSThomas Huth GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6237*fcf5ef2aSThomas Huth GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER), 6238*fcf5ef2aSThomas Huth GEN_HANDLER_E(cnttzw, 0x1F, 0x1A, 0x10, 0x00000000, PPC_NONE, PPC2_ISA300), 6239*fcf5ef2aSThomas Huth GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER), 6240*fcf5ef2aSThomas Huth GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER), 6241*fcf5ef2aSThomas Huth GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6242*fcf5ef2aSThomas Huth GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6243*fcf5ef2aSThomas Huth GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6244*fcf5ef2aSThomas Huth GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6245*fcf5ef2aSThomas Huth GEN_HANDLER(popcntb, 0x1F, 0x1A, 0x03, 0x0000F801, PPC_POPCNTB), 6246*fcf5ef2aSThomas Huth GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD), 6247*fcf5ef2aSThomas Huth GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205), 6248*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6249*fcf5ef2aSThomas Huth GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD), 6250*fcf5ef2aSThomas Huth GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B), 6251*fcf5ef2aSThomas Huth GEN_HANDLER_E(cnttzd, 0x1F, 0x1A, 0x11, 0x00000000, PPC_NONE, PPC2_ISA300), 6252*fcf5ef2aSThomas Huth GEN_HANDLER_E(darn, 0x1F, 0x13, 0x17, 0x001CF801, PPC_NONE, PPC2_ISA300), 6253*fcf5ef2aSThomas Huth GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205), 6254*fcf5ef2aSThomas Huth GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_PERM_ISA206), 6255*fcf5ef2aSThomas Huth #endif 6256*fcf5ef2aSThomas Huth GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6257*fcf5ef2aSThomas Huth GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6258*fcf5ef2aSThomas Huth GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6259*fcf5ef2aSThomas Huth GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER), 6260*fcf5ef2aSThomas Huth GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER), 6261*fcf5ef2aSThomas Huth GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER), 6262*fcf5ef2aSThomas Huth GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER), 6263*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6264*fcf5ef2aSThomas Huth GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B), 6265*fcf5ef2aSThomas Huth GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B), 6266*fcf5ef2aSThomas Huth GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B), 6267*fcf5ef2aSThomas Huth GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B), 6268*fcf5ef2aSThomas Huth GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B), 6269*fcf5ef2aSThomas Huth GEN_HANDLER2_E(extswsli0, "extswsli", 0x1F, 0x1A, 0x1B, 0x00000000, 6270*fcf5ef2aSThomas Huth PPC_NONE, PPC2_ISA300), 6271*fcf5ef2aSThomas Huth GEN_HANDLER2_E(extswsli1, "extswsli", 0x1F, 0x1B, 0x1B, 0x00000000, 6272*fcf5ef2aSThomas Huth PPC_NONE, PPC2_ISA300), 6273*fcf5ef2aSThomas Huth #endif 6274*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6275*fcf5ef2aSThomas Huth GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B), 6276*fcf5ef2aSThomas Huth GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX), 6277*fcf5ef2aSThomas Huth GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B), 6278*fcf5ef2aSThomas Huth #endif 6279*fcf5ef2aSThomas Huth GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6280*fcf5ef2aSThomas Huth GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER), 6281*fcf5ef2aSThomas Huth GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING), 6282*fcf5ef2aSThomas Huth GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING), 6283*fcf5ef2aSThomas Huth GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING), 6284*fcf5ef2aSThomas Huth GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING), 6285*fcf5ef2aSThomas Huth GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO), 6286*fcf5ef2aSThomas Huth GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM), 6287*fcf5ef2aSThomas Huth GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206), 6288*fcf5ef2aSThomas Huth GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206), 6289*fcf5ef2aSThomas Huth GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES), 6290*fcf5ef2aSThomas Huth GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0, PPC_NONE, PPC2_ATOMIC_ISA206), 6291*fcf5ef2aSThomas Huth GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0, PPC_NONE, PPC2_ATOMIC_ISA206), 6292*fcf5ef2aSThomas Huth GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES), 6293*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6294*fcf5ef2aSThomas Huth GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B), 6295*fcf5ef2aSThomas Huth GEN_HANDLER_E(lqarx, 0x1F, 0x14, 0x08, 0, PPC_NONE, PPC2_LSQ_ISA207), 6296*fcf5ef2aSThomas Huth GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B), 6297*fcf5ef2aSThomas Huth GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207), 6298*fcf5ef2aSThomas Huth #endif 6299*fcf5ef2aSThomas Huth GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC), 6300*fcf5ef2aSThomas Huth GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT), 6301*fcf5ef2aSThomas Huth GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW), 6302*fcf5ef2aSThomas Huth GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW), 6303*fcf5ef2aSThomas Huth GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW), 6304*fcf5ef2aSThomas Huth GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW), 6305*fcf5ef2aSThomas Huth GEN_HANDLER_E(bctar, 0x13, 0x10, 0x11, 0x0000E000, PPC_NONE, PPC2_BCTAR_ISA207), 6306*fcf5ef2aSThomas Huth GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER), 6307*fcf5ef2aSThomas Huth GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW), 6308*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6309*fcf5ef2aSThomas Huth GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B), 6310*fcf5ef2aSThomas Huth GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), 6311*fcf5ef2aSThomas Huth GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), 6312*fcf5ef2aSThomas Huth GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), 6313*fcf5ef2aSThomas Huth GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), 6314*fcf5ef2aSThomas Huth GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H), 6315*fcf5ef2aSThomas Huth #endif 6316*fcf5ef2aSThomas Huth GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW), 6317*fcf5ef2aSThomas Huth GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW), 6318*fcf5ef2aSThomas Huth GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW), 6319*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6320*fcf5ef2aSThomas Huth GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B), 6321*fcf5ef2aSThomas Huth GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B), 6322*fcf5ef2aSThomas Huth #endif 6323*fcf5ef2aSThomas Huth GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC), 6324*fcf5ef2aSThomas Huth GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC), 6325*fcf5ef2aSThomas Huth GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC), 6326*fcf5ef2aSThomas Huth GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC), 6327*fcf5ef2aSThomas Huth GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB), 6328*fcf5ef2aSThomas Huth GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC), 6329*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6330*fcf5ef2aSThomas Huth GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B), 6331*fcf5ef2aSThomas Huth GEN_HANDLER_E(setb, 0x1F, 0x00, 0x04, 0x0003F801, PPC_NONE, PPC2_ISA300), 6332*fcf5ef2aSThomas Huth #endif 6333*fcf5ef2aSThomas Huth GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC), 6334*fcf5ef2aSThomas Huth GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC), 6335*fcf5ef2aSThomas Huth GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE), 6336*fcf5ef2aSThomas Huth GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE), 6337*fcf5ef2aSThomas Huth GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE), 6338*fcf5ef2aSThomas Huth GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE), 6339*fcf5ef2aSThomas Huth GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE), 6340*fcf5ef2aSThomas Huth GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206), 6341*fcf5ef2aSThomas Huth GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ), 6342*fcf5ef2aSThomas Huth GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC), 6343*fcf5ef2aSThomas Huth GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC), 6344*fcf5ef2aSThomas Huth GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC), 6345*fcf5ef2aSThomas Huth GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI), 6346*fcf5ef2aSThomas Huth GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA), 6347*fcf5ef2aSThomas Huth GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT), 6348*fcf5ef2aSThomas Huth GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT), 6349*fcf5ef2aSThomas Huth GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT), 6350*fcf5ef2aSThomas Huth GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT), 6351*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6352*fcf5ef2aSThomas Huth GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B), 6353*fcf5ef2aSThomas Huth GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001, 6354*fcf5ef2aSThomas Huth PPC_SEGMENT_64B), 6355*fcf5ef2aSThomas Huth GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B), 6356*fcf5ef2aSThomas Huth GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, 6357*fcf5ef2aSThomas Huth PPC_SEGMENT_64B), 6358*fcf5ef2aSThomas Huth GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B), 6359*fcf5ef2aSThomas Huth GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B), 6360*fcf5ef2aSThomas Huth GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B), 6361*fcf5ef2aSThomas Huth GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B), 6362*fcf5ef2aSThomas Huth #endif 6363*fcf5ef2aSThomas Huth GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA), 6364*fcf5ef2aSThomas Huth /* XXX Those instructions will need to be handled differently for 6365*fcf5ef2aSThomas Huth * different ISA versions */ 6366*fcf5ef2aSThomas Huth GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE), 6367*fcf5ef2aSThomas Huth GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE), 6368*fcf5ef2aSThomas Huth GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC), 6369*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6370*fcf5ef2aSThomas Huth GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x031FFC01, PPC_SLBI), 6371*fcf5ef2aSThomas Huth GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI), 6372*fcf5ef2aSThomas Huth #endif 6373*fcf5ef2aSThomas Huth GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN), 6374*fcf5ef2aSThomas Huth GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN), 6375*fcf5ef2aSThomas Huth GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR), 6376*fcf5ef2aSThomas Huth GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR), 6377*fcf5ef2aSThomas Huth GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR), 6378*fcf5ef2aSThomas Huth GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR), 6379*fcf5ef2aSThomas Huth GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR), 6380*fcf5ef2aSThomas Huth GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR), 6381*fcf5ef2aSThomas Huth GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR), 6382*fcf5ef2aSThomas Huth GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR), 6383*fcf5ef2aSThomas Huth GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR), 6384*fcf5ef2aSThomas Huth GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR), 6385*fcf5ef2aSThomas Huth GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR), 6386*fcf5ef2aSThomas Huth GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR), 6387*fcf5ef2aSThomas Huth GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR), 6388*fcf5ef2aSThomas Huth GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR), 6389*fcf5ef2aSThomas Huth GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR), 6390*fcf5ef2aSThomas Huth GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR), 6391*fcf5ef2aSThomas Huth GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR), 6392*fcf5ef2aSThomas Huth GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR), 6393*fcf5ef2aSThomas Huth GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR), 6394*fcf5ef2aSThomas Huth GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR), 6395*fcf5ef2aSThomas Huth GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR), 6396*fcf5ef2aSThomas Huth GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR), 6397*fcf5ef2aSThomas Huth GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR), 6398*fcf5ef2aSThomas Huth GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR), 6399*fcf5ef2aSThomas Huth GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR), 6400*fcf5ef2aSThomas Huth GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR), 6401*fcf5ef2aSThomas Huth GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR), 6402*fcf5ef2aSThomas Huth GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR), 6403*fcf5ef2aSThomas Huth GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR), 6404*fcf5ef2aSThomas Huth GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR), 6405*fcf5ef2aSThomas Huth GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR), 6406*fcf5ef2aSThomas Huth GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR), 6407*fcf5ef2aSThomas Huth GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR), 6408*fcf5ef2aSThomas Huth GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR), 6409*fcf5ef2aSThomas Huth GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC), 6410*fcf5ef2aSThomas Huth GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC), 6411*fcf5ef2aSThomas Huth GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC), 6412*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB), 6413*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB), 6414*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB), 6415*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB), 6416*fcf5ef2aSThomas Huth GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER), 6417*fcf5ef2aSThomas Huth GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER), 6418*fcf5ef2aSThomas Huth GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER), 6419*fcf5ef2aSThomas Huth GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER), 6420*fcf5ef2aSThomas Huth GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER), 6421*fcf5ef2aSThomas Huth GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER), 6422*fcf5ef2aSThomas Huth GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2), 6423*fcf5ef2aSThomas Huth GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2), 6424*fcf5ef2aSThomas Huth GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2), 6425*fcf5ef2aSThomas Huth GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2), 6426*fcf5ef2aSThomas Huth GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2), 6427*fcf5ef2aSThomas Huth GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2), 6428*fcf5ef2aSThomas Huth GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2), 6429*fcf5ef2aSThomas Huth GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2), 6430*fcf5ef2aSThomas Huth GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI), 6431*fcf5ef2aSThomas Huth GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA), 6432*fcf5ef2aSThomas Huth GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR), 6433*fcf5ef2aSThomas Huth GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR), 6434*fcf5ef2aSThomas Huth GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX), 6435*fcf5ef2aSThomas Huth GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX), 6436*fcf5ef2aSThomas Huth GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX), 6437*fcf5ef2aSThomas Huth GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX), 6438*fcf5ef2aSThomas Huth GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON), 6439*fcf5ef2aSThomas Huth GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON), 6440*fcf5ef2aSThomas Huth GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT), 6441*fcf5ef2aSThomas Huth GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON), 6442*fcf5ef2aSThomas Huth GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON), 6443*fcf5ef2aSThomas Huth GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP), 6444*fcf5ef2aSThomas Huth GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206), 6445*fcf5ef2aSThomas Huth GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI), 6446*fcf5ef2aSThomas Huth GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI), 6447*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB), 6448*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB), 6449*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB), 6450*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE), 6451*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE), 6452*fcf5ef2aSThomas Huth GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE), 6453*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, 6454*fcf5ef2aSThomas Huth PPC_NONE, PPC2_BOOKE206), 6455*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, 6456*fcf5ef2aSThomas Huth PPC_NONE, PPC2_BOOKE206), 6457*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, 6458*fcf5ef2aSThomas Huth PPC_NONE, PPC2_BOOKE206), 6459*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001, 6460*fcf5ef2aSThomas Huth PPC_NONE, PPC2_BOOKE206), 6461*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001, 6462*fcf5ef2aSThomas Huth PPC_NONE, PPC2_BOOKE206), 6463*fcf5ef2aSThomas Huth GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001, 6464*fcf5ef2aSThomas Huth PPC_NONE, PPC2_PRCNTL), 6465*fcf5ef2aSThomas Huth GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001, 6466*fcf5ef2aSThomas Huth PPC_NONE, PPC2_PRCNTL), 6467*fcf5ef2aSThomas Huth GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE), 6468*fcf5ef2aSThomas Huth GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE), 6469*fcf5ef2aSThomas Huth GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC), 6470*fcf5ef2aSThomas Huth GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, 6471*fcf5ef2aSThomas Huth PPC_BOOKE, PPC2_BOOKE206), 6472*fcf5ef2aSThomas Huth GEN_HANDLER(msync_4xx, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE), 6473*fcf5ef2aSThomas Huth GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, 6474*fcf5ef2aSThomas Huth PPC_BOOKE, PPC2_BOOKE206), 6475*fcf5ef2aSThomas Huth GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC), 6476*fcf5ef2aSThomas Huth GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC), 6477*fcf5ef2aSThomas Huth GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC), 6478*fcf5ef2aSThomas Huth GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC), 6479*fcf5ef2aSThomas Huth GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC), 6480*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6481*fcf5ef2aSThomas Huth GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE, 6482*fcf5ef2aSThomas Huth PPC2_ISA300), 6483*fcf5ef2aSThomas Huth GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300), 6484*fcf5ef2aSThomas Huth #endif 6485*fcf5ef2aSThomas Huth 6486*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_ADD 6487*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_ADD_CONST 6488*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \ 6489*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER), 6490*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \ 6491*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov) \ 6492*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER), 6493*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0) 6494*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1) 6495*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0) 6496*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1) 6497*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0) 6498*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1) 6499*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0) 6500*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1) 6501*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0) 6502*fcf5ef2aSThomas Huth GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1) 6503*fcf5ef2aSThomas Huth 6504*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_DIVW 6505*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \ 6506*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER) 6507*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0), 6508*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1), 6509*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0), 6510*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1), 6511*fcf5ef2aSThomas Huth GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206), 6512*fcf5ef2aSThomas Huth GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206), 6513*fcf5ef2aSThomas Huth GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206), 6514*fcf5ef2aSThomas Huth GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206), 6515*fcf5ef2aSThomas Huth GEN_HANDLER_E(modsw, 0x1F, 0x0B, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300), 6516*fcf5ef2aSThomas Huth GEN_HANDLER_E(moduw, 0x1F, 0x0B, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300), 6517*fcf5ef2aSThomas Huth 6518*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6519*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_DIVD 6520*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \ 6521*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B) 6522*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0), 6523*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1), 6524*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0), 6525*fcf5ef2aSThomas Huth GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1), 6526*fcf5ef2aSThomas Huth 6527*fcf5ef2aSThomas Huth GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206), 6528*fcf5ef2aSThomas Huth GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206), 6529*fcf5ef2aSThomas Huth GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206), 6530*fcf5ef2aSThomas Huth GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206), 6531*fcf5ef2aSThomas Huth GEN_HANDLER_E(modsd, 0x1F, 0x09, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300), 6532*fcf5ef2aSThomas Huth GEN_HANDLER_E(modud, 0x1F, 0x09, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300), 6533*fcf5ef2aSThomas Huth 6534*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_MUL_HELPER 6535*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_MUL_HELPER(name, opc3) \ 6536*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B) 6537*fcf5ef2aSThomas Huth GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00), 6538*fcf5ef2aSThomas Huth GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02), 6539*fcf5ef2aSThomas Huth GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17), 6540*fcf5ef2aSThomas Huth #endif 6541*fcf5ef2aSThomas Huth 6542*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_SUBF 6543*fcf5ef2aSThomas Huth #undef GEN_INT_ARITH_SUBF_CONST 6544*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \ 6545*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER), 6546*fcf5ef2aSThomas Huth #define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \ 6547*fcf5ef2aSThomas Huth add_ca, compute_ca, compute_ov) \ 6548*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER), 6549*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0) 6550*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1) 6551*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0) 6552*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1) 6553*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0) 6554*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1) 6555*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0) 6556*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1) 6557*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0) 6558*fcf5ef2aSThomas Huth GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1) 6559*fcf5ef2aSThomas Huth 6560*fcf5ef2aSThomas Huth #undef GEN_LOGICAL1 6561*fcf5ef2aSThomas Huth #undef GEN_LOGICAL2 6562*fcf5ef2aSThomas Huth #define GEN_LOGICAL2(name, tcg_op, opc, type) \ 6563*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type) 6564*fcf5ef2aSThomas Huth #define GEN_LOGICAL1(name, tcg_op, opc, type) \ 6565*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) 6566*fcf5ef2aSThomas Huth GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER), 6567*fcf5ef2aSThomas Huth GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER), 6568*fcf5ef2aSThomas Huth GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER), 6569*fcf5ef2aSThomas Huth GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER), 6570*fcf5ef2aSThomas Huth GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER), 6571*fcf5ef2aSThomas Huth GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER), 6572*fcf5ef2aSThomas Huth GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER), 6573*fcf5ef2aSThomas Huth GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER), 6574*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6575*fcf5ef2aSThomas Huth GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B), 6576*fcf5ef2aSThomas Huth #endif 6577*fcf5ef2aSThomas Huth 6578*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6579*fcf5ef2aSThomas Huth #undef GEN_PPC64_R2 6580*fcf5ef2aSThomas Huth #undef GEN_PPC64_R4 6581*fcf5ef2aSThomas Huth #define GEN_PPC64_R2(name, opc1, opc2) \ 6582*fcf5ef2aSThomas Huth GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\ 6583*fcf5ef2aSThomas Huth GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \ 6584*fcf5ef2aSThomas Huth PPC_64B) 6585*fcf5ef2aSThomas Huth #define GEN_PPC64_R4(name, opc1, opc2) \ 6586*fcf5ef2aSThomas Huth GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B),\ 6587*fcf5ef2aSThomas Huth GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \ 6588*fcf5ef2aSThomas Huth PPC_64B), \ 6589*fcf5ef2aSThomas Huth GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \ 6590*fcf5ef2aSThomas Huth PPC_64B), \ 6591*fcf5ef2aSThomas Huth GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \ 6592*fcf5ef2aSThomas Huth PPC_64B) 6593*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldicl, 0x1E, 0x00), 6594*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldicr, 0x1E, 0x02), 6595*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldic, 0x1E, 0x04), 6596*fcf5ef2aSThomas Huth GEN_PPC64_R2(rldcl, 0x1E, 0x08), 6597*fcf5ef2aSThomas Huth GEN_PPC64_R2(rldcr, 0x1E, 0x09), 6598*fcf5ef2aSThomas Huth GEN_PPC64_R4(rldimi, 0x1E, 0x06), 6599*fcf5ef2aSThomas Huth #endif 6600*fcf5ef2aSThomas Huth 6601*fcf5ef2aSThomas Huth #undef GEN_LD 6602*fcf5ef2aSThomas Huth #undef GEN_LDU 6603*fcf5ef2aSThomas Huth #undef GEN_LDUX 6604*fcf5ef2aSThomas Huth #undef GEN_LDX_E 6605*fcf5ef2aSThomas Huth #undef GEN_LDS 6606*fcf5ef2aSThomas Huth #define GEN_LD(name, ldop, opc, type) \ 6607*fcf5ef2aSThomas Huth GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type), 6608*fcf5ef2aSThomas Huth #define GEN_LDU(name, ldop, opc, type) \ 6609*fcf5ef2aSThomas Huth GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type), 6610*fcf5ef2aSThomas Huth #define GEN_LDUX(name, ldop, opc2, opc3, type) \ 6611*fcf5ef2aSThomas Huth GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type), 6612*fcf5ef2aSThomas Huth #define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \ 6613*fcf5ef2aSThomas Huth GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2), 6614*fcf5ef2aSThomas Huth #define GEN_LDS(name, ldop, op, type) \ 6615*fcf5ef2aSThomas Huth GEN_LD(name, ldop, op | 0x20, type) \ 6616*fcf5ef2aSThomas Huth GEN_LDU(name, ldop, op | 0x21, type) \ 6617*fcf5ef2aSThomas Huth GEN_LDUX(name, ldop, 0x17, op | 0x01, type) \ 6618*fcf5ef2aSThomas Huth GEN_LDX(name, ldop, 0x17, op | 0x00, type) 6619*fcf5ef2aSThomas Huth 6620*fcf5ef2aSThomas Huth GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER) 6621*fcf5ef2aSThomas Huth GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER) 6622*fcf5ef2aSThomas Huth GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER) 6623*fcf5ef2aSThomas Huth GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER) 6624*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6625*fcf5ef2aSThomas Huth GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B) 6626*fcf5ef2aSThomas Huth GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B) 6627*fcf5ef2aSThomas Huth GEN_LDUX(ld, ld64_i64, 0x15, 0x01, PPC_64B) 6628*fcf5ef2aSThomas Huth GEN_LDX(ld, ld64_i64, 0x15, 0x00, PPC_64B) 6629*fcf5ef2aSThomas Huth GEN_LDX_E(ldbr, ld64ur_i64, 0x14, 0x10, PPC_NONE, PPC2_DBRX, CHK_NONE) 6630*fcf5ef2aSThomas Huth 6631*fcf5ef2aSThomas Huth /* HV/P7 and later only */ 6632*fcf5ef2aSThomas Huth GEN_LDX_HVRM(ldcix, ld64_i64, 0x15, 0x1b, PPC_CILDST) 6633*fcf5ef2aSThomas Huth GEN_LDX_HVRM(lwzcix, ld32u, 0x15, 0x18, PPC_CILDST) 6634*fcf5ef2aSThomas Huth GEN_LDX_HVRM(lhzcix, ld16u, 0x15, 0x19, PPC_CILDST) 6635*fcf5ef2aSThomas Huth GEN_LDX_HVRM(lbzcix, ld8u, 0x15, 0x1a, PPC_CILDST) 6636*fcf5ef2aSThomas Huth #endif 6637*fcf5ef2aSThomas Huth GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER) 6638*fcf5ef2aSThomas Huth GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER) 6639*fcf5ef2aSThomas Huth 6640*fcf5ef2aSThomas Huth #undef GEN_ST 6641*fcf5ef2aSThomas Huth #undef GEN_STU 6642*fcf5ef2aSThomas Huth #undef GEN_STUX 6643*fcf5ef2aSThomas Huth #undef GEN_STX_E 6644*fcf5ef2aSThomas Huth #undef GEN_STS 6645*fcf5ef2aSThomas Huth #define GEN_ST(name, stop, opc, type) \ 6646*fcf5ef2aSThomas Huth GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type), 6647*fcf5ef2aSThomas Huth #define GEN_STU(name, stop, opc, type) \ 6648*fcf5ef2aSThomas Huth GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type), 6649*fcf5ef2aSThomas Huth #define GEN_STUX(name, stop, opc2, opc3, type) \ 6650*fcf5ef2aSThomas Huth GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type), 6651*fcf5ef2aSThomas Huth #define GEN_STX_E(name, stop, opc2, opc3, type, type2, chk) \ 6652*fcf5ef2aSThomas Huth GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2), 6653*fcf5ef2aSThomas Huth #define GEN_STS(name, stop, op, type) \ 6654*fcf5ef2aSThomas Huth GEN_ST(name, stop, op | 0x20, type) \ 6655*fcf5ef2aSThomas Huth GEN_STU(name, stop, op | 0x21, type) \ 6656*fcf5ef2aSThomas Huth GEN_STUX(name, stop, 0x17, op | 0x01, type) \ 6657*fcf5ef2aSThomas Huth GEN_STX(name, stop, 0x17, op | 0x00, type) 6658*fcf5ef2aSThomas Huth 6659*fcf5ef2aSThomas Huth GEN_STS(stb, st8, 0x06, PPC_INTEGER) 6660*fcf5ef2aSThomas Huth GEN_STS(sth, st16, 0x0C, PPC_INTEGER) 6661*fcf5ef2aSThomas Huth GEN_STS(stw, st32, 0x04, PPC_INTEGER) 6662*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6663*fcf5ef2aSThomas Huth GEN_STUX(std, st64_i64, 0x15, 0x05, PPC_64B) 6664*fcf5ef2aSThomas Huth GEN_STX(std, st64_i64, 0x15, 0x04, PPC_64B) 6665*fcf5ef2aSThomas Huth GEN_STX_E(stdbr, st64r_i64, 0x14, 0x14, PPC_NONE, PPC2_DBRX, CHK_NONE) 6666*fcf5ef2aSThomas Huth GEN_STX_HVRM(stdcix, st64_i64, 0x15, 0x1f, PPC_CILDST) 6667*fcf5ef2aSThomas Huth GEN_STX_HVRM(stwcix, st32, 0x15, 0x1c, PPC_CILDST) 6668*fcf5ef2aSThomas Huth GEN_STX_HVRM(sthcix, st16, 0x15, 0x1d, PPC_CILDST) 6669*fcf5ef2aSThomas Huth GEN_STX_HVRM(stbcix, st8, 0x15, 0x1e, PPC_CILDST) 6670*fcf5ef2aSThomas Huth #endif 6671*fcf5ef2aSThomas Huth GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER) 6672*fcf5ef2aSThomas Huth GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER) 6673*fcf5ef2aSThomas Huth 6674*fcf5ef2aSThomas Huth #undef GEN_CRLOGIC 6675*fcf5ef2aSThomas Huth #define GEN_CRLOGIC(name, tcg_op, opc) \ 6676*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) 6677*fcf5ef2aSThomas Huth GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08), 6678*fcf5ef2aSThomas Huth GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04), 6679*fcf5ef2aSThomas Huth GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09), 6680*fcf5ef2aSThomas Huth GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07), 6681*fcf5ef2aSThomas Huth GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01), 6682*fcf5ef2aSThomas Huth GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E), 6683*fcf5ef2aSThomas Huth GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D), 6684*fcf5ef2aSThomas Huth GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06), 6685*fcf5ef2aSThomas Huth 6686*fcf5ef2aSThomas Huth #undef GEN_MAC_HANDLER 6687*fcf5ef2aSThomas Huth #define GEN_MAC_HANDLER(name, opc2, opc3) \ 6688*fcf5ef2aSThomas Huth GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) 6689*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchw, 0x0C, 0x05), 6690*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwo, 0x0C, 0x15), 6691*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchws, 0x0C, 0x07), 6692*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwso, 0x0C, 0x17), 6693*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06), 6694*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16), 6695*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwu, 0x0C, 0x04), 6696*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14), 6697*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhw, 0x0C, 0x01), 6698*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwo, 0x0C, 0x11), 6699*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhws, 0x0C, 0x03), 6700*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwso, 0x0C, 0x13), 6701*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02), 6702*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12), 6703*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwu, 0x0C, 0x00), 6704*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10), 6705*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D), 6706*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D), 6707*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F), 6708*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F), 6709*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C), 6710*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C), 6711*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E), 6712*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E), 6713*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05), 6714*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15), 6715*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07), 6716*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17), 6717*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01), 6718*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11), 6719*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03), 6720*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13), 6721*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D), 6722*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D), 6723*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F), 6724*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F), 6725*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulchw, 0x08, 0x05), 6726*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulchwu, 0x08, 0x04), 6727*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulhhw, 0x08, 0x01), 6728*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00), 6729*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mullhw, 0x08, 0x0D), 6730*fcf5ef2aSThomas Huth GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C), 6731*fcf5ef2aSThomas Huth 6732*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \ 6733*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6734*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tend, "tend", 0x1F, 0x0E, 0x15, 0x01FFF800, \ 6735*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6736*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \ 6737*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6738*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \ 6739*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6740*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \ 6741*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6742*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \ 6743*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6744*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \ 6745*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6746*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \ 6747*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6748*fcf5ef2aSThomas Huth GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \ 6749*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6750*fcf5ef2aSThomas Huth GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \ 6751*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6752*fcf5ef2aSThomas Huth GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \ 6753*fcf5ef2aSThomas Huth PPC_NONE, PPC2_TM), 6754*fcf5ef2aSThomas Huth 6755*fcf5ef2aSThomas Huth #include "translate/fp-ops.inc.c" 6756*fcf5ef2aSThomas Huth 6757*fcf5ef2aSThomas Huth #include "translate/vmx-ops.inc.c" 6758*fcf5ef2aSThomas Huth 6759*fcf5ef2aSThomas Huth #include "translate/vsx-ops.inc.c" 6760*fcf5ef2aSThomas Huth 6761*fcf5ef2aSThomas Huth #include "translate/dfp-ops.inc.c" 6762*fcf5ef2aSThomas Huth 6763*fcf5ef2aSThomas Huth #include "translate/spe-ops.inc.c" 6764*fcf5ef2aSThomas Huth }; 6765*fcf5ef2aSThomas Huth 6766*fcf5ef2aSThomas Huth #include "helper_regs.h" 6767*fcf5ef2aSThomas Huth #include "translate_init.c" 6768*fcf5ef2aSThomas Huth 6769*fcf5ef2aSThomas Huth /*****************************************************************************/ 6770*fcf5ef2aSThomas Huth /* Misc PowerPC helpers */ 6771*fcf5ef2aSThomas Huth void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, 6772*fcf5ef2aSThomas Huth int flags) 6773*fcf5ef2aSThomas Huth { 6774*fcf5ef2aSThomas Huth #define RGPL 4 6775*fcf5ef2aSThomas Huth #define RFPL 4 6776*fcf5ef2aSThomas Huth 6777*fcf5ef2aSThomas Huth PowerPCCPU *cpu = POWERPC_CPU(cs); 6778*fcf5ef2aSThomas Huth CPUPPCState *env = &cpu->env; 6779*fcf5ef2aSThomas Huth int i; 6780*fcf5ef2aSThomas Huth 6781*fcf5ef2aSThomas Huth cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR " 6782*fcf5ef2aSThomas Huth TARGET_FMT_lx " XER " TARGET_FMT_lx " CPU#%d\n", 6783*fcf5ef2aSThomas Huth env->nip, env->lr, env->ctr, cpu_read_xer(env), 6784*fcf5ef2aSThomas Huth cs->cpu_index); 6785*fcf5ef2aSThomas Huth cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF " 6786*fcf5ef2aSThomas Huth TARGET_FMT_lx " iidx %d didx %d\n", 6787*fcf5ef2aSThomas Huth env->msr, env->spr[SPR_HID0], 6788*fcf5ef2aSThomas Huth env->hflags, env->immu_idx, env->dmmu_idx); 6789*fcf5ef2aSThomas Huth #if !defined(NO_TIMER_DUMP) 6790*fcf5ef2aSThomas Huth cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64 6791*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 6792*fcf5ef2aSThomas Huth " DECR %08" PRIu32 6793*fcf5ef2aSThomas Huth #endif 6794*fcf5ef2aSThomas Huth "\n", 6795*fcf5ef2aSThomas Huth cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env) 6796*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 6797*fcf5ef2aSThomas Huth , cpu_ppc_load_decr(env) 6798*fcf5ef2aSThomas Huth #endif 6799*fcf5ef2aSThomas Huth ); 6800*fcf5ef2aSThomas Huth #endif 6801*fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 6802*fcf5ef2aSThomas Huth if ((i & (RGPL - 1)) == 0) 6803*fcf5ef2aSThomas Huth cpu_fprintf(f, "GPR%02d", i); 6804*fcf5ef2aSThomas Huth cpu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i)); 6805*fcf5ef2aSThomas Huth if ((i & (RGPL - 1)) == (RGPL - 1)) 6806*fcf5ef2aSThomas Huth cpu_fprintf(f, "\n"); 6807*fcf5ef2aSThomas Huth } 6808*fcf5ef2aSThomas Huth cpu_fprintf(f, "CR "); 6809*fcf5ef2aSThomas Huth for (i = 0; i < 8; i++) 6810*fcf5ef2aSThomas Huth cpu_fprintf(f, "%01x", env->crf[i]); 6811*fcf5ef2aSThomas Huth cpu_fprintf(f, " ["); 6812*fcf5ef2aSThomas Huth for (i = 0; i < 8; i++) { 6813*fcf5ef2aSThomas Huth char a = '-'; 6814*fcf5ef2aSThomas Huth if (env->crf[i] & 0x08) 6815*fcf5ef2aSThomas Huth a = 'L'; 6816*fcf5ef2aSThomas Huth else if (env->crf[i] & 0x04) 6817*fcf5ef2aSThomas Huth a = 'G'; 6818*fcf5ef2aSThomas Huth else if (env->crf[i] & 0x02) 6819*fcf5ef2aSThomas Huth a = 'E'; 6820*fcf5ef2aSThomas Huth cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' '); 6821*fcf5ef2aSThomas Huth } 6822*fcf5ef2aSThomas Huth cpu_fprintf(f, " ] RES " TARGET_FMT_lx "\n", 6823*fcf5ef2aSThomas Huth env->reserve_addr); 6824*fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) { 6825*fcf5ef2aSThomas Huth if ((i & (RFPL - 1)) == 0) 6826*fcf5ef2aSThomas Huth cpu_fprintf(f, "FPR%02d", i); 6827*fcf5ef2aSThomas Huth cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i])); 6828*fcf5ef2aSThomas Huth if ((i & (RFPL - 1)) == (RFPL - 1)) 6829*fcf5ef2aSThomas Huth cpu_fprintf(f, "\n"); 6830*fcf5ef2aSThomas Huth } 6831*fcf5ef2aSThomas Huth cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr); 6832*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 6833*fcf5ef2aSThomas Huth cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx 6834*fcf5ef2aSThomas Huth " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n", 6835*fcf5ef2aSThomas Huth env->spr[SPR_SRR0], env->spr[SPR_SRR1], 6836*fcf5ef2aSThomas Huth env->spr[SPR_PVR], env->spr[SPR_VRSAVE]); 6837*fcf5ef2aSThomas Huth 6838*fcf5ef2aSThomas Huth cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx 6839*fcf5ef2aSThomas Huth " SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n", 6840*fcf5ef2aSThomas Huth env->spr[SPR_SPRG0], env->spr[SPR_SPRG1], 6841*fcf5ef2aSThomas Huth env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]); 6842*fcf5ef2aSThomas Huth 6843*fcf5ef2aSThomas Huth cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx 6844*fcf5ef2aSThomas Huth " SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n", 6845*fcf5ef2aSThomas Huth env->spr[SPR_SPRG4], env->spr[SPR_SPRG5], 6846*fcf5ef2aSThomas Huth env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]); 6847*fcf5ef2aSThomas Huth 6848*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6849*fcf5ef2aSThomas Huth if (env->excp_model == POWERPC_EXCP_POWER7 || 6850*fcf5ef2aSThomas Huth env->excp_model == POWERPC_EXCP_POWER8) { 6851*fcf5ef2aSThomas Huth cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n", 6852*fcf5ef2aSThomas Huth env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); 6853*fcf5ef2aSThomas Huth } 6854*fcf5ef2aSThomas Huth #endif 6855*fcf5ef2aSThomas Huth if (env->excp_model == POWERPC_EXCP_BOOKE) { 6856*fcf5ef2aSThomas Huth cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx 6857*fcf5ef2aSThomas Huth " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n", 6858*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1], 6859*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]); 6860*fcf5ef2aSThomas Huth 6861*fcf5ef2aSThomas Huth cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx 6862*fcf5ef2aSThomas Huth " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n", 6863*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR], 6864*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]); 6865*fcf5ef2aSThomas Huth 6866*fcf5ef2aSThomas Huth cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx 6867*fcf5ef2aSThomas Huth " IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n", 6868*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR], 6869*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]); 6870*fcf5ef2aSThomas Huth 6871*fcf5ef2aSThomas Huth cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx 6872*fcf5ef2aSThomas Huth " EPR " TARGET_FMT_lx "\n", 6873*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8], 6874*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_EPR]); 6875*fcf5ef2aSThomas Huth 6876*fcf5ef2aSThomas Huth /* FSL-specific */ 6877*fcf5ef2aSThomas Huth cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx 6878*fcf5ef2aSThomas Huth " PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n", 6879*fcf5ef2aSThomas Huth env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1], 6880*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]); 6881*fcf5ef2aSThomas Huth 6882*fcf5ef2aSThomas Huth /* 6883*fcf5ef2aSThomas Huth * IVORs are left out as they are large and do not change often -- 6884*fcf5ef2aSThomas Huth * they can be read with "p $ivor0", "p $ivor1", etc. 6885*fcf5ef2aSThomas Huth */ 6886*fcf5ef2aSThomas Huth } 6887*fcf5ef2aSThomas Huth 6888*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6889*fcf5ef2aSThomas Huth if (env->flags & POWERPC_FLAG_CFAR) { 6890*fcf5ef2aSThomas Huth cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar); 6891*fcf5ef2aSThomas Huth } 6892*fcf5ef2aSThomas Huth #endif 6893*fcf5ef2aSThomas Huth 6894*fcf5ef2aSThomas Huth switch (env->mmu_model) { 6895*fcf5ef2aSThomas Huth case POWERPC_MMU_32B: 6896*fcf5ef2aSThomas Huth case POWERPC_MMU_601: 6897*fcf5ef2aSThomas Huth case POWERPC_MMU_SOFT_6xx: 6898*fcf5ef2aSThomas Huth case POWERPC_MMU_SOFT_74xx: 6899*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 6900*fcf5ef2aSThomas Huth case POWERPC_MMU_64B: 6901*fcf5ef2aSThomas Huth case POWERPC_MMU_2_03: 6902*fcf5ef2aSThomas Huth case POWERPC_MMU_2_06: 6903*fcf5ef2aSThomas Huth case POWERPC_MMU_2_06a: 6904*fcf5ef2aSThomas Huth case POWERPC_MMU_2_07: 6905*fcf5ef2aSThomas Huth case POWERPC_MMU_2_07a: 6906*fcf5ef2aSThomas Huth #endif 6907*fcf5ef2aSThomas Huth cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " DAR " TARGET_FMT_lx 6908*fcf5ef2aSThomas Huth " DSISR " TARGET_FMT_lx "\n", env->spr[SPR_SDR1], 6909*fcf5ef2aSThomas Huth env->spr[SPR_DAR], env->spr[SPR_DSISR]); 6910*fcf5ef2aSThomas Huth break; 6911*fcf5ef2aSThomas Huth case POWERPC_MMU_BOOKE206: 6912*fcf5ef2aSThomas Huth cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx 6913*fcf5ef2aSThomas Huth " MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n", 6914*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1], 6915*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]); 6916*fcf5ef2aSThomas Huth 6917*fcf5ef2aSThomas Huth cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx 6918*fcf5ef2aSThomas Huth " MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n", 6919*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6], 6920*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]); 6921*fcf5ef2aSThomas Huth 6922*fcf5ef2aSThomas Huth cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx 6923*fcf5ef2aSThomas Huth " TLB1CFG " TARGET_FMT_lx "\n", 6924*fcf5ef2aSThomas Huth env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG], 6925*fcf5ef2aSThomas Huth env->spr[SPR_BOOKE_TLB1CFG]); 6926*fcf5ef2aSThomas Huth break; 6927*fcf5ef2aSThomas Huth default: 6928*fcf5ef2aSThomas Huth break; 6929*fcf5ef2aSThomas Huth } 6930*fcf5ef2aSThomas Huth #endif 6931*fcf5ef2aSThomas Huth 6932*fcf5ef2aSThomas Huth #undef RGPL 6933*fcf5ef2aSThomas Huth #undef RFPL 6934*fcf5ef2aSThomas Huth } 6935*fcf5ef2aSThomas Huth 6936*fcf5ef2aSThomas Huth void ppc_cpu_dump_statistics(CPUState *cs, FILE*f, 6937*fcf5ef2aSThomas Huth fprintf_function cpu_fprintf, int flags) 6938*fcf5ef2aSThomas Huth { 6939*fcf5ef2aSThomas Huth #if defined(DO_PPC_STATISTICS) 6940*fcf5ef2aSThomas Huth PowerPCCPU *cpu = POWERPC_CPU(cs); 6941*fcf5ef2aSThomas Huth opc_handler_t **t1, **t2, **t3, *handler; 6942*fcf5ef2aSThomas Huth int op1, op2, op3; 6943*fcf5ef2aSThomas Huth 6944*fcf5ef2aSThomas Huth t1 = cpu->env.opcodes; 6945*fcf5ef2aSThomas Huth for (op1 = 0; op1 < 64; op1++) { 6946*fcf5ef2aSThomas Huth handler = t1[op1]; 6947*fcf5ef2aSThomas Huth if (is_indirect_opcode(handler)) { 6948*fcf5ef2aSThomas Huth t2 = ind_table(handler); 6949*fcf5ef2aSThomas Huth for (op2 = 0; op2 < 32; op2++) { 6950*fcf5ef2aSThomas Huth handler = t2[op2]; 6951*fcf5ef2aSThomas Huth if (is_indirect_opcode(handler)) { 6952*fcf5ef2aSThomas Huth t3 = ind_table(handler); 6953*fcf5ef2aSThomas Huth for (op3 = 0; op3 < 32; op3++) { 6954*fcf5ef2aSThomas Huth handler = t3[op3]; 6955*fcf5ef2aSThomas Huth if (handler->count == 0) 6956*fcf5ef2aSThomas Huth continue; 6957*fcf5ef2aSThomas Huth cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: " 6958*fcf5ef2aSThomas Huth "%016" PRIx64 " %" PRId64 "\n", 6959*fcf5ef2aSThomas Huth op1, op2, op3, op1, (op3 << 5) | op2, 6960*fcf5ef2aSThomas Huth handler->oname, 6961*fcf5ef2aSThomas Huth handler->count, handler->count); 6962*fcf5ef2aSThomas Huth } 6963*fcf5ef2aSThomas Huth } else { 6964*fcf5ef2aSThomas Huth if (handler->count == 0) 6965*fcf5ef2aSThomas Huth continue; 6966*fcf5ef2aSThomas Huth cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: " 6967*fcf5ef2aSThomas Huth "%016" PRIx64 " %" PRId64 "\n", 6968*fcf5ef2aSThomas Huth op1, op2, op1, op2, handler->oname, 6969*fcf5ef2aSThomas Huth handler->count, handler->count); 6970*fcf5ef2aSThomas Huth } 6971*fcf5ef2aSThomas Huth } 6972*fcf5ef2aSThomas Huth } else { 6973*fcf5ef2aSThomas Huth if (handler->count == 0) 6974*fcf5ef2aSThomas Huth continue; 6975*fcf5ef2aSThomas Huth cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64 6976*fcf5ef2aSThomas Huth " %" PRId64 "\n", 6977*fcf5ef2aSThomas Huth op1, op1, handler->oname, 6978*fcf5ef2aSThomas Huth handler->count, handler->count); 6979*fcf5ef2aSThomas Huth } 6980*fcf5ef2aSThomas Huth } 6981*fcf5ef2aSThomas Huth #endif 6982*fcf5ef2aSThomas Huth } 6983*fcf5ef2aSThomas Huth 6984*fcf5ef2aSThomas Huth /*****************************************************************************/ 6985*fcf5ef2aSThomas Huth void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb) 6986*fcf5ef2aSThomas Huth { 6987*fcf5ef2aSThomas Huth PowerPCCPU *cpu = ppc_env_get_cpu(env); 6988*fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 6989*fcf5ef2aSThomas Huth DisasContext ctx, *ctxp = &ctx; 6990*fcf5ef2aSThomas Huth opc_handler_t **table, *handler; 6991*fcf5ef2aSThomas Huth target_ulong pc_start; 6992*fcf5ef2aSThomas Huth int num_insns; 6993*fcf5ef2aSThomas Huth int max_insns; 6994*fcf5ef2aSThomas Huth 6995*fcf5ef2aSThomas Huth pc_start = tb->pc; 6996*fcf5ef2aSThomas Huth ctx.nip = pc_start; 6997*fcf5ef2aSThomas Huth ctx.tb = tb; 6998*fcf5ef2aSThomas Huth ctx.exception = POWERPC_EXCP_NONE; 6999*fcf5ef2aSThomas Huth ctx.spr_cb = env->spr_cb; 7000*fcf5ef2aSThomas Huth ctx.pr = msr_pr; 7001*fcf5ef2aSThomas Huth ctx.mem_idx = env->dmmu_idx; 7002*fcf5ef2aSThomas Huth ctx.dr = msr_dr; 7003*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 7004*fcf5ef2aSThomas Huth ctx.hv = msr_hv || !env->has_hv_mode; 7005*fcf5ef2aSThomas Huth #endif 7006*fcf5ef2aSThomas Huth ctx.insns_flags = env->insns_flags; 7007*fcf5ef2aSThomas Huth ctx.insns_flags2 = env->insns_flags2; 7008*fcf5ef2aSThomas Huth ctx.access_type = -1; 7009*fcf5ef2aSThomas Huth ctx.need_access_type = !(env->mmu_model & POWERPC_MMU_64B); 7010*fcf5ef2aSThomas Huth ctx.le_mode = !!(env->hflags & (1 << MSR_LE)); 7011*fcf5ef2aSThomas Huth ctx.default_tcg_memop_mask = ctx.le_mode ? MO_LE : MO_BE; 7012*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 7013*fcf5ef2aSThomas Huth ctx.sf_mode = msr_is_64bit(env, env->msr); 7014*fcf5ef2aSThomas Huth ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR); 7015*fcf5ef2aSThomas Huth #endif 7016*fcf5ef2aSThomas Huth if (env->mmu_model == POWERPC_MMU_32B || 7017*fcf5ef2aSThomas Huth env->mmu_model == POWERPC_MMU_601 || 7018*fcf5ef2aSThomas Huth (env->mmu_model & POWERPC_MMU_64B)) 7019*fcf5ef2aSThomas Huth ctx.lazy_tlb_flush = true; 7020*fcf5ef2aSThomas Huth 7021*fcf5ef2aSThomas Huth ctx.fpu_enabled = !!msr_fp; 7022*fcf5ef2aSThomas Huth if ((env->flags & POWERPC_FLAG_SPE) && msr_spe) 7023*fcf5ef2aSThomas Huth ctx.spe_enabled = !!msr_spe; 7024*fcf5ef2aSThomas Huth else 7025*fcf5ef2aSThomas Huth ctx.spe_enabled = false; 7026*fcf5ef2aSThomas Huth if ((env->flags & POWERPC_FLAG_VRE) && msr_vr) 7027*fcf5ef2aSThomas Huth ctx.altivec_enabled = !!msr_vr; 7028*fcf5ef2aSThomas Huth else 7029*fcf5ef2aSThomas Huth ctx.altivec_enabled = false; 7030*fcf5ef2aSThomas Huth if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) { 7031*fcf5ef2aSThomas Huth ctx.vsx_enabled = !!msr_vsx; 7032*fcf5ef2aSThomas Huth } else { 7033*fcf5ef2aSThomas Huth ctx.vsx_enabled = false; 7034*fcf5ef2aSThomas Huth } 7035*fcf5ef2aSThomas Huth #if defined(TARGET_PPC64) 7036*fcf5ef2aSThomas Huth if ((env->flags & POWERPC_FLAG_TM) && msr_tm) { 7037*fcf5ef2aSThomas Huth ctx.tm_enabled = !!msr_tm; 7038*fcf5ef2aSThomas Huth } else { 7039*fcf5ef2aSThomas Huth ctx.tm_enabled = false; 7040*fcf5ef2aSThomas Huth } 7041*fcf5ef2aSThomas Huth #endif 7042*fcf5ef2aSThomas Huth if ((env->flags & POWERPC_FLAG_SE) && msr_se) 7043*fcf5ef2aSThomas Huth ctx.singlestep_enabled = CPU_SINGLE_STEP; 7044*fcf5ef2aSThomas Huth else 7045*fcf5ef2aSThomas Huth ctx.singlestep_enabled = 0; 7046*fcf5ef2aSThomas Huth if ((env->flags & POWERPC_FLAG_BE) && msr_be) 7047*fcf5ef2aSThomas Huth ctx.singlestep_enabled |= CPU_BRANCH_STEP; 7048*fcf5ef2aSThomas Huth if (unlikely(cs->singlestep_enabled)) { 7049*fcf5ef2aSThomas Huth ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP; 7050*fcf5ef2aSThomas Huth } 7051*fcf5ef2aSThomas Huth #if defined (DO_SINGLE_STEP) && 0 7052*fcf5ef2aSThomas Huth /* Single step trace mode */ 7053*fcf5ef2aSThomas Huth msr_se = 1; 7054*fcf5ef2aSThomas Huth #endif 7055*fcf5ef2aSThomas Huth num_insns = 0; 7056*fcf5ef2aSThomas Huth max_insns = tb->cflags & CF_COUNT_MASK; 7057*fcf5ef2aSThomas Huth if (max_insns == 0) { 7058*fcf5ef2aSThomas Huth max_insns = CF_COUNT_MASK; 7059*fcf5ef2aSThomas Huth } 7060*fcf5ef2aSThomas Huth if (max_insns > TCG_MAX_INSNS) { 7061*fcf5ef2aSThomas Huth max_insns = TCG_MAX_INSNS; 7062*fcf5ef2aSThomas Huth } 7063*fcf5ef2aSThomas Huth 7064*fcf5ef2aSThomas Huth gen_tb_start(tb); 7065*fcf5ef2aSThomas Huth tcg_clear_temp_count(); 7066*fcf5ef2aSThomas Huth /* Set env in case of segfault during code fetch */ 7067*fcf5ef2aSThomas Huth while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) { 7068*fcf5ef2aSThomas Huth tcg_gen_insn_start(ctx.nip); 7069*fcf5ef2aSThomas Huth num_insns++; 7070*fcf5ef2aSThomas Huth 7071*fcf5ef2aSThomas Huth if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) { 7072*fcf5ef2aSThomas Huth gen_debug_exception(ctxp); 7073*fcf5ef2aSThomas Huth /* The address covered by the breakpoint must be included in 7074*fcf5ef2aSThomas Huth [tb->pc, tb->pc + tb->size) in order to for it to be 7075*fcf5ef2aSThomas Huth properly cleared -- thus we increment the PC here so that 7076*fcf5ef2aSThomas Huth the logic setting tb->size below does the right thing. */ 7077*fcf5ef2aSThomas Huth ctx.nip += 4; 7078*fcf5ef2aSThomas Huth break; 7079*fcf5ef2aSThomas Huth } 7080*fcf5ef2aSThomas Huth 7081*fcf5ef2aSThomas Huth LOG_DISAS("----------------\n"); 7082*fcf5ef2aSThomas Huth LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", 7083*fcf5ef2aSThomas Huth ctx.nip, ctx.mem_idx, (int)msr_ir); 7084*fcf5ef2aSThomas Huth if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) 7085*fcf5ef2aSThomas Huth gen_io_start(); 7086*fcf5ef2aSThomas Huth if (unlikely(need_byteswap(&ctx))) { 7087*fcf5ef2aSThomas Huth ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip)); 7088*fcf5ef2aSThomas Huth } else { 7089*fcf5ef2aSThomas Huth ctx.opcode = cpu_ldl_code(env, ctx.nip); 7090*fcf5ef2aSThomas Huth } 7091*fcf5ef2aSThomas Huth LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n", 7092*fcf5ef2aSThomas Huth ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), 7093*fcf5ef2aSThomas Huth opc3(ctx.opcode), opc4(ctx.opcode), 7094*fcf5ef2aSThomas Huth ctx.le_mode ? "little" : "big"); 7095*fcf5ef2aSThomas Huth ctx.nip += 4; 7096*fcf5ef2aSThomas Huth table = env->opcodes; 7097*fcf5ef2aSThomas Huth handler = table[opc1(ctx.opcode)]; 7098*fcf5ef2aSThomas Huth if (is_indirect_opcode(handler)) { 7099*fcf5ef2aSThomas Huth table = ind_table(handler); 7100*fcf5ef2aSThomas Huth handler = table[opc2(ctx.opcode)]; 7101*fcf5ef2aSThomas Huth if (is_indirect_opcode(handler)) { 7102*fcf5ef2aSThomas Huth table = ind_table(handler); 7103*fcf5ef2aSThomas Huth handler = table[opc3(ctx.opcode)]; 7104*fcf5ef2aSThomas Huth if (is_indirect_opcode(handler)) { 7105*fcf5ef2aSThomas Huth table = ind_table(handler); 7106*fcf5ef2aSThomas Huth handler = table[opc4(ctx.opcode)]; 7107*fcf5ef2aSThomas Huth } 7108*fcf5ef2aSThomas Huth } 7109*fcf5ef2aSThomas Huth } 7110*fcf5ef2aSThomas Huth /* Is opcode *REALLY* valid ? */ 7111*fcf5ef2aSThomas Huth if (unlikely(handler->handler == &gen_invalid)) { 7112*fcf5ef2aSThomas Huth qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: " 7113*fcf5ef2aSThomas Huth "%02x - %02x - %02x - %02x (%08x) " 7114*fcf5ef2aSThomas Huth TARGET_FMT_lx " %d\n", 7115*fcf5ef2aSThomas Huth opc1(ctx.opcode), opc2(ctx.opcode), 7116*fcf5ef2aSThomas Huth opc3(ctx.opcode), opc4(ctx.opcode), 7117*fcf5ef2aSThomas Huth ctx.opcode, ctx.nip - 4, (int)msr_ir); 7118*fcf5ef2aSThomas Huth } else { 7119*fcf5ef2aSThomas Huth uint32_t inval; 7120*fcf5ef2aSThomas Huth 7121*fcf5ef2aSThomas Huth if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE) && Rc(ctx.opcode))) { 7122*fcf5ef2aSThomas Huth inval = handler->inval2; 7123*fcf5ef2aSThomas Huth } else { 7124*fcf5ef2aSThomas Huth inval = handler->inval1; 7125*fcf5ef2aSThomas Huth } 7126*fcf5ef2aSThomas Huth 7127*fcf5ef2aSThomas Huth if (unlikely((ctx.opcode & inval) != 0)) { 7128*fcf5ef2aSThomas Huth qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: " 7129*fcf5ef2aSThomas Huth "%02x - %02x - %02x - %02x (%08x) " 7130*fcf5ef2aSThomas Huth TARGET_FMT_lx "\n", ctx.opcode & inval, 7131*fcf5ef2aSThomas Huth opc1(ctx.opcode), opc2(ctx.opcode), 7132*fcf5ef2aSThomas Huth opc3(ctx.opcode), opc4(ctx.opcode), 7133*fcf5ef2aSThomas Huth ctx.opcode, ctx.nip - 4); 7134*fcf5ef2aSThomas Huth gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL); 7135*fcf5ef2aSThomas Huth break; 7136*fcf5ef2aSThomas Huth } 7137*fcf5ef2aSThomas Huth } 7138*fcf5ef2aSThomas Huth (*(handler->handler))(&ctx); 7139*fcf5ef2aSThomas Huth #if defined(DO_PPC_STATISTICS) 7140*fcf5ef2aSThomas Huth handler->count++; 7141*fcf5ef2aSThomas Huth #endif 7142*fcf5ef2aSThomas Huth /* Check trace mode exceptions */ 7143*fcf5ef2aSThomas Huth if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP && 7144*fcf5ef2aSThomas Huth (ctx.nip <= 0x100 || ctx.nip > 0xF00) && 7145*fcf5ef2aSThomas Huth ctx.exception != POWERPC_SYSCALL && 7146*fcf5ef2aSThomas Huth ctx.exception != POWERPC_EXCP_TRAP && 7147*fcf5ef2aSThomas Huth ctx.exception != POWERPC_EXCP_BRANCH)) { 7148*fcf5ef2aSThomas Huth gen_exception_nip(ctxp, POWERPC_EXCP_TRACE, ctx.nip); 7149*fcf5ef2aSThomas Huth } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) || 7150*fcf5ef2aSThomas Huth (cs->singlestep_enabled) || 7151*fcf5ef2aSThomas Huth singlestep || 7152*fcf5ef2aSThomas Huth num_insns >= max_insns)) { 7153*fcf5ef2aSThomas Huth /* if we reach a page boundary or are single stepping, stop 7154*fcf5ef2aSThomas Huth * generation 7155*fcf5ef2aSThomas Huth */ 7156*fcf5ef2aSThomas Huth break; 7157*fcf5ef2aSThomas Huth } 7158*fcf5ef2aSThomas Huth if (tcg_check_temp_count()) { 7159*fcf5ef2aSThomas Huth fprintf(stderr, "Opcode %02x %02x %02x %02x (%08x) leaked " 7160*fcf5ef2aSThomas Huth "temporaries\n", opc1(ctx.opcode), opc2(ctx.opcode), 7161*fcf5ef2aSThomas Huth opc3(ctx.opcode), opc4(ctx.opcode), ctx.opcode); 7162*fcf5ef2aSThomas Huth exit(1); 7163*fcf5ef2aSThomas Huth } 7164*fcf5ef2aSThomas Huth } 7165*fcf5ef2aSThomas Huth if (tb->cflags & CF_LAST_IO) 7166*fcf5ef2aSThomas Huth gen_io_end(); 7167*fcf5ef2aSThomas Huth if (ctx.exception == POWERPC_EXCP_NONE) { 7168*fcf5ef2aSThomas Huth gen_goto_tb(&ctx, 0, ctx.nip); 7169*fcf5ef2aSThomas Huth } else if (ctx.exception != POWERPC_EXCP_BRANCH) { 7170*fcf5ef2aSThomas Huth if (unlikely(cs->singlestep_enabled)) { 7171*fcf5ef2aSThomas Huth gen_debug_exception(ctxp); 7172*fcf5ef2aSThomas Huth } 7173*fcf5ef2aSThomas Huth /* Generate the return instruction */ 7174*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 7175*fcf5ef2aSThomas Huth } 7176*fcf5ef2aSThomas Huth gen_tb_end(tb, num_insns); 7177*fcf5ef2aSThomas Huth 7178*fcf5ef2aSThomas Huth tb->size = ctx.nip - pc_start; 7179*fcf5ef2aSThomas Huth tb->icount = num_insns; 7180*fcf5ef2aSThomas Huth 7181*fcf5ef2aSThomas Huth #if defined(DEBUG_DISAS) 7182*fcf5ef2aSThomas Huth if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) 7183*fcf5ef2aSThomas Huth && qemu_log_in_addr_range(pc_start)) { 7184*fcf5ef2aSThomas Huth int flags; 7185*fcf5ef2aSThomas Huth flags = env->bfd_mach; 7186*fcf5ef2aSThomas Huth flags |= ctx.le_mode << 16; 7187*fcf5ef2aSThomas Huth qemu_log_lock(); 7188*fcf5ef2aSThomas Huth qemu_log("IN: %s\n", lookup_symbol(pc_start)); 7189*fcf5ef2aSThomas Huth log_target_disas(cs, pc_start, ctx.nip - pc_start, flags); 7190*fcf5ef2aSThomas Huth qemu_log("\n"); 7191*fcf5ef2aSThomas Huth qemu_log_unlock(); 7192*fcf5ef2aSThomas Huth } 7193*fcf5ef2aSThomas Huth #endif 7194*fcf5ef2aSThomas Huth } 7195*fcf5ef2aSThomas Huth 7196*fcf5ef2aSThomas Huth void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, 7197*fcf5ef2aSThomas Huth target_ulong *data) 7198*fcf5ef2aSThomas Huth { 7199*fcf5ef2aSThomas Huth env->nip = data[0]; 7200*fcf5ef2aSThomas Huth } 7201