mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
Patch queue for ppc - 2015-01-07
New year's release. This time's highlights: - E500: More RAM support - pseries: New SLOF release - Migration fixes - Simplify USB spawning logic, removes support for explicit usb=off - TCG: Simple untansactional TM emulation -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJUrU6JAAoJECszeR4D/txgclcQALbuKWkpj4O85zfC3MbbC/ld dORPmHFI0OChyN9YOU8UKtetIQK6FlbBB+ZA0VVOusEVpiQ/bmj+iGelTRf4R08a 5pcqlF8yQPoWrIxH6JK+OJqg7rrNJSUSrlYnMQKsZudmvL6r1VzFCcGoL+lIzIi8 uGoD+ngBHdEjUKRD+BxnOdkBwIm5K6FlbK1uynN1Cj9FLkYw9RsmVNqNPtd0vYSn 2Qi4XPXZoLxwVM2x/M89d1HCW41eBeLhBr28KuXR4bphIS1eyZY5pBlS35LPPt9+ KWo9xvkT2y+18T968vwKHLmQlqN62N0rotSFlNCpnvoo3bd6KexsSkjg497HsUR9 eOHdgVOBOHReWmmqtjgECgjzBmI2hEY8fEHg8ktOdOJ0YupcGdbWui5+r0ObYbnp BKEvPiAo3/+XSASbW6NkAxcWvFt6DQx8nh5Y+9XFq1Q6Ge962SuCldzExzTo/8iQ kSxTeECsHZb5Ch0vPyrOICeWxeBFJYW6lWVl59qSS0NzHflBD/Nns9TBGO8LJxm6 6NLmAu47Q7KW4xYZOXve6+I5Ze20szasiPF2v9BeV6TeKdSCd2krut1D8lUurPQM EdtRmAKOCRQnC3x/lzQrrRxszoCqa3OSStO9RZ5TaGeq+7zec5J3g/9iomgGtMyz t4Q8k66Mez8BhviG0SoS =28q1 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging Patch queue for ppc - 2015-01-07 New year's release. This time's highlights: - E500: More RAM support - pseries: New SLOF release - Migration fixes - Simplify USB spawning logic, removes support for explicit usb=off - TCG: Simple untansactional TM emulation # gpg: Signature made Wed 07 Jan 2015 15:19:37 GMT using RSA key ID 03FEDC60 # gpg: Good signature from "Alexander Graf <agraf@suse.de>" # gpg: aka "Alexander Graf <alex@csgraf.de>" * remotes/agraf/tags/signed-ppc-for-upstream: (37 commits) hw/ppc/mac_newworld: simplify usb controller creation logic hw/ppc/spapr: simplify usb controller creation logic hw/ppc/mac_newworld: QOMified mac99 machines hw/usb: simplified usb_enabled hw/machine: added machine_usb wrapper hw/ppc: modified the condition for usb controllers to be created for some ppc machines target-ppc: Cast ssize_t to size_t before printing with %zx target-ppc: Mark SR() and gen_sync_exception() as !CONFIG_USER_ONLY PPC: e500: Fix GPIO controller interrupt number target-ppc: Introduce Privileged TM Noops target-ppc: Introduce tcheck target-ppc: Introduce TM Noops target-ppc: Introduce tbegin target-ppc: Introduce TEXASRU Bit Fields target-ppc: Power8 Supports Transactional Memory target-ppc: Introduce tm_enabled Bit to CPU State target-ppc: Introduce Feature Flag for Transactional Memory target-ppc: Introduce Instruction Type for Transactional Memory pseries: Update SLOF firmware image to 20141202 PPC: Fix crash on spapr_tce_table_finalize() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
97052d64e4
20 changed files with 538 additions and 156 deletions
|
@ -203,6 +203,7 @@ struct DisasContext {
|
|||
int altivec_enabled;
|
||||
int vsx_enabled;
|
||||
int spe_enabled;
|
||||
int tm_enabled;
|
||||
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
|
||||
int singlestep_enabled;
|
||||
uint64_t insns_flags;
|
||||
|
@ -250,26 +251,10 @@ static inline void gen_reset_fpstatus(void)
|
|||
gen_helper_reset_fpstatus(cpu_env);
|
||||
}
|
||||
|
||||
static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc)
|
||||
static inline void gen_compute_fprf(TCGv_i64 arg)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
if (set_fprf != 0) {
|
||||
/* This case might be optimized later */
|
||||
tcg_gen_movi_i32(t0, 1);
|
||||
gen_helper_compute_fprf(t0, cpu_env, arg, t0);
|
||||
if (unlikely(set_rc)) {
|
||||
tcg_gen_mov_i32(cpu_crf[1], t0);
|
||||
}
|
||||
gen_helper_float_check_status(cpu_env);
|
||||
} else if (unlikely(set_rc)) {
|
||||
/* We always need to compute fpcc */
|
||||
tcg_gen_movi_i32(t0, 0);
|
||||
gen_helper_compute_fprf(t0, cpu_env, arg, t0);
|
||||
tcg_gen_mov_i32(cpu_crf[1], t0);
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
gen_helper_compute_fprf(cpu_env, arg);
|
||||
gen_helper_float_check_status(cpu_env);
|
||||
}
|
||||
|
||||
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
|
||||
|
@ -346,11 +331,13 @@ static inline void gen_stop_exception(DisasContext *ctx)
|
|||
ctx->exception = POWERPC_EXCP_STOP;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* No need to update nip here, as execution flow will change */
|
||||
static inline void gen_sync_exception(DisasContext *ctx)
|
||||
{
|
||||
ctx->exception = POWERPC_EXCP_SYNC;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
|
||||
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
|
||||
|
@ -452,7 +439,10 @@ EXTRACT_HELPER(ME, 1, 5);
|
|||
EXTRACT_HELPER(TO, 21, 5);
|
||||
|
||||
EXTRACT_HELPER(CRM, 12, 8);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
EXTRACT_HELPER(SR, 16, 4);
|
||||
#endif
|
||||
|
||||
/* mtfsf/mtfsfi */
|
||||
EXTRACT_HELPER(FPBF, 23, 3);
|
||||
|
@ -2077,6 +2067,21 @@ static void gen_srd(DisasContext *ctx)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
static void gen_set_cr1_from_fpscr(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
|
||||
tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
#else
|
||||
static void gen_set_cr1_from_fpscr(DisasContext *ctx)
|
||||
{
|
||||
tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** Floating-Point arithmetic ***/
|
||||
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
|
||||
static void gen_f##name(DisasContext *ctx) \
|
||||
|
@ -2095,8 +2100,12 @@ static void gen_f##name(DisasContext *ctx) \
|
|||
gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
|
||||
cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf, \
|
||||
Rc(ctx->opcode) != 0); \
|
||||
if (set_fprf) { \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) { \
|
||||
gen_set_cr1_from_fpscr(ctx); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
|
||||
|
@ -2120,8 +2129,12 @@ static void gen_f##name(DisasContext *ctx) \
|
|||
gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
|
||||
cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
|
||||
set_fprf, Rc(ctx->opcode) != 0); \
|
||||
if (set_fprf) { \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) { \
|
||||
gen_set_cr1_from_fpscr(ctx); \
|
||||
} \
|
||||
}
|
||||
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
|
||||
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
|
||||
|
@ -2144,8 +2157,12 @@ static void gen_f##name(DisasContext *ctx) \
|
|||
gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env, \
|
||||
cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
|
||||
set_fprf, Rc(ctx->opcode) != 0); \
|
||||
if (set_fprf) { \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) { \
|
||||
gen_set_cr1_from_fpscr(ctx); \
|
||||
} \
|
||||
}
|
||||
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
|
||||
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
|
||||
|
@ -2163,8 +2180,12 @@ static void gen_f##name(DisasContext *ctx) \
|
|||
gen_reset_fpstatus(); \
|
||||
gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
|
||||
cpu_fpr[rB(ctx->opcode)]); \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
|
||||
set_fprf, Rc(ctx->opcode) != 0); \
|
||||
if (set_fprf) { \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) { \
|
||||
gen_set_cr1_from_fpscr(ctx); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
|
||||
|
@ -2179,8 +2200,12 @@ static void gen_f##name(DisasContext *ctx) \
|
|||
gen_reset_fpstatus(); \
|
||||
gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env, \
|
||||
cpu_fpr[rB(ctx->opcode)]); \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
|
||||
set_fprf, Rc(ctx->opcode) != 0); \
|
||||
if (set_fprf) { \
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]); \
|
||||
} \
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) { \
|
||||
gen_set_cr1_from_fpscr(ctx); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* fadd - fadds */
|
||||
|
@ -2213,7 +2238,10 @@ static void gen_frsqrtes(DisasContext *ctx)
|
|||
cpu_fpr[rB(ctx->opcode)]);
|
||||
gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
|
||||
cpu_fpr[rD(ctx->opcode)]);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* fsel */
|
||||
|
@ -2234,7 +2262,10 @@ static void gen_fsqrt(DisasContext *ctx)
|
|||
gen_reset_fpstatus();
|
||||
gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
|
||||
cpu_fpr[rB(ctx->opcode)]);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_fsqrts(DisasContext *ctx)
|
||||
|
@ -2250,7 +2281,10 @@ static void gen_fsqrts(DisasContext *ctx)
|
|||
cpu_fpr[rB(ctx->opcode)]);
|
||||
gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
|
||||
cpu_fpr[rD(ctx->opcode)]);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)]);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Floating-Point multiply-and-add ***/
|
||||
|
@ -2370,7 +2404,9 @@ static void gen_fabs(DisasContext *ctx)
|
|||
}
|
||||
tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
|
||||
~(1ULL << 63));
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
|
||||
if (unlikely(Rc(ctx->opcode))) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* fmr - fmr. */
|
||||
|
@ -2382,7 +2418,9 @@ static void gen_fmr(DisasContext *ctx)
|
|||
return;
|
||||
}
|
||||
tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
|
||||
if (unlikely(Rc(ctx->opcode))) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* fnabs */
|
||||
|
@ -2395,7 +2433,9 @@ static void gen_fnabs(DisasContext *ctx)
|
|||
}
|
||||
tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
|
||||
1ULL << 63);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
|
||||
if (unlikely(Rc(ctx->opcode))) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* fneg */
|
||||
|
@ -2408,7 +2448,9 @@ static void gen_fneg(DisasContext *ctx)
|
|||
}
|
||||
tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
|
||||
1ULL << 63);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
|
||||
if (unlikely(Rc(ctx->opcode))) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* fcpsgn: PowerPC 2.05 specification */
|
||||
|
@ -2421,7 +2463,9 @@ static void gen_fcpsgn(DisasContext *ctx)
|
|||
}
|
||||
tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
|
||||
cpu_fpr[rB(ctx->opcode)], 0, 63);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
|
||||
if (unlikely(Rc(ctx->opcode))) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_fmrgew(DisasContext *ctx)
|
||||
|
@ -2479,7 +2523,9 @@ static void gen_mffs(DisasContext *ctx)
|
|||
}
|
||||
gen_reset_fpstatus();
|
||||
tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
|
||||
gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
|
||||
if (unlikely(Rc(ctx->opcode))) {
|
||||
gen_set_cr1_from_fpscr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* mtfsb0 */
|
||||
|
@ -6743,7 +6789,7 @@ static void gen_st##name(DisasContext *ctx) \
|
|||
tcg_temp_free(EA); \
|
||||
}
|
||||
|
||||
#define GEN_VR_LVE(name, opc2, opc3) \
|
||||
#define GEN_VR_LVE(name, opc2, opc3, size) \
|
||||
static void gen_lve##name(DisasContext *ctx) \
|
||||
{ \
|
||||
TCGv EA; \
|
||||
|
@ -6755,13 +6801,16 @@ static void gen_lve##name(DisasContext *ctx) \
|
|||
gen_set_access_type(ctx, ACCESS_INT); \
|
||||
EA = tcg_temp_new(); \
|
||||
gen_addr_reg_index(ctx, EA); \
|
||||
if (size > 1) { \
|
||||
tcg_gen_andi_tl(EA, EA, ~(size - 1)); \
|
||||
} \
|
||||
rs = gen_avr_ptr(rS(ctx->opcode)); \
|
||||
gen_helper_lve##name(cpu_env, rs, EA); \
|
||||
tcg_temp_free(EA); \
|
||||
tcg_temp_free_ptr(rs); \
|
||||
}
|
||||
|
||||
#define GEN_VR_STVE(name, opc2, opc3) \
|
||||
#define GEN_VR_STVE(name, opc2, opc3, size) \
|
||||
static void gen_stve##name(DisasContext *ctx) \
|
||||
{ \
|
||||
TCGv EA; \
|
||||
|
@ -6773,6 +6822,9 @@ static void gen_stve##name(DisasContext *ctx) \
|
|||
gen_set_access_type(ctx, ACCESS_INT); \
|
||||
EA = tcg_temp_new(); \
|
||||
gen_addr_reg_index(ctx, EA); \
|
||||
if (size > 1) { \
|
||||
tcg_gen_andi_tl(EA, EA, ~(size - 1)); \
|
||||
} \
|
||||
rs = gen_avr_ptr(rS(ctx->opcode)); \
|
||||
gen_helper_stve##name(cpu_env, rs, EA); \
|
||||
tcg_temp_free(EA); \
|
||||
|
@ -6783,17 +6835,17 @@ GEN_VR_LDX(lvx, 0x07, 0x03);
|
|||
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
|
||||
GEN_VR_LDX(lvxl, 0x07, 0x0B);
|
||||
|
||||
GEN_VR_LVE(bx, 0x07, 0x00);
|
||||
GEN_VR_LVE(hx, 0x07, 0x01);
|
||||
GEN_VR_LVE(wx, 0x07, 0x02);
|
||||
GEN_VR_LVE(bx, 0x07, 0x00, 1);
|
||||
GEN_VR_LVE(hx, 0x07, 0x01, 2);
|
||||
GEN_VR_LVE(wx, 0x07, 0x02, 4);
|
||||
|
||||
GEN_VR_STX(svx, 0x07, 0x07);
|
||||
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
|
||||
GEN_VR_STX(svxl, 0x07, 0x0F);
|
||||
|
||||
GEN_VR_STVE(bx, 0x07, 0x04);
|
||||
GEN_VR_STVE(hx, 0x07, 0x05);
|
||||
GEN_VR_STVE(wx, 0x07, 0x06);
|
||||
GEN_VR_STVE(bx, 0x07, 0x04, 1);
|
||||
GEN_VR_STVE(hx, 0x07, 0x05, 2);
|
||||
GEN_VR_STVE(wx, 0x07, 0x06, 4);
|
||||
|
||||
static void gen_lvsl(DisasContext *ctx)
|
||||
{
|
||||
|
@ -8205,21 +8257,6 @@ static inline TCGv_ptr gen_fprp_ptr(int reg)
|
|||
return r;
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
static void gen_set_cr1_from_fpscr(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
|
||||
tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
#else
|
||||
static void gen_set_cr1_from_fpscr(DisasContext *ctx)
|
||||
{
|
||||
tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define GEN_DFP_T_A_B_Rc(name) \
|
||||
static void gen_##name(DisasContext *ctx) \
|
||||
{ \
|
||||
|
@ -9642,6 +9679,88 @@ GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE
|
|||
GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); //
|
||||
GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); //
|
||||
|
||||
static void gen_tbegin(DisasContext *ctx)
|
||||
{
|
||||
if (unlikely(!ctx->tm_enabled)) {
|
||||
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
|
||||
return;
|
||||
}
|
||||
gen_helper_tbegin(cpu_env);
|
||||
}
|
||||
|
||||
#define GEN_TM_NOOP(name) \
|
||||
static inline void gen_##name(DisasContext *ctx) \
|
||||
{ \
|
||||
if (unlikely(!ctx->tm_enabled)) { \
|
||||
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
|
||||
return; \
|
||||
} \
|
||||
/* Because tbegin always fails in QEMU, these user \
|
||||
* space instructions all have a simple implementation: \
|
||||
* \
|
||||
* CR[0] = 0b0 || MSR[TS] || 0b0 \
|
||||
* = 0b0 || 0b00 || 0b0 \
|
||||
*/ \
|
||||
tcg_gen_movi_i32(cpu_crf[0], 0); \
|
||||
}
|
||||
|
||||
GEN_TM_NOOP(tend);
|
||||
GEN_TM_NOOP(tabort);
|
||||
GEN_TM_NOOP(tabortwc);
|
||||
GEN_TM_NOOP(tabortwci);
|
||||
GEN_TM_NOOP(tabortdc);
|
||||
GEN_TM_NOOP(tabortdci);
|
||||
GEN_TM_NOOP(tsr);
|
||||
|
||||
static void gen_tcheck(DisasContext *ctx)
|
||||
{
|
||||
if (unlikely(!ctx->tm_enabled)) {
|
||||
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
|
||||
return;
|
||||
}
|
||||
/* Because tbegin always fails, the tcheck implementation
|
||||
* is simple:
|
||||
*
|
||||
* CR[CRF] = TDOOMED || MSR[TS] || 0b0
|
||||
* = 0b1 || 0b00 || 0b0
|
||||
*/
|
||||
tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0x8);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#define GEN_TM_PRIV_NOOP(name) \
|
||||
static inline void gen_##name(DisasContext *ctx) \
|
||||
{ \
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define GEN_TM_PRIV_NOOP(name) \
|
||||
static inline void gen_##name(DisasContext *ctx) \
|
||||
{ \
|
||||
if (unlikely(ctx->pr)) { \
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); \
|
||||
return; \
|
||||
} \
|
||||
if (unlikely(!ctx->tm_enabled)) { \
|
||||
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
|
||||
return; \
|
||||
} \
|
||||
/* Because tbegin always fails, the implementation is \
|
||||
* simple: \
|
||||
* \
|
||||
* CR[0] = 0b0 || MSR[TS] || 0b0 \
|
||||
* = 0b0 || 0b00 | 0b0 \
|
||||
*/ \
|
||||
tcg_gen_movi_i32(cpu_crf[0], 0); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
GEN_TM_PRIV_NOOP(treclaim);
|
||||
GEN_TM_PRIV_NOOP(trechkpt);
|
||||
|
||||
static opcode_t opcodes[] = {
|
||||
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE),
|
||||
GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
|
||||
|
@ -11054,6 +11173,29 @@ GEN_SPEOP_LDST(evstwhe, 0x18, 2),
|
|||
GEN_SPEOP_LDST(evstwho, 0x1A, 2),
|
||||
GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
|
||||
GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
|
||||
|
||||
GEN_HANDLER2_E(tbegin, "tbegin", 0x1F, 0x0E, 0x14, 0x01DFF800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tend, "tend", 0x1F, 0x0E, 0x15, 0x01FFF800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tabort, "tabort", 0x1F, 0x0E, 0x1C, 0x03E0F800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tabortwc, "tabortwc", 0x1F, 0x0E, 0x18, 0x00000000, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tabortwci, "tabortwci", 0x1F, 0x0E, 0x1A, 0x00000000, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tabortdc, "tabortdc", 0x1F, 0x0E, 0x19, 0x00000000, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tabortdci, "tabortdci", 0x1F, 0x0E, 0x1B, 0x00000000, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tsr, "tsr", 0x1F, 0x0E, 0x17, 0x03DFF800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(tcheck, "tcheck", 0x1F, 0x0E, 0x16, 0x007FF800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(treclaim, "treclaim", 0x1F, 0x0E, 0x1D, 0x03E0F800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 0x03FFF800, \
|
||||
PPC_NONE, PPC2_TM),
|
||||
};
|
||||
|
||||
#include "helper_regs.h"
|
||||
|
@ -11311,6 +11453,13 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
|
|||
} else {
|
||||
ctx.vsx_enabled = 0;
|
||||
}
|
||||
#if defined(TARGET_PPC64)
|
||||
if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
|
||||
ctx.tm_enabled = msr_tm;
|
||||
} else {
|
||||
ctx.tm_enabled = 0;
|
||||
}
|
||||
#endif
|
||||
if ((env->flags & POWERPC_FLAG_SE) && msr_se)
|
||||
ctx.singlestep_enabled = CPU_SINGLE_STEP;
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue