提交 3d7b417e 编写于 作者: A aurel32

target-ppc: Convert XER accesses to TCG

Define XER bits as a single register and access them individually to
avoid defining 5 32-bit registers (TCG doesn't permit to map 8-bit
registers).
Signed-off-by: NAurelien Jarno <aurelien@aurel32.net>

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