target/sparc: Remove CC_OP_TADDTV, CC_OP_TSUBTV
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
f828df7443
commit
68524e83f8
@ -21,198 +21,12 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static inline uint32_t get_NZ_icc(int32_t dst)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (dst == 0) {
|
||||
ret = PSR_ZERO;
|
||||
} else if (dst < 0) {
|
||||
ret = PSR_NEG;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static inline uint32_t get_NZ_xcc(target_long dst)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (!dst) {
|
||||
ret = PSR_ZERO;
|
||||
} else if (dst < 0) {
|
||||
ret = PSR_NEG;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (dst < src1) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (dst < src1) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_add_xcc(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_xcc(CC_DST);
|
||||
ret |= get_C_add_xcc(CC_DST, CC_SRC);
|
||||
ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_add_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_add_xcc(CC_DST, CC_SRC);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t compute_C_add(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_add_icc(CC_DST, CC_SRC);
|
||||
}
|
||||
|
||||
static uint32_t compute_all_taddtv(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_add_icc(CC_DST, CC_SRC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (src1 < src2) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (src1 < src2) {
|
||||
ret = PSR_CARRY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
|
||||
ret = PSR_OVF;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_all_sub_xcc(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_xcc(CC_DST);
|
||||
ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
|
||||
ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t compute_C_sub_xcc(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_sub_xcc(CC_SRC, CC_SRC2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t compute_C_sub(CPUSPARCState *env)
|
||||
{
|
||||
return get_C_sub_icc(CC_SRC, CC_SRC2);
|
||||
}
|
||||
|
||||
static uint32_t compute_all_tsubtv(CPUSPARCState *env)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = get_NZ_icc(CC_DST);
|
||||
ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct CCTable {
|
||||
uint32_t (*compute_all)(CPUSPARCState *env); /* return all the flags */
|
||||
uint32_t (*compute_c)(CPUSPARCState *env); /* return the C flag */
|
||||
} CCTable;
|
||||
|
||||
static const CCTable icc_table[CC_OP_NB] = {
|
||||
/* CC_OP_DYNAMIC should never happen */
|
||||
[CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
|
||||
[CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
|
||||
};
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
static const CCTable xcc_table[CC_OP_NB] = {
|
||||
/* CC_OP_DYNAMIC should never happen */
|
||||
[CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
|
||||
[CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
|
||||
};
|
||||
#endif
|
||||
|
||||
void helper_compute_psr(CPUSPARCState *env)
|
||||
{
|
||||
if (CC_OP == CC_OP_FLAGS) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t icc = icc_table[CC_OP].compute_all(env);
|
||||
#ifdef TARGET_SPARC64
|
||||
uint32_t xcc = xcc_table[CC_OP].compute_all(env);
|
||||
|
||||
env->cc_N = deposit64(-(icc & PSR_NEG), 32, 32, -(xcc & PSR_NEG));
|
||||
env->cc_V = deposit64(-(icc & PSR_OVF), 32, 32, -(xcc & PSR_OVF));
|
||||
env->icc_C = (uint64_t)icc << (32 - PSR_CARRY_SHIFT);
|
||||
env->xcc_C = (xcc >> PSR_CARRY_SHIFT) & 1;
|
||||
env->xcc_Z = ~xcc & PSR_ZERO;
|
||||
#else
|
||||
env->cc_N = -(icc & PSR_NEG);
|
||||
env->cc_V = -(icc & PSR_OVF);
|
||||
env->icc_C = (icc >> PSR_CARRY_SHIFT) & 1;
|
||||
#endif
|
||||
env->icc_Z = ~icc & PSR_ZERO;
|
||||
|
||||
CC_OP = CC_OP_FLAGS;
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
uint32_t helper_compute_C_icc(CPUSPARCState *env)
|
||||
@ -224,5 +38,5 @@ uint32_t helper_compute_C_icc(CPUSPARCState *env)
|
||||
return env->icc_C;
|
||||
#endif
|
||||
}
|
||||
return icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -150,8 +150,6 @@ enum {
|
||||
enum {
|
||||
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
||||
CC_OP_FLAGS, /* all cc are back in cc_*_[NZCV] registers */
|
||||
CC_OP_TADDTV, /* modify all flags except V, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_TSUBTV, /* modify all flags except V, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_NB,
|
||||
};
|
||||
|
||||
|
@ -156,7 +156,7 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
|
||||
target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
target_ulong dst;
|
||||
target_ulong dst, v;
|
||||
|
||||
/* Tag overflow occurs if either input has bits 0 or 1 set. */
|
||||
if ((src1 | src2) & 3) {
|
||||
@ -166,13 +166,23 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
dst = src1 + src2;
|
||||
|
||||
/* Tag overflow occurs if the addition overflows. */
|
||||
if (~(src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
|
||||
v = ~(src1 ^ src2) & (src1 ^ dst);
|
||||
if (v & (1u << 31)) {
|
||||
goto tag_overflow;
|
||||
}
|
||||
|
||||
/* Only modify the CC after any exceptions have been generated. */
|
||||
env->cc_src = src1;
|
||||
env->cc_src2 = src2;
|
||||
env->cc_V = v;
|
||||
env->cc_N = dst;
|
||||
env->icc_Z = dst;
|
||||
#ifdef TARGET_SPARC64
|
||||
env->xcc_Z = dst;
|
||||
env->icc_C = dst ^ src1 ^ src2;
|
||||
env->xcc_C = dst < src1;
|
||||
#else
|
||||
env->icc_C = dst < src1;
|
||||
#endif
|
||||
|
||||
return dst;
|
||||
|
||||
tag_overflow:
|
||||
@ -182,7 +192,7 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
target_ulong dst;
|
||||
target_ulong dst, v;
|
||||
|
||||
/* Tag overflow occurs if either input has bits 0 or 1 set. */
|
||||
if ((src1 | src2) & 3) {
|
||||
@ -192,13 +202,23 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
|
||||
dst = src1 - src2;
|
||||
|
||||
/* Tag overflow occurs if the subtraction overflows. */
|
||||
if ((src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
|
||||
v = (src1 ^ src2) & (src1 ^ dst);
|
||||
if (v & (1u << 31)) {
|
||||
goto tag_overflow;
|
||||
}
|
||||
|
||||
/* Only modify the CC after any exceptions have been generated. */
|
||||
env->cc_src = src1;
|
||||
env->cc_src2 = src2;
|
||||
env->cc_V = v;
|
||||
env->cc_N = dst;
|
||||
env->icc_Z = dst;
|
||||
#ifdef TARGET_SPARC64
|
||||
env->xcc_Z = dst;
|
||||
env->icc_C = dst ^ src1 ^ src2;
|
||||
env->xcc_C = src1 < src2;
|
||||
#else
|
||||
env->icc_C = src1 < src2;
|
||||
#endif
|
||||
|
||||
return dst;
|
||||
|
||||
tag_overflow:
|
||||
|
@ -3598,8 +3598,8 @@ TRANS(SUB, ALL, do_arith, a, CC_OP_FLAGS,
|
||||
|
||||
TRANS(TADDcc, ALL, do_arith, a, CC_OP_FLAGS, NULL, NULL, gen_op_taddcc)
|
||||
TRANS(TSUBcc, ALL, do_arith, a, CC_OP_FLAGS, NULL, NULL, gen_op_tsubcc)
|
||||
TRANS(TADDccTV, ALL, do_arith, a, CC_OP_TADDTV, NULL, NULL, gen_op_taddcctv)
|
||||
TRANS(TSUBccTV, ALL, do_arith, a, CC_OP_TSUBTV, NULL, NULL, gen_op_tsubcctv)
|
||||
TRANS(TADDccTV, ALL, do_arith, a, CC_OP_FLAGS, NULL, NULL, gen_op_taddcctv)
|
||||
TRANS(TSUBccTV, ALL, do_arith, a, CC_OP_FLAGS, NULL, NULL, gen_op_tsubcctv)
|
||||
|
||||
TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
|
||||
TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
|
||||
|
Loading…
Reference in New Issue
Block a user