diff options
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 142 |
1 files changed, 140 insertions, 2 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 198fbf6815..7d382d6cab 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1584,6 +1584,14 @@ GEN_FLOAT_B(ctiw, 0x0E, 0x00); GEN_FLOAT_B(ctiwz, 0x0F, 0x00); /* frsp */ GEN_FLOAT_B(rsp, 0x0C, 0x00); +#if defined(TARGET_PPC64) +/* fcfid */ +GEN_FLOAT_B(cfid, 0x0E, 0x1A); +/* fctid */ +GEN_FLOAT_B(ctid, 0x0E, 0x19); +/* fctidz */ +GEN_FLOAT_B(ctidz, 0x0F, 0x19); +#endif /*** Floating-Point compare ***/ /* fcmpo */ @@ -1996,8 +2004,8 @@ GEN_STS(h, 0x0C, PPC_INTEGER); GEN_STS(w, 0x04, PPC_INTEGER); #if defined(TARGET_PPC64) OP_ST_TABLE(d); -GEN_STUX(d, 0x15, 0x01, PPC_64B); -GEN_STX(d, 0x15, 0x00, PPC_64B); +GEN_STUX(d, 0x15, 0x05, PPC_64B); +GEN_STX(d, 0x15, 0x04, PPC_64B); GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B) { if (Rc(ctx->opcode)) { @@ -2358,6 +2366,62 @@ GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES) op_stwcx(); } +#if defined(TARGET_PPC64) +#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])() +#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])() +#if defined(CONFIG_USER_ONLY) +static GenOpFunc *gen_op_ldarx[] = { + &gen_op_ldarx_raw, + &gen_op_ldarx_le_raw, + &gen_op_ldarx_64_raw, + &gen_op_ldarx_le_64_raw, +}; +static GenOpFunc *gen_op_stdcx[] = { + &gen_op_stdcx_raw, + &gen_op_stdcx_le_raw, + &gen_op_stdcx_64_raw, + &gen_op_stdcx_le_64_raw, +}; +#else +static GenOpFunc *gen_op_ldarx[] = { + &gen_op_ldarx_user, + &gen_op_ldarx_le_user, + &gen_op_ldarx_kernel, + &gen_op_ldarx_le_kernel, + &gen_op_ldarx_64_user, + &gen_op_ldarx_le_64_user, + &gen_op_ldarx_64_kernel, + &gen_op_ldarx_le_64_kernel, +}; +static GenOpFunc *gen_op_stdcx[] = { + &gen_op_stdcx_user, + &gen_op_stdcx_le_user, + &gen_op_stdcx_kernel, + &gen_op_stdcx_le_kernel, + &gen_op_stdcx_64_user, + &gen_op_stdcx_le_64_user, + &gen_op_stdcx_64_kernel, + &gen_op_stdcx_le_64_kernel, +}; +#endif + +/* ldarx */ +GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES) +{ + gen_addr_reg_index(ctx); + op_ldarx(); + gen_op_store_T1_gpr(rD(ctx->opcode)); +} + +/* stdcx. */ +GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_RES) +{ + gen_addr_reg_index(ctx); + gen_op_load_gpr_T1(rS(ctx->opcode)); + op_stdcx(); +} +#endif /* defined(TARGET_PPC64) */ + /* sync */ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM_SYNC) { @@ -2807,6 +2871,26 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW) #endif } +#if defined(TARGET_PPC64) +GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW) +{ +#if defined(CONFIG_USER_ONLY) + RET_PRIVOPC(ctx); +#else + /* Restore CPU state */ + if (unlikely(!ctx->supervisor)) { + RET_PRIVOPC(ctx); + return; + } + if (!ctx->sf_mode) + gen_op_rfid_32(); + else + gen_op_rfid(); + RET_CHG_FLOW(ctx); +#endif +} +#endif + /* sc */ GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW) { @@ -2978,6 +3062,25 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC) } /* mtmsr */ +#if defined(TARGET_PPC64) +GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_MISC) +{ +#if defined(CONFIG_USER_ONLY) + RET_PRIVREG(ctx); +#else + if (unlikely(!ctx->supervisor)) { + RET_PRIVREG(ctx); + return; + } + gen_update_nip(ctx, ctx->nip); + gen_op_load_gpr_T0(rS(ctx->opcode)); + gen_op_store_msr(); + /* Must stop the translation as machine state (may have) changed */ + RET_CHG_FLOW(ctx); +#endif +} +#endif + GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) { #if defined(CONFIG_USER_ONLY) @@ -3313,6 +3416,41 @@ GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC) #endif } +#if defined(TARGET_PPC64) +/* slbia */ +GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI) +{ +#if defined(CONFIG_USER_ONLY) + RET_PRIVOPC(ctx); +#else + if (unlikely(!ctx->supervisor)) { + if (loglevel) + fprintf(logfile, "%s: ! supervisor\n", __func__); + RET_PRIVOPC(ctx); + return; + } + gen_op_slbia(); + RET_STOP(ctx); +#endif +} + +/* slbie */ +GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI) +{ +#if defined(CONFIG_USER_ONLY) + RET_PRIVOPC(ctx); +#else + if (unlikely(!ctx->supervisor)) { + RET_PRIVOPC(ctx); + return; + } + gen_op_load_gpr_T0(rB(ctx->opcode)); + gen_op_slbie(); + RET_STOP(ctx); +#endif +} +#endif + /*** External control ***/ /* Optional: */ #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])() |