mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
microblaze: Improve subkc
Move code from the helper into the translator. The remaining helper parts can reuse helper_addkc, making it possible to remove helper_subkc entirely. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
parent
7e9e433008
commit
e0a42ebc08
@ -3,7 +3,6 @@
|
||||
DEF_HELPER_1(raise_exception, void, i32)
|
||||
DEF_HELPER_0(debug, void)
|
||||
DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
|
||||
DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
|
||||
DEF_HELPER_2(cmp, i32, i32, i32)
|
||||
DEF_HELPER_2(cmpu, i32, i32, i32)
|
||||
|
||||
|
@ -138,28 +138,6 @@ uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
|
||||
return ncf;
|
||||
}
|
||||
|
||||
uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
|
||||
{
|
||||
uint32_t d, cf = 1, ncf;
|
||||
|
||||
if (c)
|
||||
cf = env->sregs[SR_MSR] >> 31;
|
||||
assert(cf == 0 || cf == 1);
|
||||
d = b + ~a + cf;
|
||||
|
||||
if (!k) {
|
||||
ncf = compute_carry(b, ~a, cf);
|
||||
assert(ncf == 0 || ncf == 1);
|
||||
if (ncf)
|
||||
env->sregs[SR_MSR] |= MSR_C | MSR_CC;
|
||||
else
|
||||
env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
|
||||
}
|
||||
D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
|
||||
d, a, b, cf, ncf, k, c));
|
||||
return d;
|
||||
}
|
||||
|
||||
static inline int div_prepare(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (b == 0) {
|
||||
|
@ -247,6 +247,7 @@ static void dec_add(DisasContext *dc)
|
||||
static void dec_sub(DisasContext *dc)
|
||||
{
|
||||
unsigned int u, cmp, k, c;
|
||||
TCGv cf, na;
|
||||
|
||||
u = dc->imm & 2;
|
||||
k = dc->opcode & 4;
|
||||
@ -261,24 +262,57 @@ static void dec_sub(DisasContext *dc)
|
||||
else
|
||||
gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
|
||||
}
|
||||
} else {
|
||||
LOG_DIS("sub%s%s r%d, r%d r%d\n",
|
||||
k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb);
|
||||
|
||||
if (!k || c) {
|
||||
TCGv t;
|
||||
t = tcg_temp_new();
|
||||
if (dc->rd)
|
||||
gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
|
||||
tcg_const_tl(k), tcg_const_tl(c));
|
||||
else
|
||||
gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
|
||||
tcg_const_tl(k), tcg_const_tl(c));
|
||||
tcg_temp_free(t);
|
||||
}
|
||||
else if (dc->rd)
|
||||
tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DIS("sub%s%s r%d, r%d r%d\n",
|
||||
k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb);
|
||||
|
||||
/* Take care of the easy cases first. */
|
||||
if (k) {
|
||||
/* k - keep carry, no need to update MSR. */
|
||||
/* If rd == r0, it's a nop. */
|
||||
if (dc->rd) {
|
||||
tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
|
||||
|
||||
if (c) {
|
||||
/* c - Add carry into the result. */
|
||||
cf = tcg_temp_new();
|
||||
|
||||
read_carry(dc, cf);
|
||||
tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
|
||||
tcg_temp_free(cf);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* From now on, we can assume k is zero. So we need to update MSR. */
|
||||
/* Extract carry. And complement a into na. */
|
||||
cf = tcg_temp_new();
|
||||
na = tcg_temp_new();
|
||||
if (c) {
|
||||
read_carry(dc, cf);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cf, 1);
|
||||
}
|
||||
|
||||
/* d = b + ~a + c. carry defaults to 1. */
|
||||
tcg_gen_not_tl(na, cpu_R[dc->ra]);
|
||||
|
||||
if (dc->rd) {
|
||||
TCGv ncf = tcg_temp_new();
|
||||
gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
|
||||
tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
|
||||
tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
|
||||
write_carry(dc, ncf);
|
||||
tcg_temp_free(ncf);
|
||||
} else {
|
||||
gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
|
||||
write_carry(dc, cf);
|
||||
}
|
||||
tcg_temp_free(cf);
|
||||
tcg_temp_free(na);
|
||||
}
|
||||
|
||||
static void dec_pattern(DisasContext *dc)
|
||||
|
Loading…
Reference in New Issue
Block a user