diff --git a/gdbstub.c b/gdbstub.c index ed3f5c684..b1e35002d 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -445,7 +445,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n) } case 67: GET_REGL(env->lr); case 68: GET_REGL(env->ctr); - case 69: GET_REG32(ppc_load_xer(env)); + case 69: GET_REGL(env->xer); case 70: GET_REG32(0); /* fpscr */ } } @@ -485,8 +485,8 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) env->ctr = ldtul_p(mem_buf); return sizeof(target_ulong); case 69: - ppc_store_xer(env, ldl_p(mem_buf)); - return 4; + env->xer = ldtul_p(mem_buf); + return sizeof(target_ulong); case 70: /* fpscr */ return 4; diff --git a/monitor.c b/monitor.c index 4d7c782bc..f0a0bc322 100644 --- a/monitor.c +++ b/monitor.c @@ -1582,7 +1582,7 @@ static target_long monitor_get_xer (const struct MonitorDef *md, int val) CPUState *env = mon_get_cpu(); if (!env) return 0; - return ppc_load_xer(env); + return env->xer; } static target_long monitor_get_decr (const struct MonitorDef *md, int val) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index b50a593ed..4422411e7 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -553,8 +553,7 @@ struct CPUPPCState { /* condition register */ uint32_t crf[8]; /* XER */ - /* XXX: We use only 5 fields, but we want to keep the structure aligned */ - uint8_t xer[8]; + target_ulong xer; /* Reservation address */ target_ulong reserve; @@ -831,16 +830,16 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) /*****************************************************************************/ /* Registers definitions */ -#define XER_SO 31 -#define XER_OV 30 -#define XER_CA 29 -#define XER_CMP 8 -#define XER_BC 0 -#define xer_so env->xer[4] -#define xer_ov env->xer[6] -#define xer_ca env->xer[2] -#define xer_cmp env->xer[1] -#define xer_bc env->xer[0] +#define XER_SO 31 +#define XER_OV 30 +#define XER_CA 29 +#define XER_CMP 8 +#define XER_BC 0 +#define xer_so ((env->xer >> XER_SO) & 1) +#define xer_ov ((env->xer >> XER_OV) & 1) +#define xer_ca ((env->xer >> XER_CA) & 1) +#define xer_cmp ((env->xer >> XER_CMP) & 0xFF) +#define xer_bc ((env->xer >> XER_BC) & 0x7F) /* SPR definitions */ #define SPR_MQ (0x000) diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 1dac1511d..befedeacc 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2124,16 +2124,6 @@ void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) } #endif /* !defined (CONFIG_USER_ONLY) */ -target_ulong ppc_load_xer (CPUPPCState *env) -{ - return hreg_load_xer(env); -} - -void ppc_store_xer (CPUPPCState *env, target_ulong value) -{ - hreg_store_xer(env, value); -} - /* GDBstub can read and write MSR... */ void ppc_store_msr (CPUPPCState *env, target_ulong value) { diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h index 34dfa02a5..9666d4b6f 100644 --- a/target-ppc/helper_regs.h +++ b/target-ppc/helper_regs.h @@ -21,24 +21,6 @@ #if !defined(__HELPER_REGS_H__) #define __HELPER_REGS_H__ -static always_inline target_ulong hreg_load_xer (CPUPPCState *env) -{ - return (xer_so << XER_SO) | - (xer_ov << XER_OV) | - (xer_ca << XER_CA) | - (xer_bc << XER_BC) | - (xer_cmp << XER_CMP); -} - -static always_inline void hreg_store_xer (CPUPPCState *env, target_ulong value) -{ - xer_so = (value >> XER_SO) & 0x01; - xer_ov = (value >> XER_OV) & 0x01; - xer_ca = (value >> XER_CA) & 0x01; - xer_cmp = (value >> XER_CMP) & 0xFF; - xer_bc = (value >> XER_BC) & 0x7F; -} - /* Swap temporary saved registers with GPRs */ static always_inline void hreg_swap_gpr_tgpr (CPUPPCState *env) { diff --git a/target-ppc/op.c b/target-ppc/op.c index 5887424c5..a9ab62971 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -58,49 +58,6 @@ void OPPROTO op_store_cr (void) RETURN(); } -void OPPROTO op_load_xer_cr (void) -{ - T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1); - RETURN(); -} - -void OPPROTO op_clear_xer_ov (void) -{ - xer_so = 0; - xer_ov = 0; - RETURN(); -} - -void OPPROTO op_clear_xer_ca (void) -{ - xer_ca = 0; - RETURN(); -} - -void OPPROTO op_load_xer_bc (void) -{ - T1 = xer_bc; - RETURN(); -} - -void OPPROTO op_store_xer_bc (void) -{ - xer_bc = T0; - RETURN(); -} - -void OPPROTO op_load_xer (void) -{ - T0 = hreg_load_xer(env); - RETURN(); -} - -void OPPROTO op_store_xer (void) -{ - hreg_store_xer(env, T0); - RETURN(); -} - #if defined(TARGET_PPC64) void OPPROTO op_store_pri (void) { @@ -574,18 +531,26 @@ void OPPROTO op_dec_ctr (void) /* add */ void OPPROTO op_check_addo (void) { - xer_ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) & + int ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) & ((uint32_t)T2 ^ (uint32_t)T0)) >> 31; - xer_so |= xer_ov; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); + } else { + env->xer &= ~(1 << XER_OV); + } RETURN(); } #if defined(TARGET_PPC64) void OPPROTO op_check_addo_64 (void) { - xer_ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) & + int ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) & ((uint64_t)T2 ^ (uint64_t)T0)) >> 63; - xer_so |= xer_ov; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); + } else { + env->xer &= ~(1 << XER_OV); + } RETURN(); } #endif @@ -594,9 +559,9 @@ void OPPROTO op_check_addo_64 (void) void OPPROTO op_check_addc (void) { if (likely((uint32_t)T0 >= (uint32_t)T2)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } RETURN(); } @@ -605,9 +570,9 @@ void OPPROTO op_check_addc (void) void OPPROTO op_check_addc_64 (void) { if (likely((uint64_t)T0 >= (uint64_t)T2)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } RETURN(); } @@ -633,7 +598,7 @@ void OPPROTO op_add_me (void) { T0 += xer_ca + (-1); if (likely((uint32_t)T1 != 0)) - xer_ca = 1; + env->xer |= (1 << XER_CA); RETURN(); } @@ -642,7 +607,7 @@ void OPPROTO op_add_me_64 (void) { T0 += xer_ca + (-1); if (likely((uint64_t)T1 != 0)) - xer_ca = 1; + env->xer |= (1 << XER_CA); RETURN(); } #endif @@ -855,9 +820,9 @@ void OPPROTO op_nego_64 (void) void OPPROTO op_check_subfc (void) { if (likely((uint32_t)T0 > (uint32_t)T1)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } RETURN(); } @@ -866,9 +831,9 @@ void OPPROTO op_check_subfc (void) void OPPROTO op_check_subfc_64 (void) { if (likely((uint64_t)T0 > (uint64_t)T1)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } RETURN(); } @@ -894,9 +859,9 @@ void OPPROTO op_subfic (void) { T0 = (int32_t)PARAM1 + ~T0 + 1; if ((uint32_t)T0 <= (uint32_t)PARAM1) { - xer_ca = 1; + env->xer |= (1 << XER_CA); } else { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } RETURN(); } @@ -906,9 +871,9 @@ void OPPROTO op_subfic_64 (void) { T0 = (int64_t)PARAM1 + ~T0 + 1; if ((uint64_t)T0 <= (uint64_t)PARAM1) { - xer_ca = 1; + env->xer |= (1 << XER_CA); } else { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } RETURN(); } @@ -919,7 +884,7 @@ void OPPROTO op_subfme (void) { T0 = ~T0 + xer_ca - 1; if (likely((uint32_t)T0 != UINT32_MAX)) - xer_ca = 1; + env->xer |= (1 << XER_CA); RETURN(); } @@ -928,7 +893,7 @@ void OPPROTO op_subfme_64 (void) { T0 = ~T0 + xer_ca - 1; if (likely((uint64_t)T0 != UINT64_MAX)) - xer_ca = 1; + env->xer |= (1 << XER_CA); RETURN(); } #endif @@ -953,9 +918,9 @@ void OPPROTO op_subfze (void) T1 = ~T0; T0 = T1 + xer_ca; if ((uint32_t)T0 < (uint32_t)T1) { - xer_ca = 1; + env->xer |= (1 << XER_CA); } else { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } RETURN(); } @@ -966,9 +931,9 @@ void OPPROTO op_subfze_64 (void) T1 = ~T0; T0 = T1 + xer_ca; if ((uint64_t)T0 < (uint64_t)T1) { - xer_ca = 1; + env->xer |= (1 << XER_CA); } else { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } RETURN(); } @@ -1317,9 +1282,9 @@ void OPPROTO op_srawi (void) T0 = (int32_t)T0 >> PARAM1; if ((int32_t)T1 < 0 && (T1 & mask) != 0) { - xer_ca = 1; + env->xer |= (1 << XER_CA); } else { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } RETURN(); } @@ -1331,9 +1296,9 @@ void OPPROTO op_sradi (void) T0 = (int64_t)T0 >> PARAM1; if ((int64_t)T1 < 0 && ((uint64_t)T1 & mask) != 0) { - xer_ca = 1; + env->xer |= (1 << XER_CA); } else { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } RETURN(); } @@ -1975,7 +1940,7 @@ void OPPROTO op_POWER_nabso (void) /* nabs never overflows */ if (T0 > 0) T0 = -T0; - xer_ov = 0; + env->xer &= ~(1 << XER_OV); RETURN(); } @@ -2189,10 +2154,9 @@ void OPPROTO op_405_check_sat (void) void OPPROTO op_405_check_ovu (void) { if (likely(T0 >= T2)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } else { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } RETURN(); } diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 28bbc98a3..ad52e0d67 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -119,9 +119,9 @@ void do_adde (void) T0 += T1 + xer_ca; if (likely(!((uint32_t)T0 < (uint32_t)T2 || (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } @@ -132,32 +132,42 @@ void do_adde_64 (void) T0 += T1 + xer_ca; if (likely(!((uint64_t)T0 < (uint64_t)T2 || (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } #endif void do_addmeo (void) { + int ov; T1 = T0; T0 += xer_ca + (-1); - xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31; - xer_so |= xer_ov; + ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); + } else { + env->xer &= ~(1 << XER_OV); + } if (likely((uint32_t)T1 != 0)) - xer_ca = 1; + env->xer |= (1 << XER_CA); } #if defined(TARGET_PPC64) void do_addmeo_64 (void) { + int ov; T1 = T0; T0 += xer_ca + (-1); - xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63; - xer_so |= xer_ov; + ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); + } else { + env->xer &= ~(1 << XER_OV); + } if (likely((uint64_t)T1 != 0)) - xer_ca = 1; + env->xer |= (1 << XER_CA); } #endif @@ -165,13 +175,12 @@ void do_divwo (void) { if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || (int32_t)T1 == 0))) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); T0 = (int32_t)T0 / (int32_t)T1; } else { - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); T0 = UINT32_MAX * ((uint32_t)T0 >> 31); } - xer_so |= xer_ov; } #if defined(TARGET_PPC64) @@ -179,24 +188,22 @@ void do_divdo (void) { if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) || (int64_t)T1 == 0))) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); T0 = (int64_t)T0 / (int64_t)T1; } else { - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); T0 = UINT64_MAX * ((uint64_t)T0 >> 63); } - xer_so |= xer_ov; } #endif void do_divwuo (void) { if (likely((uint32_t)T1 != 0)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); T0 = (uint32_t)T0 / (uint32_t)T1; } else { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); T0 = 0; } } @@ -205,11 +212,10 @@ void do_divwuo (void) void do_divduo (void) { if (likely((uint64_t)T1 != 0)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); T0 = (uint64_t)T0 / (uint64_t)T1; } else { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); T0 = 0; } } @@ -220,10 +226,9 @@ void do_mullwo (void) int64_t res = (int64_t)(int32_t)T0 * (int64_t)(int32_t)T1; if (likely((int32_t)res == res)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } else { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } T0 = (int32_t)res; } @@ -238,22 +243,20 @@ void do_mulldo (void) T0 = (int64_t)tl; /* If th != 0 && th != -1, then we had an overflow */ if (likely((uint64_t)(th + 1) <= 1)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } else { - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } - xer_so |= xer_ov; } #endif void do_nego (void) { if (likely((int32_t)T0 != INT32_MIN)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); T0 = -(int32_t)T0; } else { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } } @@ -261,11 +264,10 @@ void do_nego (void) void do_nego_64 (void) { if (likely((int64_t)T0 != INT64_MIN)) { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); T0 = -(int64_t)T0; } else { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } } #endif @@ -275,9 +277,9 @@ void do_subfe (void) T0 = T1 + ~T0 + xer_ca; if (likely((uint32_t)T0 >= (uint32_t)T1 && (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } @@ -287,61 +289,81 @@ void do_subfe_64 (void) T0 = T1 + ~T0 + xer_ca; if (likely((uint64_t)T0 >= (uint64_t)T1 && (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } #endif void do_subfmeo (void) { + int ov; T1 = T0; T0 = ~T0 + xer_ca - 1; - xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31; - xer_so |= xer_ov; + ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); + } else { + env->xer &= ~(1 << XER_OV); + } if (likely((uint32_t)T1 != UINT32_MAX)) - xer_ca = 1; + env->xer |= (1 << XER_CA); } #if defined(TARGET_PPC64) void do_subfmeo_64 (void) { + int ov; T1 = T0; T0 = ~T0 + xer_ca - 1; - xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63; - xer_so |= xer_ov; + ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); + } else { + env->xer &= ~(1 << XER_OV); + } if (likely((uint64_t)T1 != UINT64_MAX)) - xer_ca = 1; + env->xer |= (1 << XER_CA); } #endif void do_subfzeo (void) { + int ov; T1 = T0; T0 = ~T0 + xer_ca; - xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) & - ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31; - xer_so |= xer_ov; - if (likely((uint32_t)T0 >= (uint32_t)~T1)) { - xer_ca = 0; + ov = (((uint32_t)~T1 ^ UINT32_MAX) & + ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { - xer_ca = 1; + env->xer &= ~(1 << XER_OV); + } + if (likely((uint32_t)T0 >= (uint32_t)~T1)) { + env->xer &= ~(1 << XER_CA); + } else { + env->xer |= (1 << XER_CA); } } #if defined(TARGET_PPC64) void do_subfzeo_64 (void) { + int ov; T1 = T0; T0 = ~T0 + xer_ca; - xer_ov = (((uint64_t)~T1 ^ UINT64_MAX) & - ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63; - xer_so |= xer_ov; - if (likely((uint64_t)T0 >= (uint64_t)~T1)) { - xer_ca = 0; + ov = (((uint64_t)~T1 ^ UINT64_MAX) & + ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63; + if (ov) { + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { - xer_ca = 1; + env->xer &= ~(1 << XER_OV); + } + if (likely((uint64_t)T0 >= (uint64_t)~T1)) { + env->xer &= ~(1 << XER_CA); + } else { + env->xer |= (1 << XER_CA); } } #endif @@ -367,20 +389,20 @@ void do_sraw (void) if (likely((uint32_t)T1 != 0)) { ret = (int32_t)T0 >> (T1 & 0x1fUL); if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } else { ret = T0; - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } } else { ret = UINT32_MAX * ((uint32_t)T0 >> 31); if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } T0 = ret; @@ -395,20 +417,20 @@ void do_srad (void) if (likely((uint64_t)T1 != 0)) { ret = (int64_t)T0 >> (T1 & 0x3FUL); if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } else { ret = T0; - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } } else { ret = UINT64_MAX * ((uint64_t)T0 >> 63); if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) { - xer_ca = 0; + env->xer &= ~(1 << XER_CA); } else { - xer_ca = 1; + env->xer |= (1 << XER_CA); } } T0 = ret; @@ -1478,14 +1500,13 @@ void do_POWER_abso (void) { if ((int32_t)T0 == INT32_MIN) { T0 = INT32_MAX; - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else if ((int32_t)T0 < 0) { T0 = -T0; - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } else { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } - xer_so |= xer_ov; } void do_POWER_clcs (void) @@ -1538,19 +1559,18 @@ void do_POWER_divo (void) (int32_t)T1 == 0) { T0 = UINT32_MAX * ((uint32_t)T0 >> 31); env->spr[SPR_MQ] = 0; - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; env->spr[SPR_MQ] = tmp % T1; tmp /= (int32_t)T1; if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) { - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } T0 = tmp; } - xer_so |= xer_ov; } void do_POWER_divs (void) @@ -1571,13 +1591,12 @@ void do_POWER_divso (void) (int32_t)T1 == 0) { T0 = UINT32_MAX * ((uint32_t)T0 >> 31); env->spr[SPR_MQ] = 0; - xer_ov = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { T0 = (int32_t)T0 / (int32_t)T1; env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1; - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } - xer_so |= xer_ov; } void do_POWER_dozo (void) @@ -1587,14 +1606,13 @@ void do_POWER_dozo (void) T0 = T1 - T0; if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) & ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } } else { T0 = 0; - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } } @@ -1621,10 +1639,9 @@ void do_POWER_mulo (void) env->spr[SPR_MQ] = tmp >> 32; T0 = tmp; if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) { - xer_ov = 1; - xer_so = 1; + env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { - xer_ov = 0; + env->xer &= ~(1 << XER_OV); } } diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 96b3699e7..c5a9735c8 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -62,6 +62,7 @@ static TCGv cpu_crf[8]; static TCGv cpu_nip; static TCGv cpu_ctr; static TCGv cpu_lr; +static TCGv cpu_xer; /* dyngen register indexes */ static TCGv cpu_T[3]; @@ -175,6 +176,9 @@ void ppc_translate_init(void) cpu_lr = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, offsetof(CPUState, lr), "lr"); + cpu_xer = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, + offsetof(CPUState, xer), "xer"); + /* register helpers */ #undef DEF_HELPER #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name); @@ -1057,7 +1061,7 @@ GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) #endif gen_op_check_addc(); } else { - gen_op_clear_xer_ca(); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_CA)); } tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); } @@ -1077,7 +1081,7 @@ GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) #endif gen_op_check_addc(); } else { - gen_op_clear_xer_ca(); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_CA)); } tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); gen_set_Rc0(ctx); @@ -2852,7 +2856,7 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING) if (ra == 0) { ra = rb; } - gen_op_load_xer_bc(); + tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F); op_ldstsx(lswx, rD(ctx->opcode), ra, rb); } @@ -2876,7 +2880,7 @@ GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING) /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); gen_addr_reg_index(cpu_T[0], ctx); - gen_op_load_xer_bc(); + tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F); op_ldsts(stsw, rS(ctx->opcode)); } @@ -3509,10 +3513,9 @@ GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B) /* mcrxr */ GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC) { - gen_op_load_xer_cr(); - tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); - gen_op_clear_xer_ov(); - gen_op_clear_xer_ca(); + tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer); + tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA)); } /* mfcr */ @@ -4310,10 +4313,12 @@ GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR) } /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_op_load_xer_bc(); - gen_op_load_xer_cmp(); + tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F); + tcg_gen_shri_tl(cpu_T[2], cpu_xer, XER_CMP); + tcg_gen_andi_tl(cpu_T[2], cpu_T[2], 0xFF); op_POWER_lscbx(rD(ctx->opcode), ra, rb); - gen_op_store_xer_bc(); + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F); + tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]); if (unlikely(Rc(ctx->opcode) != 0)) gen_set_Rc0(ctx); } @@ -5500,7 +5505,8 @@ GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC) tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); gen_op_440_dlmzb(); tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); - gen_op_store_xer_bc(); + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F); + tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]); if (Rc(ctx->opcode)) { gen_op_440_dlmzb_update_Rc(); tcg_gen_andi_i32(cpu_crf[0], cpu_T[0], 0xf); @@ -6391,7 +6397,7 @@ void cpu_dump_state (CPUState *env, FILE *f, int i; cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n", - env->nip, env->lr, env->ctr, hreg_load_xer(env)); + env->nip, env->lr, env->ctr, env->xer); cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n", env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx); #if !defined(NO_TIMER_DUMP) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 67951bf20..02590ae6e 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -99,12 +99,12 @@ static void spr_write_clear (void *opaque, int sprn) /* XER */ static void spr_read_xer (void *opaque, int sprn) { - gen_op_load_xer(); + tcg_gen_mov_tl(cpu_T[0], cpu_xer); } static void spr_write_xer (void *opaque, int sprn) { - gen_op_store_xer(); + tcg_gen_mov_tl(cpu_xer, cpu_T[0]); } /* LR */