* [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements
@ 2012-10-05 23:54 Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 01/23] target-sparc: Tidy cpu_dump_state Richard Henderson
` (23 more replies)
0 siblings, 24 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Most of the patches are cleanup. Some of the middle patches that
make use of setcond and movcond where apropriate do improve code
generation. But more important that that, we no longer have tcg
temporaries that are live across basic blocks. Indeed, the only
remaining uses of brcond are in Tcc and the actual end-of-TB
branching code.
The final patch begins to make use of the infrastructure added
during the cleanups. Obviously there's more that can be done
here, handling addcc and logic ops, but I've run out of time for
today.
Tested on
linux-user-test-0.3 images
sparc32 works well
sparc64 no longer crashes, but does exit 1
the shipped openbios image
sparc32 works well
sparc64 works as well as head (stalls before prompt)
sparc-test-0.2
sparc32 boots to prompt
r~
Richard Henderson (23):
target-sparc: Tidy cpu_dump_state
target-sparc: Make CPU_LOG_INT useful by default
target-sparc: Tidy do_branch interfaces
target-sparc: Tidy flush_cond interface
target-sparc: Tidy gen_trap_ifnofpu interface
target-sparc: Tidy save_state interface
target-sparc: Tidy gen_mov_pc_npc interface
target-sparc: Tidy save_npc interface
target-sparc: Tidy gen_generic_branch interface
target-sparc: Introduce DisasCompare and functions to generate it
target-sparc: Use DisasCompare in Tcc
target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC
target-sparc: Use DisasCompare and movcond in MOVCC
target-sparc: Use DisasCompare and movcond in MOVR
target-sparc: Use movcond in gen_generic_branch
target-sparc: Move sdivx and udivx out of line
target-sparc: Tidy Tcc
target-sparc: Move taddcctv and tsubcctv out of line
target-sparc: Use movcond in mulscc
target-sparc: Use movcond for FMOV*R
target-sparc: Cleanup "global" temporary allocation
target-sparc: Fall through from not-taken trap
target-sparc: Optimize conditionals using SUBCC
target-sparc/cpu.c | 7 +-
target-sparc/cpu.h | 1 +
target-sparc/helper.c | 86 ++++
target-sparc/helper.h | 6 +
target-sparc/int32_helper.c | 7 +-
target-sparc/int64_helper.c | 8 +-
target-sparc/ldst_helper.c | 4 +-
target-sparc/translate.c | 1133 +++++++++++++++++++++----------------------
8 files changed, 653 insertions(+), 599 deletions(-)
--
1.7.11.4
^ permalink raw reply [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 01/23] target-sparc: Tidy cpu_dump_state
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 02/23] target-sparc: Make CPU_LOG_INT useful by default Richard Henderson
` (22 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
We don't really need to be told that %g are general register, etc.
Issue a trailing newline to separate blocks.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/cpu.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index f7c004c..71cc9e8 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -792,7 +792,6 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
env->npc);
- cpu_fprintf(f, "General Registers:\n");
for (i = 0; i < 8; i++) {
if (i % REGS_PER_LINE == 0) {
@@ -803,7 +802,6 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n");
}
}
- cpu_fprintf(f, "\nCurrent Register Window:\n");
for (x = 0; x < 3; x++) {
for (i = 0; i < 8; i++) {
if (i % REGS_PER_LINE == 0) {
@@ -817,10 +815,10 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
}
}
}
- cpu_fprintf(f, "\nFloating Point Registers:\n");
+
for (i = 0; i < TARGET_DPREGS; i++) {
if ((i & 3) == 0) {
- cpu_fprintf(f, "%%f%02d:", i * 2);
+ cpu_fprintf(f, "%%f%02d: ", i * 2);
}
cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
if ((i & 3) == 3) {
@@ -850,6 +848,7 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
env->fsr, env->y);
#endif
+ cpu_fprintf(f, "\n");
}
static void sparc_cpu_initfn(Object *obj)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 02/23] target-sparc: Make CPU_LOG_INT useful by default
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 01/23] target-sparc: Tidy cpu_dump_state Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 03/23] target-sparc: Tidy do_branch interfaces Richard Henderson
` (21 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
No need for ifdefs when the log mask does just as well.
No need to print pc/npc when we're dumping the whole cpu state.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/int32_helper.c | 7 ++-----
target-sparc/int64_helper.c | 8 ++------
2 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index 5e33d50..9ac5aac 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -21,7 +21,7 @@
#include "trace.h"
#include "sysemu.h"
-//#define DEBUG_PCALL
+#define DEBUG_PCALL
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
@@ -78,10 +78,7 @@ void do_interrupt(CPUSPARCState *env)
}
}
- qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
+ qemu_log("%6d: %s (v=%02x)\n", count, name, intno);
log_cpu_state(env, 0);
#if 0
{
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index 5e3eff7..5d0bc6c 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -21,7 +21,7 @@
#include "helper.h"
#include "trace.h"
-//#define DEBUG_PCALL
+#define DEBUG_PCALL
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
@@ -84,11 +84,7 @@ void do_interrupt(CPUSPARCState *env)
}
}
- qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
- " SP=%016" PRIx64 "\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
+ qemu_log("%6d: %s (v=%04x)\n", count, name, intno);
log_cpu_state(env, 0);
#if 0
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 03/23] target-sparc: Tidy do_branch interfaces
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 01/23] target-sparc: Tidy cpu_dump_state Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 02/23] target-sparc: Make CPU_LOG_INT useful by default Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 04/23] target-sparc: Tidy flush_cond interface Richard Henderson
` (20 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
We always pass cpu_cond to the r_cond parameter. Use that global
register directly instead of passing it down.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 38 ++++++++++++++++++--------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index e5ebedf..079a040 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1337,8 +1337,7 @@ static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
}
#endif
-static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
- TCGv r_cond)
+static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
{
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
target_ulong target = dc->pc + offset;
@@ -1368,10 +1367,10 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
tcg_gen_mov_tl(cpu_pc, cpu_npc);
}
} else {
- flush_cond(dc, r_cond);
- gen_cond(r_cond, cc, cond, dc);
+ flush_cond(dc, cpu_cond);
+ gen_cond(cpu_cond, cc, cond, dc);
if (a) {
- gen_branch_a(dc, target, dc->npc, r_cond);
+ gen_branch_a(dc, target, dc->npc, cpu_cond);
dc->is_br = 1;
} else {
dc->pc = dc->npc;
@@ -1387,8 +1386,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
}
}
-static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
- TCGv r_cond)
+static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
{
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
target_ulong target = dc->pc + offset;
@@ -1418,10 +1416,10 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
tcg_gen_mov_tl(cpu_pc, cpu_npc);
}
} else {
- flush_cond(dc, r_cond);
- gen_fcond(r_cond, cc, cond);
+ flush_cond(dc, cpu_cond);
+ gen_fcond(cpu_cond, cc, cond);
if (a) {
- gen_branch_a(dc, target, dc->npc, r_cond);
+ gen_branch_a(dc, target, dc->npc, cpu_cond);
dc->is_br = 1;
} else {
dc->pc = dc->npc;
@@ -1439,7 +1437,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
#ifdef TARGET_SPARC64
static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
- TCGv r_cond, TCGv r_reg)
+ TCGv r_reg)
{
unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
target_ulong target = dc->pc + offset;
@@ -1447,10 +1445,10 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
if (unlikely(AM_CHECK(dc))) {
target &= 0xffffffffULL;
}
- flush_cond(dc, r_cond);
- gen_cond_reg(r_cond, cond, r_reg);
+ flush_cond(dc, cpu_cond);
+ gen_cond_reg(cpu_cond, cond, r_reg);
if (a) {
- gen_branch_a(dc, target, dc->npc, r_cond);
+ gen_branch_a(dc, target, dc->npc, cpu_cond);
dc->is_br = 1;
} else {
dc->pc = dc->npc;
@@ -2421,9 +2419,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target <<= 2;
cc = GET_FIELD_SP(insn, 20, 21);
if (cc == 0)
- do_branch(dc, target, insn, 0, cpu_cond);
+ do_branch(dc, target, insn, 0);
else if (cc == 2)
- do_branch(dc, target, insn, 1, cpu_cond);
+ do_branch(dc, target, insn, 1);
else
goto illegal_insn;
goto jmp_insn;
@@ -2435,7 +2433,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target = sign_extend(target, 16);
target <<= 2;
cpu_src1 = get_src1(insn, cpu_src1);
- do_branch_reg(dc, target, insn, cpu_cond, cpu_src1);
+ do_branch_reg(dc, target, insn, cpu_src1);
goto jmp_insn;
}
case 0x5: /* V9 FBPcc */
@@ -2446,7 +2444,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target = GET_FIELD_SP(insn, 0, 18);
target = sign_extend(target, 19);
target <<= 2;
- do_fbranch(dc, target, insn, cc, cpu_cond);
+ do_fbranch(dc, target, insn, cc);
goto jmp_insn;
}
#else
@@ -2460,7 +2458,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target = GET_FIELD(insn, 10, 31);
target = sign_extend(target, 22);
target <<= 2;
- do_branch(dc, target, insn, 0, cpu_cond);
+ do_branch(dc, target, insn, 0);
goto jmp_insn;
}
case 0x6: /* FBN+x */
@@ -2470,7 +2468,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
target = GET_FIELD(insn, 10, 31);
target = sign_extend(target, 22);
target <<= 2;
- do_fbranch(dc, target, insn, 0, cpu_cond);
+ do_fbranch(dc, target, insn, 0);
goto jmp_insn;
}
case 0x4: /* SETHI */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 04/23] target-sparc: Tidy flush_cond interface
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (2 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 03/23] target-sparc: Tidy do_branch interfaces Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 05/23] target-sparc: Tidy gen_trap_ifnofpu interface Richard Henderson
` (19 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
We always pass cpu_cond to the cond parameter. Use that global
register directly instead of passing it down.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 079a040..5b2d5ea 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1118,10 +1118,10 @@ static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2,
/* call this function before using the condition register as it may
have been set for a jump */
-static inline void flush_cond(DisasContext *dc, TCGv cond)
+static inline void flush_cond(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
+ gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
dc->npc = DYNAMIC_PC;
}
}
@@ -1367,7 +1367,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
tcg_gen_mov_tl(cpu_pc, cpu_npc);
}
} else {
- flush_cond(dc, cpu_cond);
+ flush_cond(dc);
gen_cond(cpu_cond, cc, cond, dc);
if (a) {
gen_branch_a(dc, target, dc->npc, cpu_cond);
@@ -1416,7 +1416,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
tcg_gen_mov_tl(cpu_pc, cpu_npc);
}
} else {
- flush_cond(dc, cpu_cond);
+ flush_cond(dc);
gen_fcond(cpu_cond, cc, cond);
if (a) {
gen_branch_a(dc, target, dc->npc, cpu_cond);
@@ -1445,7 +1445,7 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
if (unlikely(AM_CHECK(dc))) {
target &= 0xffffffffULL;
}
- flush_cond(dc, cpu_cond);
+ flush_cond(dc);
gen_cond_reg(cpu_cond, cond, r_reg);
if (a) {
gen_branch_a(dc, target, dc->npc, cpu_cond);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 05/23] target-sparc: Tidy gen_trap_ifnofpu interface
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (3 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 04/23] target-sparc: Tidy flush_cond interface Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 06/23] target-sparc: Tidy save_state interface Richard Henderson
` (18 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
We always pass cpu_cond to the cond parameter. Use that global
register directly instead of passing it down.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 46 ++++++++++++++++++++++++++++------------------
1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 5b2d5ea..9787664 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1615,13 +1615,13 @@ static inline void gen_op_fpexception_im(int fsr_flags)
tcg_temp_free_i32(r_const);
}
-static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
+static int gen_trap_ifnofpu(DisasContext *dc)
{
#if !defined(CONFIG_USER_ONLY)
if (!dc->fpu_enabled) {
TCGv_i32 r_const;
- save_state(dc, r_cond);
+ save_state(dc, cpu_cond);
r_const = tcg_const_i32(TT_NFPU_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -2439,8 +2439,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x5: /* V9 FBPcc */
{
int cc = GET_FIELD_SP(insn, 20, 21);
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
target = GET_FIELD_SP(insn, 0, 18);
target = sign_extend(target, 19);
target <<= 2;
@@ -2463,8 +2464,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
case 0x6: /* FBN+x */
{
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
target = GET_FIELD(insn, 10, 31);
target = sign_extend(target, 22);
target <<= 2;
@@ -2643,8 +2645,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0xf: /* V9 membar */
break; /* no effect */
case 0x13: /* Graphics Status */
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
gen_movl_TN_reg(rd, cpu_gsr);
break;
case 0x16: /* Softint */
@@ -2861,8 +2864,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
#endif
} else if (xop == 0x34) { /* FPU Operations */
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
gen_op_clear_ieee_excp_and_FTT();
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
@@ -3035,8 +3039,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#ifdef TARGET_SPARC64
int cond;
#endif
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
gen_op_clear_ieee_excp_and_FTT();
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
@@ -3699,8 +3704,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#endif
break;
case 0x13: /* Graphics Status */
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
break;
case 0x14: /* Softint set */
@@ -4105,8 +4111,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
int opf = GET_FIELD_SP(insn, 5, 13);
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
switch (opf) {
case 0x000: /* VIS I edge8cc */
@@ -4873,7 +4880,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x2d: /* V9 prefetch, no effect */
goto skip_move;
case 0x30: /* V9 ldfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
save_state(dc, cpu_cond);
@@ -4881,7 +4888,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_update_fprs_dirty(rd);
goto skip_move;
case 0x33: /* V9 lddfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
save_state(dc, cpu_cond);
@@ -4892,7 +4899,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto skip_move;
case 0x32: /* V9 ldqfa */
CHECK_FPU_FEATURE(dc, FLOAT128);
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
save_state(dc, cpu_cond);
@@ -4908,8 +4915,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
skip_move: ;
#endif
} else if (xop >= 0x20 && xop < 0x24) {
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
save_state(dc, cpu_cond);
switch (xop) {
case 0x20: /* ldf, load fpreg */
@@ -5056,8 +5064,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto illegal_insn;
}
} else if (xop > 0x23 && xop < 0x28) {
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
save_state(dc, cpu_cond);
switch (xop) {
case 0x24: /* stf, store fpreg */
@@ -5100,8 +5109,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#else
if (!supervisor(dc))
goto priv_insn;
- if (gen_trap_ifnofpu(dc, cpu_cond))
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
+ }
goto nfq_insn;
#endif
#endif
@@ -5118,7 +5128,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
switch (xop) {
#ifdef TARGET_SPARC64
case 0x34: /* V9 stfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
gen_stf_asi(cpu_addr, insn, 4, rd);
@@ -5128,7 +5138,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv_i32 r_const;
CHECK_FPU_FEATURE(dc, FLOAT128);
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
r_const = tcg_const_i32(7);
@@ -5138,7 +5148,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
break;
case 0x37: /* V9 stdfa */
- if (gen_trap_ifnofpu(dc, cpu_cond)) {
+ if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 06/23] target-sparc: Tidy save_state interface
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (4 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 05/23] target-sparc: Tidy gen_trap_ifnofpu interface Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 07/23] target-sparc: Tidy gen_mov_pc_npc interface Richard Henderson
` (17 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Use the cpu_cond global register directly instead of passing it down.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 98 ++++++++++++++++++++++++------------------------
1 file changed, 49 insertions(+), 49 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9787664..eb95260 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1136,7 +1136,7 @@ static inline void save_npc(DisasContext *dc, TCGv cond)
}
}
-static inline void save_state(DisasContext *dc, TCGv cond)
+static inline void save_state(DisasContext *dc)
{
tcg_gen_movi_tl(cpu_pc, dc->pc);
/* flush pending conditional evaluations before exposing cpu state */
@@ -1144,7 +1144,7 @@ static inline void save_state(DisasContext *dc, TCGv cond)
dc->cc_op = CC_OP_FLAGS;
gen_helper_compute_psr(cpu_env);
}
- save_npc(dc, cond);
+ save_npc(dc, cpu_cond);
}
static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond)
@@ -1621,7 +1621,7 @@ static int gen_trap_ifnofpu(DisasContext *dc)
if (!dc->fpu_enabled) {
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_NFPU_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -2529,7 +2529,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
cond = GET_FIELD(insn, 3, 6);
if (cond == 0x8) { /* Trap Always */
- save_state(dc, cpu_cond);
+ save_state(dc);
if ((dc->def->features & CPU_FEATURE_HYPV) &&
supervisor(dc))
tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
@@ -2546,7 +2546,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
/* V9 icc/xcc */
int cc = GET_FIELD_SP(insn, 11, 12);
- save_state(dc, cpu_cond);
+ save_state(dc);
if (cc == 0)
gen_cond(r_cond, 0, cond, dc);
else if (cc == 2)
@@ -2554,7 +2554,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
else
goto illegal_insn;
#else
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_cond(r_cond, 0, cond, dc);
#endif
l1 = gen_new_label();
@@ -2854,7 +2854,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
} else if (xop == 0x2b) { /* rdtbr / V9 flushw */
#ifdef TARGET_SPARC64
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_flushw(cpu_env);
#else
if (!supervisor(dc))
@@ -2871,7 +2871,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26);
- save_state(dc, cpu_cond);
+ save_state(dc);
switch (xop) {
case 0x1: /* fmovs */
cpu_src1_32 = gen_load_fpr_F(dc, rs2);
@@ -3046,7 +3046,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26);
- save_state(dc, cpu_cond);
+ save_state(dc);
#ifdef TARGET_SPARC64
if ((xop & 0x11f) == 0x005) { // V9 fmovsr
int l1;
@@ -3607,14 +3607,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
dc->cc_op = CC_OP_TSUB;
break;
case 0x22: /* taddcctv */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV);
dc->cc_op = CC_OP_TADDTV;
break;
case 0x23: /* tsubcctv */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV);
@@ -3691,7 +3691,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x6: /* V9 wrfprs */
tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst);
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_next_insn();
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -3818,7 +3818,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_helper_wrpsr(cpu_env, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
dc->cc_op = CC_OP_FLAGS;
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_next_insn();
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -3898,7 +3898,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv r_tmp = tcg_temp_local_new();
tcg_gen_mov_tl(r_tmp, cpu_tmp0);
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_wrpstate(cpu_env, r_tmp);
tcg_temp_free(r_tmp);
dc->npc = DYNAMIC_PC;
@@ -3909,7 +3909,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv r_tmp = tcg_temp_local_new();
tcg_gen_mov_tl(r_tmp, cpu_tmp0);
- save_state(dc, cpu_cond);
+ save_state(dc);
tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp);
tcg_temp_free(r_tmp);
tcg_gen_st_i32(cpu_tmp32, cpu_env,
@@ -3991,7 +3991,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
switch (rd) {
case 0: // hpstate
// XXX gen_op_wrhpstate();
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_next_insn();
tcg_gen_exit_tb(0);
dc->is_br = 1;
@@ -4559,7 +4559,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
} else if (xop == 0x39) { /* V9 return */
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
cpu_src1 = get_src1(insn, cpu_src1);
if (IS_IMM) { /* immediate */
simm = GET_FIELDs(insn, 19, 31);
@@ -4635,12 +4635,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
/* nop */
break;
case 0x3c: /* save */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_save(cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x3d: /* restore */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_restore(cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
@@ -4723,7 +4723,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
else {
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(7);
/* XXX remove alignment check */
gen_helper_check_align(cpu_env, cpu_addr, r_const);
@@ -4774,7 +4774,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
break;
case 0x11: /* lduba, load unsigned byte alternate */
@@ -4784,7 +4784,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
break;
case 0x12: /* lduha, load unsigned halfword alternate */
@@ -4794,7 +4794,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
break;
case 0x13: /* ldda, load double word alternate */
@@ -4806,7 +4806,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#endif
if (rd & 1)
goto illegal_insn;
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
goto skip_move;
case 0x19: /* ldsba, load signed byte alternate */
@@ -4816,7 +4816,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
break;
case 0x1a: /* ldsha, load signed halfword alternate */
@@ -4826,7 +4826,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
break;
case 0x1d: /* ldstuba -- XXX: should be atomically */
@@ -4836,7 +4836,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldstub_asi(cpu_val, cpu_addr, insn);
break;
case 0x1f: /* swapa, swap reg with alt. memory. Also
@@ -4848,7 +4848,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_movl_reg_TN(rd, cpu_val);
gen_swap_asi(cpu_val, cpu_addr, insn);
break;
@@ -4870,11 +4870,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
break;
case 0x18: /* V9 ldswa */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
break;
case 0x1b: /* V9 ldxa */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
break;
case 0x2d: /* V9 prefetch, no effect */
@@ -4883,7 +4883,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldf_asi(cpu_addr, insn, 4, rd);
gen_update_fprs_dirty(rd);
goto skip_move;
@@ -4891,7 +4891,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
goto skip_move;
@@ -4902,7 +4902,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
goto skip_move;
@@ -4918,7 +4918,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
switch (xop) {
case 0x20: /* ldf, load fpreg */
gen_address_mask(dc, cpu_addr);
@@ -4989,7 +4989,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
else {
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_address_mask(dc, cpu_addr);
r_const = tcg_const_i32(7);
/* XXX remove alignment check */
@@ -5008,7 +5008,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 4);
dc->npc = DYNAMIC_PC;
break;
@@ -5019,7 +5019,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 1);
dc->npc = DYNAMIC_PC;
break;
@@ -5030,7 +5030,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
#endif
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 2);
dc->npc = DYNAMIC_PC;
break;
@@ -5044,7 +5044,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (rd & 1)
goto illegal_insn;
else {
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_stda_asi(cpu_val, cpu_addr, insn, rd);
}
break;
@@ -5055,7 +5055,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
break;
case 0x1e: /* V9 stxa */
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_st_asi(cpu_val, cpu_addr, insn, 8);
dc->npc = DYNAMIC_PC;
break;
@@ -5067,7 +5067,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
- save_state(dc, cpu_cond);
+ save_state(dc);
switch (xop) {
case 0x24: /* stf, store fpreg */
gen_address_mask(dc, cpu_addr);
@@ -5124,7 +5124,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto illegal_insn;
}
} else if (xop > 0x33 && xop < 0x3f) {
- save_state(dc, cpu_cond);
+ save_state(dc);
switch (xop) {
#ifdef TARGET_SPARC64
case 0x34: /* V9 stfa */
@@ -5194,7 +5194,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_ILL_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -5205,7 +5205,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_UNIMP_FLUSH);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -5217,7 +5217,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv_i32 r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_PRIV_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
@@ -5226,13 +5226,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto egress;
#endif
nfpu_insn:
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
dc->is_br = 1;
goto egress;
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
nfq_insn:
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
dc->is_br = 1;
goto egress;
@@ -5242,7 +5242,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
TCGv r_const;
- save_state(dc, cpu_cond);
+ save_state(dc);
r_const = tcg_const_i32(TT_NCP_INSN);
gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free(r_const);
@@ -5308,7 +5308,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
if (dc->pc != pc_start)
- save_state(dc, cpu_cond);
+ save_state(dc);
gen_helper_debug(cpu_env);
tcg_gen_exit_tb(0);
dc->is_br = 1;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 07/23] target-sparc: Tidy gen_mov_pc_npc interface
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (5 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 06/23] target-sparc: Tidy save_state interface Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 08/23] target-sparc: Tidy save_npc interface Richard Henderson
` (16 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Use the cpu_cond global register directly instead of passing it down.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index eb95260..d9e1b01 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1147,10 +1147,10 @@ static inline void save_state(DisasContext *dc)
save_npc(dc, cpu_cond);
}
-static inline void gen_mov_pc_npc(DisasContext *dc, TCGv cond)
+static inline void gen_mov_pc_npc(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
+ gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
tcg_gen_mov_tl(cpu_pc, cpu_npc);
dc->pc = DYNAMIC_PC;
} else if (dc->npc == DYNAMIC_PC) {
@@ -2499,7 +2499,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_movl_TN_reg(15, r_const);
tcg_temp_free(r_const);
target += dc->pc;
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
#ifdef TARGET_SPARC64
if (unlikely(AM_CHECK(dc))) {
target &= 0xffffffffULL;
@@ -4573,7 +4573,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_mov_tl(cpu_dst, cpu_src1);
}
gen_helper_restore(cpu_env);
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
r_const = tcg_const_i32(3);
gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
@@ -4603,7 +4603,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_pc = tcg_const_tl(dc->pc);
gen_movl_TN_reg(rd, r_pc);
tcg_temp_free(r_pc);
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
r_const = tcg_const_i32(3);
gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
@@ -4619,7 +4619,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (!supervisor(dc))
goto priv_insn;
- gen_mov_pc_npc(dc, cpu_cond);
+ gen_mov_pc_npc(dc);
r_const = tcg_const_i32(3);
gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 08/23] target-sparc: Tidy save_npc interface
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (6 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 07/23] target-sparc: Tidy gen_mov_pc_npc interface Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 09/23] target-sparc: Tidy gen_generic_branch interface Richard Henderson
` (15 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Use the cpu_cond global register directly instead of passing it down.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d9e1b01..4cc7887 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1126,10 +1126,10 @@ static inline void flush_cond(DisasContext *dc)
}
}
-static inline void save_npc(DisasContext *dc, TCGv cond)
+static inline void save_npc(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cond);
+ gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
dc->npc = DYNAMIC_PC;
} else if (dc->npc != DYNAMIC_PC) {
tcg_gen_movi_tl(cpu_npc, dc->npc);
@@ -1144,7 +1144,7 @@ static inline void save_state(DisasContext *dc)
dc->cc_op = CC_OP_FLAGS;
gen_helper_compute_psr(cpu_env);
}
- save_npc(dc, cpu_cond);
+ save_npc(dc);
}
static inline void gen_mov_pc_npc(DisasContext *dc)
@@ -5372,7 +5372,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
} else {
if (dc->pc != DYNAMIC_PC)
tcg_gen_movi_tl(cpu_pc, dc->pc);
- save_npc(dc, cpu_cond);
+ save_npc(dc);
tcg_gen_exit_tb(0);
}
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 09/23] target-sparc: Tidy gen_generic_branch interface
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (7 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 08/23] target-sparc: Tidy save_npc interface Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 10/23] target-sparc: Introduce DisasCompare and functions to generate it Richard Henderson
` (14 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
The arguments passed are always the same.
Pass down just DisasContext instead.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 4cc7887..d759da2 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1098,21 +1098,20 @@ static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
}
-static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2,
- TCGv r_cond)
+static inline void gen_generic_branch(DisasContext *dc)
{
int l1, l2;
l1 = gen_new_label();
l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1);
- tcg_gen_movi_tl(cpu_npc, npc1);
+ tcg_gen_movi_tl(cpu_npc, dc->jump_pc[0]);
tcg_gen_br(l2);
gen_set_label(l1);
- tcg_gen_movi_tl(cpu_npc, npc2);
+ tcg_gen_movi_tl(cpu_npc, dc->jump_pc[1]);
gen_set_label(l2);
}
@@ -1121,7 +1120,7 @@ static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2,
static inline void flush_cond(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
+ gen_generic_branch(dc);
dc->npc = DYNAMIC_PC;
}
}
@@ -1129,7 +1128,7 @@ static inline void flush_cond(DisasContext *dc)
static inline void save_npc(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
+ gen_generic_branch(dc);
dc->npc = DYNAMIC_PC;
} else if (dc->npc != DYNAMIC_PC) {
tcg_gen_movi_tl(cpu_npc, dc->npc);
@@ -1150,7 +1149,7 @@ static inline void save_state(DisasContext *dc)
static inline void gen_mov_pc_npc(DisasContext *dc)
{
if (dc->npc == JUMP_PC) {
- gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
+ gen_generic_branch(dc);
tcg_gen_mov_tl(cpu_pc, cpu_npc);
dc->pc = DYNAMIC_PC;
} else if (dc->npc == DYNAMIC_PC) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 10/23] target-sparc: Introduce DisasCompare and functions to generate it
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (8 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 09/23] target-sparc: Tidy gen_generic_branch interface Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 11/23] target-sparc: Use DisasCompare in Tcc Richard Henderson
` (13 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
For the moment gen_cond et al retain their existing interface,
using setcond to turn a (potential) comparison back into a boolean.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 92 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 83 insertions(+), 9 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d759da2..d61a9a0 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -86,6 +86,13 @@ typedef struct DisasContext {
int n_t32;
} DisasContext;
+typedef struct {
+ TCGCond cond;
+ bool is_bool;
+ bool g1, g2;
+ TCGv c1, c2;
+} DisasCompare;
+
// This function uses non-native bit order
#define GET_FIELD(X, FROM, TO) \
((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
@@ -1166,10 +1173,28 @@ static inline void gen_op_next_insn(void)
tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
}
-static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
- DisasContext *dc)
+static void free_compare(DisasCompare *cmp)
+{
+ if (!cmp->g1) {
+ tcg_temp_free(cmp->c1);
+ }
+ if (!cmp->g2) {
+ tcg_temp_free(cmp->c2);
+ }
+}
+
+static void gen_compare(DisasCompare *cmp, unsigned int cc, unsigned int cond,
+ DisasContext *dc)
{
TCGv_i32 r_src;
+ TCGv r_dst;
+
+ /* For now we still generate a straight boolean result. */
+ cmp->cond = TCG_COND_NE;
+ cmp->is_bool = true;
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = r_dst = tcg_temp_new();
+ cmp->c2 = tcg_const_tl(0);
#ifdef TARGET_SPARC64
if (cc)
@@ -1239,9 +1264,17 @@ static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
}
}
-static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
+static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
{
unsigned int offset;
+ TCGv r_dst;
+
+ /* For now we still generate a straight boolean result. */
+ cmp->cond = TCG_COND_NE;
+ cmp->is_bool = true;
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = r_dst = tcg_temp_new();
+ cmp->c2 = tcg_const_tl(0);
switch (cc) {
default:
@@ -1311,6 +1344,37 @@ static inline void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
}
}
+static void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
+ DisasContext *dc)
+{
+ DisasCompare cmp;
+ gen_compare(&cmp, cc, cond, dc);
+
+ /* The interface is to return a boolean in r_dst. */
+ if (cmp.is_bool) {
+ tcg_gen_mov_tl(r_dst, cmp.c1);
+ } else {
+ tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
+ }
+
+ free_compare(&cmp);
+}
+
+static void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
+{
+ DisasCompare cmp;
+ gen_fcompare(&cmp, cc, cond);
+
+ /* The interface is to return a boolean in r_dst. */
+ if (cmp.is_bool) {
+ tcg_gen_mov_tl(r_dst, cmp.c1);
+ } else {
+ tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
+ }
+
+ free_compare(&cmp);
+}
+
#ifdef TARGET_SPARC64
// Inverted logic
static const int gen_tcg_cond_reg[8] = {
@@ -1324,15 +1388,25 @@ static const int gen_tcg_cond_reg[8] = {
TCG_COND_LT,
};
+static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
+{
+ cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]);
+ cmp->is_bool = false;
+ cmp->g1 = true;
+ cmp->g2 = false;
+ cmp->c1 = r_src;
+ cmp->c2 = tcg_const_tl(0);
+}
+
static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
{
- int l1;
+ DisasCompare cmp;
+ gen_compare_reg(&cmp, cond, r_src);
- l1 = gen_new_label();
- tcg_gen_movi_tl(r_dst, 0);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], r_src, 0, l1);
- tcg_gen_movi_tl(r_dst, 1);
- gen_set_label(l1);
+ /* The interface is to return a boolean in r_dst. */
+ tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
+
+ free_compare(&cmp);
}
#endif
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 11/23] target-sparc: Use DisasCompare in Tcc
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (9 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 10/23] target-sparc: Introduce DisasCompare and functions to generate it Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 12/23] target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC Richard Henderson
` (12 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d61a9a0..fa9a057 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2613,25 +2613,28 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_helper_raise_exception(cpu_env, cpu_tmp32);
} else if (cond != 0) {
- TCGv r_cond = tcg_temp_new();
+ DisasCompare cmp;
int l1;
#ifdef TARGET_SPARC64
/* V9 icc/xcc */
int cc = GET_FIELD_SP(insn, 11, 12);
save_state(dc);
- if (cc == 0)
- gen_cond(r_cond, 0, cond, dc);
- else if (cc == 2)
- gen_cond(r_cond, 1, cond, dc);
- else
+ if (cc == 0) {
+ gen_compare(&cmp, 0, cond, dc);
+ } else if (cc == 2) {
+ gen_compare(&cmp, 1, cond, dc);
+ } else {
goto illegal_insn;
+ }
#else
save_state(dc);
- gen_cond(r_cond, 0, cond, dc);
+ gen_compare(&cmp, 0, cond, dc);
#endif
l1 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
+ tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
+ cmp.c1, cmp.c2, l1);
+ free_compare(&cmp);
if ((dc->def->features & CPU_FEATURE_HYPV) &&
supervisor(dc))
@@ -2643,7 +2646,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_helper_raise_exception(cpu_env, cpu_tmp32);
gen_set_label(l1);
- tcg_temp_free(r_cond);
}
gen_op_next_insn();
tcg_gen_exit_tb(0);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 12/23] target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (10 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 11/23] target-sparc: Use DisasCompare in Tcc Richard Henderson
@ 2012-10-05 23:54 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 13/23] target-sparc: Use DisasCompare and movcond in MOVCC Richard Henderson
` (11 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 203 ++++++++++++++++++++---------------------------
1 file changed, 86 insertions(+), 117 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index fa9a057..a7cd677 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2281,6 +2281,57 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
}
#ifdef TARGET_SPARC64
+static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
+{
+ TCGv_i32 c32, zero, dst, s1, s2;
+
+ /* We have two choices here: extend the 32 bit data and use movcond_i64,
+ or fold the comparison down to 32 bits and use movcond_i32. Choose
+ the later. */
+ c32 = tcg_temp_new_i32();
+ if (cmp->is_bool) {
+ tcg_gen_trunc_i64_i32(c32, cmp->c1);
+ } else {
+ TCGv_i64 c64 = tcg_temp_new_i64();
+ tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
+ tcg_gen_trunc_i64_i32(c32, c64);
+ tcg_temp_free_i64(c64);
+ }
+
+ s1 = gen_load_fpr_F(dc, rs);
+ s2 = gen_load_fpr_F(dc, rd);
+ dst = gen_dest_fpr_F();
+ zero = tcg_const_i32(0);
+
+ tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
+
+ tcg_temp_free_i32(c32);
+ tcg_temp_free_i32(zero);
+ gen_store_fpr_F(dc, rd, dst);
+}
+
+static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
+{
+ TCGv_i64 dst = gen_dest_fpr_D();
+ tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
+ gen_load_fpr_D(dc, rs),
+ gen_load_fpr_D(dc, rd));
+ gen_store_fpr_D(dc, rd, dst);
+}
+
+static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
+{
+ int qd = QFPREG(rd);
+ int qs = QFPREG(rs);
+
+ tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
+ cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
+ tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
+ cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
+
+ gen_update_fprs_dirty(qd);
+}
+
static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
{
TCGv_i32 r_tl = tcg_temp_new_i32();
@@ -3163,168 +3214,86 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
#endif
switch (xop) {
#ifdef TARGET_SPARC64
-#define FMOVSCC(fcc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_fcond(r_cond, fcc, cond); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
- gen_store_fpr_F(dc, rd, cpu_src1_32); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVDCC(fcc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_fcond(r_cond, fcc, cond); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
- gen_store_fpr_D(dc, rd, cpu_src1_64); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVQCC(fcc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
+#define FMOVCC(fcc, sz) \
+ do { \
+ DisasCompare cmp; \
cond = GET_FIELD_SP(insn, 14, 17); \
- gen_fcond(r_cond, fcc, cond); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- gen_move_Q(rd, rs2); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
+ gen_fcompare(&cmp, fcc, cond); \
+ gen_fmov##sz(dc, &cmp, rd, rs2); \
+ free_compare(&cmp); \
+ } while (0)
+
case 0x001: /* V9 fmovscc %fcc0 */
- FMOVSCC(0);
+ FMOVCC(0, s);
break;
case 0x002: /* V9 fmovdcc %fcc0 */
- FMOVDCC(0);
+ FMOVCC(0, d);
break;
case 0x003: /* V9 fmovqcc %fcc0 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(0);
+ FMOVCC(0, q);
break;
case 0x041: /* V9 fmovscc %fcc1 */
- FMOVSCC(1);
+ FMOVCC(1, s);
break;
case 0x042: /* V9 fmovdcc %fcc1 */
- FMOVDCC(1);
+ FMOVCC(1, d);
break;
case 0x043: /* V9 fmovqcc %fcc1 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(1);
+ FMOVCC(1, q);
break;
case 0x081: /* V9 fmovscc %fcc2 */
- FMOVSCC(2);
+ FMOVCC(2, s);
break;
case 0x082: /* V9 fmovdcc %fcc2 */
- FMOVDCC(2);
+ FMOVCC(2, d);
break;
case 0x083: /* V9 fmovqcc %fcc2 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(2);
+ FMOVCC(2, q);
break;
case 0x0c1: /* V9 fmovscc %fcc3 */
- FMOVSCC(3);
+ FMOVCC(3, s);
break;
case 0x0c2: /* V9 fmovdcc %fcc3 */
- FMOVDCC(3);
+ FMOVCC(3, d);
break;
case 0x0c3: /* V9 fmovqcc %fcc3 */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(3);
+ FMOVCC(3, q);
break;
-#undef FMOVSCC
-#undef FMOVDCC
-#undef FMOVQCC
-#define FMOVSCC(icc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_cond(r_cond, icc, cond, dc); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
- gen_store_fpr_F(dc, rd, cpu_src1_32); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVDCC(icc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
+#undef FMOVCC
+#define FMOVCC(xcc, sz) \
+ do { \
+ DisasCompare cmp; \
cond = GET_FIELD_SP(insn, 14, 17); \
- gen_cond(r_cond, icc, cond, dc); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
- gen_store_fpr_D(dc, rd, cpu_src1_64); \
- gen_update_fprs_dirty(DFPREG(rd)); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
-#define FMOVQCC(icc) \
- { \
- TCGv r_cond; \
- int l1; \
- \
- l1 = gen_new_label(); \
- r_cond = tcg_temp_new(); \
- cond = GET_FIELD_SP(insn, 14, 17); \
- gen_cond(r_cond, icc, cond, dc); \
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
- 0, l1); \
- gen_move_Q(rd, rs2); \
- gen_set_label(l1); \
- tcg_temp_free(r_cond); \
- }
+ gen_compare(&cmp, xcc, cond, dc); \
+ gen_fmov##sz(dc, &cmp, rd, rs2); \
+ free_compare(&cmp); \
+ } while (0)
case 0x101: /* V9 fmovscc %icc */
- FMOVSCC(0);
+ FMOVCC(0, s);
break;
case 0x102: /* V9 fmovdcc %icc */
- FMOVDCC(0);
+ FMOVCC(0, d);
break;
case 0x103: /* V9 fmovqcc %icc */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(0);
+ FMOVCC(0, q);
break;
case 0x181: /* V9 fmovscc %xcc */
- FMOVSCC(1);
+ FMOVCC(1, s);
break;
case 0x182: /* V9 fmovdcc %xcc */
- FMOVDCC(1);
+ FMOVCC(1, d);
break;
case 0x183: /* V9 fmovqcc %xcc */
CHECK_FPU_FEATURE(dc, FLOAT128);
- FMOVQCC(1);
+ FMOVCC(1, q);
break;
-#undef FMOVSCC
-#undef FMOVDCC
-#undef FMOVQCC
+#undef FMOVCC
#endif
case 0x51: /* fcmps, V9 %fcc */
cpu_src1_32 = gen_load_fpr_F(dc, rs1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 13/23] target-sparc: Use DisasCompare and movcond in MOVCC
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (11 preceding siblings ...)
2012-10-05 23:54 ` [Qemu-devel] [PATCH 12/23] target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 14/23] target-sparc: Use DisasCompare and movcond in MOVR Richard Henderson
` (10 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 44 ++++++++++++++++++++------------------------
1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index a7cd677..6c9be29 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4075,38 +4075,34 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
int cc = GET_FIELD_SP(insn, 11, 12);
int cond = GET_FIELD_SP(insn, 14, 17);
- TCGv r_cond;
- int l1;
+ DisasCompare cmp;
- r_cond = tcg_temp_new();
if (insn & (1 << 18)) {
- if (cc == 0)
- gen_cond(r_cond, 0, cond, dc);
- else if (cc == 2)
- gen_cond(r_cond, 1, cond, dc);
- else
+ if (cc == 0) {
+ gen_compare(&cmp, 0, cond, dc);
+ } else if (cc == 2) {
+ gen_compare(&cmp, 1, cond, dc);
+ } else {
goto illegal_insn;
+ }
} else {
- gen_fcond(r_cond, cc, cond);
+ gen_fcompare(&cmp, cc, cond);
}
- l1 = gen_new_label();
-
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
- if (IS_IMM) { /* immediate */
- TCGv r_const;
-
+ /* The get_src2 above loaded the normal 13-bit
+ immediate field, not the 11-bit field we have
+ in movcc. But it did handle the reg case. */
+ if (IS_IMM) {
simm = GET_FIELD_SPs(insn, 0, 10);
- r_const = tcg_const_tl(simm);
- gen_movl_TN_reg(rd, r_const);
- tcg_temp_free(r_const);
- } else {
- rs2 = GET_FIELD_SP(insn, 0, 4);
- gen_movl_reg_TN(rs2, cpu_tmp0);
- gen_movl_TN_reg(rd, cpu_tmp0);
+ tcg_gen_movi_tl(cpu_src2, simm);
}
- gen_set_label(l1);
- tcg_temp_free(r_cond);
+
+ gen_movl_reg_TN(rd, cpu_dst);
+ tcg_gen_movcond_tl(cmp.cond, cpu_dst,
+ cmp.c1, cmp.c2,
+ cpu_src2, cpu_dst);
+ free_compare(&cmp);
+ gen_movl_TN_reg(rd, cpu_dst);
break;
}
case 0x2d: /* V9 sdivx */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 14/23] target-sparc: Use DisasCompare and movcond in MOVR
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (12 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 13/23] target-sparc: Use DisasCompare and movcond in MOVCC Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 15/23] target-sparc: Use movcond in gen_generic_branch Richard Henderson
` (9 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 6c9be29..9aef8e5 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4118,27 +4118,24 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x2f: /* V9 movr */
{
int cond = GET_FIELD_SP(insn, 10, 12);
- int l1;
-
- cpu_src1 = get_src1(insn, cpu_src1);
-
- l1 = gen_new_label();
+ DisasCompare cmp;
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond],
- cpu_src1, 0, l1);
- if (IS_IMM) { /* immediate */
- TCGv r_const;
+ gen_compare_reg(&cmp, cond, cpu_src1);
+ /* The get_src2 above loaded the normal 13-bit
+ immediate field, not the 10-bit field we have
+ in movr. But it did handle the reg case. */
+ if (IS_IMM) {
simm = GET_FIELD_SPs(insn, 0, 9);
- r_const = tcg_const_tl(simm);
- gen_movl_TN_reg(rd, r_const);
- tcg_temp_free(r_const);
- } else {
- rs2 = GET_FIELD_SP(insn, 0, 4);
- gen_movl_reg_TN(rs2, cpu_tmp0);
- gen_movl_TN_reg(rd, cpu_tmp0);
+ tcg_gen_movi_tl(cpu_src2, simm);
}
- gen_set_label(l1);
+
+ gen_movl_reg_TN(rd, cpu_dst);
+ tcg_gen_movcond_tl(cmp.cond, cpu_dst,
+ cmp.c1, cmp.c2,
+ cpu_src2, cpu_dst);
+ free_compare(&cmp);
+ gen_movl_TN_reg(rd, cpu_dst);
break;
}
#endif
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 15/23] target-sparc: Use movcond in gen_generic_branch
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (13 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 14/23] target-sparc: Use DisasCompare and movcond in MOVR Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 16/23] target-sparc: Move sdivx and udivx out of line Richard Henderson
` (8 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9aef8e5..c1a1dc4 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1107,19 +1107,15 @@ static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
static inline void gen_generic_branch(DisasContext *dc)
{
- int l1, l2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
+ TCGv npc0 = tcg_const_tl(dc->jump_pc[0]);
+ TCGv npc1 = tcg_const_tl(dc->jump_pc[1]);
+ TCGv zero = tcg_const_tl(0);
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1);
+ tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1);
- tcg_gen_movi_tl(cpu_npc, dc->jump_pc[0]);
- tcg_gen_br(l2);
-
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_npc, dc->jump_pc[1]);
- gen_set_label(l2);
+ tcg_temp_free(npc0);
+ tcg_temp_free(npc1);
+ tcg_temp_free(zero);
}
/* call this function before using the condition register as it may
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 16/23] target-sparc: Move sdivx and udivx out of line
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (14 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 15/23] target-sparc: Use movcond in gen_generic_branch Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 17/23] target-sparc: Tidy Tcc Richard Henderson
` (7 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
The branches around the exception are maintaining an otherwise
unnecessary use of local temps for the cpu destination.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/cpu.h | 1 +
target-sparc/helper.c | 28 +++++++++++++++++++++++++
target-sparc/helper.h | 4 ++++
target-sparc/ldst_helper.c | 4 ++--
target-sparc/translate.c | 52 ++--------------------------------------------
5 files changed, 37 insertions(+), 52 deletions(-)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index e16b7b3..214d01d 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -714,6 +714,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
int is_write, int is_user,
uintptr_t retaddr);
+void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr);
#define TB_FLAG_FPU_ENABLED (1 << 4)
#define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 65e1740..4555d2b 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -75,6 +75,7 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);
if (x1 == 0) {
+ cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
@@ -113,6 +114,7 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);
if (x1 == 0) {
+ cpu_restore_state2(env, GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
@@ -139,3 +141,29 @@ target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
{
return helper_sdiv_common(env, a, b, 1);
}
+
+#ifdef TARGET_SPARC64
+int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b)
+{
+ if (b == 0) {
+ /* Raise divide by zero trap. */
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_DIV_ZERO);
+ } else if (b == -1) {
+ /* Avoid overflow trap with i386 divide insn. */
+ return -a;
+ } else {
+ return a / b;
+ }
+}
+
+uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
+{
+ if (b == 0) {
+ /* Raise divide by zero trap. */
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_DIV_ZERO);
+ }
+ return a / b;
+}
+#endif
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index e3c7fdd..827df67 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -38,6 +38,10 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
+#ifdef TARGET_SPARC64
+DEF_HELPER_3(sdivx, s64, env, s64, s64)
+DEF_HELPER_3(udivx, i64, env, i64, i64)
+#endif
DEF_HELPER_3(ldqf, void, env, tl, int)
DEF_HELPER_3(stqf, void, env, tl, int)
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 9bec7a9..2ca9a5c 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2390,9 +2390,8 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
#endif
#endif
-#if !defined(CONFIG_USER_ONLY)
/* XXX: make it generic ? */
-static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
+void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
{
TranslationBlock *tb;
@@ -2407,6 +2406,7 @@ static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
}
}
+#if !defined(CONFIG_USER_ONLY)
void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
int is_user, uintptr_t retaddr)
{
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index c1a1dc4..1628cf3 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -768,44 +768,6 @@ static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
gen_op_multiply(dst, src1, src2, 1);
}
-#ifdef TARGET_SPARC64
-static inline void gen_trap_ifdivzero_tl(TCGv divisor)
-{
- TCGv_i32 r_const;
- int l1;
-
- l1 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
- r_const = tcg_const_i32(TT_DIV_ZERO);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
-}
-
-static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
-{
- int l1, l2;
- TCGv r_temp1, r_temp2;
-
- l1 = gen_new_label();
- l2 = gen_new_label();
- r_temp1 = tcg_temp_local_new();
- r_temp2 = tcg_temp_local_new();
- tcg_gen_mov_tl(r_temp1, src1);
- tcg_gen_mov_tl(r_temp2, src2);
- gen_trap_ifdivzero_tl(r_temp2);
- tcg_gen_brcondi_tl(TCG_COND_NE, r_temp1, INT64_MIN, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, r_temp2, -1, l1);
- tcg_gen_movi_i64(dst, INT64_MIN);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_div_i64(dst, r_temp1, r_temp2);
- gen_set_label(l2);
- tcg_temp_free(r_temp1);
- tcg_temp_free(r_temp2);
-}
-#endif
-
// 1
static inline void gen_op_eval_ba(TCGv dst)
{
@@ -3591,17 +3553,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
#ifdef TARGET_SPARC64
case 0xd: /* V9 udivx */
- {
- TCGv r_temp1, r_temp2;
- r_temp1 = tcg_temp_local_new();
- r_temp2 = tcg_temp_local_new();
- tcg_gen_mov_tl(r_temp1, cpu_src1);
- tcg_gen_mov_tl(r_temp2, cpu_src2);
- gen_trap_ifdivzero_tl(r_temp2);
- tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2);
- tcg_temp_free(r_temp1);
- tcg_temp_free(r_temp2);
- }
+ gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
break;
#endif
case 0xe: /* udiv */
@@ -4102,7 +4054,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
}
case 0x2d: /* V9 sdivx */
- gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x2e: /* V9 popc */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 17/23] target-sparc: Tidy Tcc
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (15 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 16/23] target-sparc: Move sdivx and udivx out of line Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 18/23] target-sparc: Move taddcctv and tsubcctv out of line Richard Henderson
` (6 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Share more code between unconditional and conditional paths.
Move the computation of the trap number into the conditional BB;
avoid using temporaries that have gone out of scope (cpu_tmp32)
or rely on local temps (cpu_dst).
Fully fold the exception number when the trap number is %g0+imm.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 91 ++++++++++++++++++++++++++++--------------------
1 file changed, 53 insertions(+), 38 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 1628cf3..111c025 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2594,41 +2594,23 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
unsigned int xop = GET_FIELD(insn, 7, 12);
if (xop == 0x3a) { /* generate trap */
- int cond;
+ int cond = GET_FIELD(insn, 3, 6);
+ TCGv_i32 trap;
+ int l1 = -1, mask;
- cpu_src1 = get_src1(insn, cpu_src1);
- if (IS_IMM) {
- rs2 = GET_FIELD(insn, 25, 31);
- tcg_gen_addi_tl(cpu_dst, cpu_src1, rs2);
- } else {
- rs2 = GET_FIELD(insn, 27, 31);
- if (rs2 != 0) {
- gen_movl_reg_TN(rs2, cpu_src2);
- tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
- } else
- tcg_gen_mov_tl(cpu_dst, cpu_src1);
+ if (cond == 0) {
+ /* Trap never. */
+ break;
}
- cond = GET_FIELD(insn, 3, 6);
- if (cond == 0x8) { /* Trap Always */
- save_state(dc);
- if ((dc->def->features & CPU_FEATURE_HYPV) &&
- supervisor(dc))
- tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
- else
- tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
- tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
- tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
- gen_helper_raise_exception(cpu_env, cpu_tmp32);
+ save_state(dc);
- } else if (cond != 0) {
+ if (cond != 8) {
+ /* Conditional trap. */
DisasCompare cmp;
- int l1;
#ifdef TARGET_SPARC64
/* V9 icc/xcc */
int cc = GET_FIELD_SP(insn, 11, 12);
-
- save_state(dc);
if (cc == 0) {
gen_compare(&cmp, 0, cond, dc);
} else if (cc == 2) {
@@ -2637,27 +2619,60 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto illegal_insn;
}
#else
- save_state(dc);
gen_compare(&cmp, 0, cond, dc);
#endif
l1 = gen_new_label();
tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
cmp.c1, cmp.c2, l1);
free_compare(&cmp);
+ }
- if ((dc->def->features & CPU_FEATURE_HYPV) &&
- supervisor(dc))
- tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
- else
- tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
- tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
- tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
- gen_helper_raise_exception(cpu_env, cpu_tmp32);
+ mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
+ ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
+
+ /* Don't use the normal temporaries, as they may well have
+ gone out of scope with the branch above. While we're
+ doing that we might as well pre-truncate to 32-bit. */
+ trap = tcg_temp_new_i32();
+
+ rs1 = GET_FIELD_SP(insn, 14, 18);
+ if (IS_IMM) {
+ rs2 = GET_FIELD_SP(insn, 0, 6);
+ if (rs1 == 0) {
+ tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP);
+ /* Signal that the trap value is fully constant. */
+ mask = 0;
+ } else {
+ TCGv t1 = tcg_temp_new();
+ gen_movl_reg_TN(rs1, t1);
+ tcg_gen_trunc_tl_i32(trap, t1);
+ tcg_temp_free(t1);
+ tcg_gen_addi_i32(trap, trap, rs2);
+ }
+ } else {
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+ rs2 = GET_FIELD_SP(insn, 0, 4);
+ gen_movl_reg_TN(rs1, t1);
+ gen_movl_reg_TN(rs2, t2);
+ tcg_gen_add_tl(t1, t1, t2);
+ tcg_gen_trunc_tl_i32(trap, t1);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+ }
+ if (mask != 0) {
+ tcg_gen_andi_i32(trap, trap, mask);
+ tcg_gen_addi_i32(trap, trap, TT_TRAP);
+ }
+
+ gen_helper_raise_exception(cpu_env, trap);
+ tcg_temp_free_i32(trap);
+ if (cond != 8) {
gen_set_label(l1);
+ gen_op_next_insn();
+ tcg_gen_exit_tb(0);
}
- gen_op_next_insn();
- tcg_gen_exit_tb(0);
dc->is_br = 1;
goto jmp_insn;
} else if (xop == 0x28) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 18/23] target-sparc: Move taddcctv and tsubcctv out of line
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (16 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 17/23] target-sparc: Tidy Tcc Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 19/23] target-sparc: Use movcond in mulscc Richard Henderson
` (5 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
The branches around the exception are maintaining an otherwise
unnecessary use of local temps for the cpu destination.
Note that gen_op_t{add,sub}_cc were identical to gen_op_{add,sub}_cc.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/helper.c | 58 +++++++++++++++++++++++++
target-sparc/helper.h | 2 +
target-sparc/translate.c | 108 +++--------------------------------------------
3 files changed, 66 insertions(+), 102 deletions(-)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 4555d2b..556ac28 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -167,3 +167,61 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
return a / b;
}
#endif
+
+target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
+ target_ulong src2)
+{
+ target_ulong dst;
+
+ /* Tag overflow occurs if either input has bits 0 or 1 set. */
+ if ((src1 | src2) & 3) {
+ goto tag_overflow;
+ }
+
+ dst = src1 + src2;
+
+ /* Tag overflow occurs if the addition overflows. */
+ if (~(src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
+ goto tag_overflow;
+ }
+
+ /* Only modify the CC after any exceptions have been generated. */
+ env->cc_op = CC_OP_TADDTV;
+ env->cc_src = src1;
+ env->cc_src2 = src2;
+ env->cc_dst = dst;
+ return dst;
+
+ tag_overflow:
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_TOVF);
+}
+
+target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
+ target_ulong src2)
+{
+ target_ulong dst;
+
+ /* Tag overflow occurs if either input has bits 0 or 1 set. */
+ if ((src1 | src2) & 3) {
+ goto tag_overflow;
+ }
+
+ dst = src1 - src2;
+
+ /* Tag overflow occurs if the subtraction overflows. */
+ if ((src1 ^ src2) & (src1 ^ dst) & (1u << 31)) {
+ goto tag_overflow;
+ }
+
+ /* Only modify the CC after any exceptions have been generated. */
+ env->cc_op = CC_OP_TSUBTV;
+ env->cc_src = src1;
+ env->cc_src2 = src2;
+ env->cc_dst = dst;
+ return dst;
+
+ tag_overflow:
+ cpu_restore_state2(env, GETPC());
+ helper_raise_exception(env, TT_TOVF);
+}
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 827df67..e1ae3c7 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -38,6 +38,8 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
+DEF_HELPER_3(taddcctv, tl, env, tl, tl)
+DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
#ifdef TARGET_SPARC64
DEF_HELPER_3(sdivx, s64, env, s64, s64)
DEF_HELPER_3(udivx, i64, env, i64, i64)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 111c025..98efb84 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -336,43 +336,6 @@ static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src)
tcg_gen_andi_tl(reg, reg, 0x1);
}
-static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
-{
- TCGv r_temp;
- TCGv_i32 r_const;
- int l1;
-
- l1 = gen_new_label();
-
- r_temp = tcg_temp_new();
- tcg_gen_xor_tl(r_temp, src1, src2);
- tcg_gen_not_tl(r_temp, r_temp);
- tcg_gen_xor_tl(cpu_tmp0, src1, dst);
- tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
- tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
- r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
- tcg_temp_free(r_temp);
-}
-
-static inline void gen_tag_tv(TCGv src1, TCGv src2)
-{
- int l1;
- TCGv_i32 r_const;
-
- l1 = gen_new_label();
- tcg_gen_or_tl(cpu_tmp0, src1, src2);
- tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
- tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
- r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
-}
-
static inline void gen_op_addi_cc(TCGv dst, TCGv src1, target_long src2)
{
tcg_gen_mov_tl(cpu_cc_src, src1);
@@ -517,45 +480,6 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
}
}
-static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
-static inline void gen_op_tadd_ccTV(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- gen_tag_tv(cpu_cc_src, cpu_cc_src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- gen_add_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
-static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
-{
- TCGv r_temp;
- TCGv_i32 r_const;
- int l1;
-
- l1 = gen_new_label();
-
- r_temp = tcg_temp_new();
- tcg_gen_xor_tl(r_temp, src1, src2);
- tcg_gen_xor_tl(cpu_tmp0, src1, dst);
- tcg_gen_and_tl(r_temp, r_temp, cpu_tmp0);
- tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
- r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(cpu_env, r_const);
- tcg_temp_free_i32(r_const);
- gen_set_label(l1);
- tcg_temp_free(r_temp);
-}
-
static inline void gen_op_subi_cc(TCGv dst, TCGv src1, target_long src2, DisasContext *dc)
{
tcg_gen_mov_tl(cpu_cc_src, src1);
@@ -656,24 +580,6 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
}
}
-static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
-static inline void gen_op_tsub_ccTV(TCGv dst, TCGv src1, TCGv src2)
-{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- gen_tag_tv(cpu_cc_src, cpu_cc_src2);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- gen_sub_tv(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
-
static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
{
TCGv r_temp;
@@ -3602,29 +3508,27 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
cpu_src2 = get_src2(insn, cpu_src2);
switch (xop) {
case 0x20: /* taddcc */
- gen_op_tadd_cc(cpu_dst, cpu_src1, cpu_src2);
+ gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
dc->cc_op = CC_OP_TADD;
break;
case 0x21: /* tsubcc */
- gen_op_tsub_cc(cpu_dst, cpu_src1, cpu_src2);
+ gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
dc->cc_op = CC_OP_TSUB;
break;
case 0x22: /* taddcctv */
- save_state(dc);
- gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_taddcctv(cpu_dst, cpu_env,
+ cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV);
dc->cc_op = CC_OP_TADDTV;
break;
case 0x23: /* tsubcctv */
- save_state(dc);
- gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_tsubcctv(cpu_dst, cpu_env,
+ cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV);
dc->cc_op = CC_OP_TSUBTV;
break;
case 0x24: /* mulscc */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 19/23] target-sparc: Use movcond in mulscc
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (17 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 18/23] target-sparc: Move taddcctv and tsubcctv out of line Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 20/23] target-sparc: Use movcond for FMOV*R Richard Henderson
` (4 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 98efb84..614905e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -582,22 +582,21 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
{
- TCGv r_temp;
- int l1;
+ TCGv r_temp, zero;
- l1 = gen_new_label();
r_temp = tcg_temp_new();
/* old op:
if (!(env->y & 1))
T1 = 0;
*/
+ zero = tcg_const_tl(0);
tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
- tcg_gen_brcondi_tl(TCG_COND_NE, r_temp, 0, l1);
- tcg_gen_movi_tl(cpu_cc_src2, 0);
- gen_set_label(l1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero,
+ zero, cpu_cc_src2);
+ tcg_temp_free(zero);
// b2 = T0 & 1;
// env->y = (b2 << 31) | (env->y >> 1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 20/23] target-sparc: Use movcond for FMOV*R
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (18 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 19/23] target-sparc: Use movcond in mulscc Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 21/23] target-sparc: Cleanup "global" temporary allocation Richard Henderson
` (3 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 46 ++++++++++++++++------------------------------
1 file changed, 16 insertions(+), 30 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 614905e..d594284 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3051,44 +3051,30 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26);
save_state(dc);
-#ifdef TARGET_SPARC64
- if ((xop & 0x11f) == 0x005) { // V9 fmovsr
- int l1;
- l1 = gen_new_label();
- cond = GET_FIELD_SP(insn, 14, 17);
- cpu_src1 = get_src1(insn, cpu_src1);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
- 0, l1);
- cpu_src1_32 = gen_load_fpr_F(dc, rs2);
- gen_store_fpr_F(dc, rd, cpu_src1_32);
- gen_set_label(l1);
+#ifdef TARGET_SPARC64
+#define FMOVR(sz) \
+ do { \
+ DisasCompare cmp; \
+ cond = GET_FIELD_SP(insn, 14, 17); \
+ cpu_src1 = get_src1(insn, cpu_src1); \
+ gen_compare_reg(&cmp, cond, cpu_src1); \
+ gen_fmov##sz(dc, &cmp, rd, rs2); \
+ free_compare(&cmp); \
+ } while (0)
+
+ if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
+ FMOVR(s);
break;
} else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
- int l1;
-
- l1 = gen_new_label();
- cond = GET_FIELD_SP(insn, 14, 17);
- cpu_src1 = get_src1(insn, cpu_src1);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
- 0, l1);
- cpu_src1_64 = gen_load_fpr_D(dc, rs2);
- gen_store_fpr_D(dc, rd, cpu_src1_64);
- gen_set_label(l1);
+ FMOVR(d);
break;
} else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
- int l1;
-
CHECK_FPU_FEATURE(dc, FLOAT128);
- l1 = gen_new_label();
- cond = GET_FIELD_SP(insn, 14, 17);
- cpu_src1 = get_src1(insn, cpu_src1);
- tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
- 0, l1);
- gen_move_Q(rd, rs2);
- gen_set_label(l1);
+ FMOVR(q);
break;
}
+#undef FMOVR
#endif
switch (xop) {
#ifdef TARGET_SPARC64
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 21/23] target-sparc: Cleanup "global" temporary allocation
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (19 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 20/23] target-sparc: Use movcond for FMOV*R Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 22/23] target-sparc: Fall through from not-taken trap Richard Henderson
` (2 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
There are 6 temporaries that disas_sparc_insn relies on having been
allocated. Now that they are no longer referenced across branches,
they need not be allocated as local temps.
Move the allocation/free of these temporaries to make it clear that
they are local to the translation of a single insn.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d594284..48c245e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5177,16 +5177,6 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
dc->singlestep = (env->singlestep_enabled || singlestep);
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
- cpu_tmp0 = tcg_temp_new();
- cpu_tmp32 = tcg_temp_new_i32();
- cpu_tmp64 = tcg_temp_new_i64();
-
- cpu_dst = tcg_temp_local_new();
-
- // loads and stores
- cpu_val = tcg_temp_local_new();
- cpu_addr = tcg_temp_local_new();
-
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0)
@@ -5222,9 +5212,24 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
gen_io_start();
last_pc = dc->pc;
insn = cpu_ldl_code(env, dc->pc);
+
+ cpu_tmp0 = tcg_temp_new();
+ cpu_tmp32 = tcg_temp_new_i32();
+ cpu_tmp64 = tcg_temp_new_i64();
+ cpu_dst = tcg_temp_new();
+ cpu_val = tcg_temp_new();
+ cpu_addr = tcg_temp_new();
+
disas_sparc_insn(dc, insn);
num_insns++;
+ tcg_temp_free(cpu_addr);
+ tcg_temp_free(cpu_val);
+ tcg_temp_free(cpu_dst);
+ tcg_temp_free_i64(cpu_tmp64);
+ tcg_temp_free_i32(cpu_tmp32);
+ tcg_temp_free(cpu_tmp0);
+
if (dc->is_br)
break;
/* if the next PC is different, we abort now */
@@ -5244,23 +5249,18 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
num_insns < max_insns);
exit_gen_loop:
- tcg_temp_free(cpu_addr);
- tcg_temp_free(cpu_val);
- tcg_temp_free(cpu_dst);
- tcg_temp_free_i64(cpu_tmp64);
- tcg_temp_free_i32(cpu_tmp32);
- tcg_temp_free(cpu_tmp0);
-
- if (tb->cflags & CF_LAST_IO)
+ if (tb->cflags & CF_LAST_IO) {
gen_io_end();
+ }
if (!dc->is_br) {
if (dc->pc != DYNAMIC_PC &&
(dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
/* static PC and NPC: we can use direct chaining */
gen_goto_tb(dc, 0, dc->pc, dc->npc);
} else {
- if (dc->pc != DYNAMIC_PC)
+ if (dc->pc != DYNAMIC_PC) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
+ }
save_npc(dc);
tcg_gen_exit_tb(0);
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 22/23] target-sparc: Fall through from not-taken trap
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (20 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 21/23] target-sparc: Cleanup "global" temporary allocation Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC Richard Henderson
2012-10-07 18:44 ` [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Blue Swirl
23 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Now that we've cleaned up global temporary allocation, we can
continue translating the fallthru path of a conditional trap.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 48c245e..a7f6407 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2573,13 +2573,15 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_helper_raise_exception(cpu_env, trap);
tcg_temp_free_i32(trap);
- if (cond != 8) {
+ if (cond == 8) {
+ /* An unconditional trap ends the TB. */
+ dc->is_br = 1;
+ goto jmp_insn;
+ } else {
+ /* A conditional trap falls through to the next insn. */
gen_set_label(l1);
- gen_op_next_insn();
- tcg_gen_exit_tb(0);
+ break;
}
- dc->is_br = 1;
- goto jmp_insn;
} else if (xop == 0x28) {
rs1 = GET_FIELD(insn, 13, 17);
switch(rs1) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (21 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 22/23] target-sparc: Fall through from not-taken trap Richard Henderson
@ 2012-10-05 23:55 ` Richard Henderson
2012-10-07 18:48 ` Blue Swirl
2012-10-07 22:40 ` Aurelien Jarno
2012-10-07 18:44 ` [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Blue Swirl
23 siblings, 2 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-05 23:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl
Aka "normal" comparisons. We now have the infrastructure to
pass back non-boolean results from gen_compare. This will
automatically get used by both branches and conditional moves.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-sparc/translate.c | 192 ++++++++++++++++++++++++++++++++---------------
1 file changed, 131 insertions(+), 61 deletions(-)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index a7f6407..472eb51 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1046,83 +1046,153 @@ static void free_compare(DisasCompare *cmp)
}
}
-static void gen_compare(DisasCompare *cmp, unsigned int cc, unsigned int cond,
+static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
DisasContext *dc)
{
+ static int subcc_cond[16] = {
+ -1, /* never */
+ TCG_COND_EQ,
+ TCG_COND_LE,
+ TCG_COND_LT,
+ TCG_COND_LEU,
+ TCG_COND_LTU,
+ -1, /* neg */
+ -1, /* overflow */
+ -1, /* always */
+ TCG_COND_NE,
+ TCG_COND_GT,
+ TCG_COND_GE,
+ TCG_COND_GTU,
+ TCG_COND_GEU,
+ -1, /* pos */
+ -1, /* no overflow */
+ };
+
TCGv_i32 r_src;
TCGv r_dst;
- /* For now we still generate a straight boolean result. */
- cmp->cond = TCG_COND_NE;
- cmp->is_bool = true;
- cmp->g1 = cmp->g2 = false;
- cmp->c1 = r_dst = tcg_temp_new();
- cmp->c2 = tcg_const_tl(0);
-
#ifdef TARGET_SPARC64
- if (cc)
+ if (xcc) {
r_src = cpu_xcc;
- else
+ } else {
r_src = cpu_psr;
+ }
#else
r_src = cpu_psr;
#endif
+
switch (dc->cc_op) {
- case CC_OP_FLAGS:
+ case CC_OP_SUB:
+ switch (cond) {
+ case 6: /* neg */
+ case 14: /* pos */
+ cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE);
+ cmp->is_bool = false;
+ cmp->g2 = false;
+ cmp->c2 = tcg_const_tl(0);
+#ifdef TARGET_SPARC64
+ if (!xcc) {
+ cmp->g1 = false;
+ cmp->c1 = tcg_temp_new();
+ tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst);
+ break;
+ }
+#endif
+ cmp->g1 = true;
+ cmp->c1 = cpu_cc_dst;
+ break;
+
+ case 0: /* never */
+ case 8: /* always */
+ case 7: /* overflow */
+ case 15: /* !overflow */
+ goto do_dynamic;
+
+ default:
+ cmp->cond = subcc_cond[cond];
+ cmp->is_bool = false;
+#ifdef TARGET_SPARC64
+ if (!xcc) {
+ /* Note that sign-extension works for unsigned compares as
+ long as both operands are sign-extended. */
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = tcg_temp_new();
+ cmp->c2 = tcg_temp_new();
+ tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src);
+ tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2);
+ }
+#endif
+ cmp->g1 = cmp->g2 = true;
+ cmp->c1 = cpu_cc_src;
+ cmp->c2 = cpu_cc_src2;
+ break;
+ }
break;
+
default:
+ do_dynamic:
gen_helper_compute_psr(cpu_env);
dc->cc_op = CC_OP_FLAGS;
- break;
- }
- switch (cond) {
- case 0x0:
- gen_op_eval_bn(r_dst);
- break;
- case 0x1:
- gen_op_eval_be(r_dst, r_src);
- break;
- case 0x2:
- gen_op_eval_ble(r_dst, r_src);
- break;
- case 0x3:
- gen_op_eval_bl(r_dst, r_src);
- break;
- case 0x4:
- gen_op_eval_bleu(r_dst, r_src);
- break;
- case 0x5:
- gen_op_eval_bcs(r_dst, r_src);
- break;
- case 0x6:
- gen_op_eval_bneg(r_dst, r_src);
- break;
- case 0x7:
- gen_op_eval_bvs(r_dst, r_src);
- break;
- case 0x8:
- gen_op_eval_ba(r_dst);
- break;
- case 0x9:
- gen_op_eval_bne(r_dst, r_src);
- break;
- case 0xa:
- gen_op_eval_bg(r_dst, r_src);
- break;
- case 0xb:
- gen_op_eval_bge(r_dst, r_src);
- break;
- case 0xc:
- gen_op_eval_bgu(r_dst, r_src);
- break;
- case 0xd:
- gen_op_eval_bcc(r_dst, r_src);
- break;
- case 0xe:
- gen_op_eval_bpos(r_dst, r_src);
- break;
- case 0xf:
- gen_op_eval_bvc(r_dst, r_src);
+ /* FALLTHRU */
+
+ case CC_OP_FLAGS:
+ /* We're going to generate a boolean result. */
+ cmp->cond = TCG_COND_NE;
+ cmp->is_bool = true;
+ cmp->g1 = cmp->g2 = false;
+ cmp->c1 = r_dst = tcg_temp_new();
+ cmp->c2 = tcg_const_tl(0);
+
+ switch (cond) {
+ case 0x0:
+ gen_op_eval_bn(r_dst);
+ break;
+ case 0x1:
+ gen_op_eval_be(r_dst, r_src);
+ break;
+ case 0x2:
+ gen_op_eval_ble(r_dst, r_src);
+ break;
+ case 0x3:
+ gen_op_eval_bl(r_dst, r_src);
+ break;
+ case 0x4:
+ gen_op_eval_bleu(r_dst, r_src);
+ break;
+ case 0x5:
+ gen_op_eval_bcs(r_dst, r_src);
+ break;
+ case 0x6:
+ gen_op_eval_bneg(r_dst, r_src);
+ break;
+ case 0x7:
+ gen_op_eval_bvs(r_dst, r_src);
+ break;
+ case 0x8:
+ gen_op_eval_ba(r_dst);
+ break;
+ case 0x9:
+ gen_op_eval_bne(r_dst, r_src);
+ break;
+ case 0xa:
+ gen_op_eval_bg(r_dst, r_src);
+ break;
+ case 0xb:
+ gen_op_eval_bge(r_dst, r_src);
+ break;
+ case 0xc:
+ gen_op_eval_bgu(r_dst, r_src);
+ break;
+ case 0xd:
+ gen_op_eval_bcc(r_dst, r_src);
+ break;
+ case 0xe:
+ gen_op_eval_bpos(r_dst, r_src);
+ break;
+ case 0xf:
+ gen_op_eval_bvc(r_dst, r_src);
+ break;
+ }
break;
}
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
` (22 preceding siblings ...)
2012-10-05 23:55 ` [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC Richard Henderson
@ 2012-10-07 18:44 ` Blue Swirl
23 siblings, 0 replies; 28+ messages in thread
From: Blue Swirl @ 2012-10-07 18:44 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Fri, Oct 5, 2012 at 11:54 PM, Richard Henderson <rth@twiddle.net> wrote:
> Most of the patches are cleanup. Some of the middle patches that
> make use of setcond and movcond where apropriate do improve code
> generation. But more important that that, we no longer have tcg
> temporaries that are live across basic blocks. Indeed, the only
> remaining uses of brcond are in Tcc and the actual end-of-TB
> branching code.
>
> The final patch begins to make use of the infrastructure added
> during the cleanups. Obviously there's more that can be done
> here, handling addcc and logic ops, but I've run out of time for
> today.
Thanks, applied all.
>
> Tested on
> linux-user-test-0.3 images
> sparc32 works well
> sparc64 no longer crashes, but does exit 1
>
> the shipped openbios image
> sparc32 works well
> sparc64 works as well as head (stalls before prompt)
>
> sparc-test-0.2
> sparc32 boots to prompt
>
>
> r~
>
>
> Richard Henderson (23):
> target-sparc: Tidy cpu_dump_state
> target-sparc: Make CPU_LOG_INT useful by default
> target-sparc: Tidy do_branch interfaces
> target-sparc: Tidy flush_cond interface
> target-sparc: Tidy gen_trap_ifnofpu interface
> target-sparc: Tidy save_state interface
> target-sparc: Tidy gen_mov_pc_npc interface
> target-sparc: Tidy save_npc interface
> target-sparc: Tidy gen_generic_branch interface
> target-sparc: Introduce DisasCompare and functions to generate it
> target-sparc: Use DisasCompare in Tcc
> target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC
> target-sparc: Use DisasCompare and movcond in MOVCC
> target-sparc: Use DisasCompare and movcond in MOVR
> target-sparc: Use movcond in gen_generic_branch
> target-sparc: Move sdivx and udivx out of line
> target-sparc: Tidy Tcc
> target-sparc: Move taddcctv and tsubcctv out of line
> target-sparc: Use movcond in mulscc
> target-sparc: Use movcond for FMOV*R
> target-sparc: Cleanup "global" temporary allocation
> target-sparc: Fall through from not-taken trap
> target-sparc: Optimize conditionals using SUBCC
>
> target-sparc/cpu.c | 7 +-
> target-sparc/cpu.h | 1 +
> target-sparc/helper.c | 86 ++++
> target-sparc/helper.h | 6 +
> target-sparc/int32_helper.c | 7 +-
> target-sparc/int64_helper.c | 8 +-
> target-sparc/ldst_helper.c | 4 +-
> target-sparc/translate.c | 1133 +++++++++++++++++++++----------------------
> 8 files changed, 653 insertions(+), 599 deletions(-)
>
> --
> 1.7.11.4
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC
2012-10-05 23:55 ` [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC Richard Henderson
@ 2012-10-07 18:48 ` Blue Swirl
2012-10-07 19:16 ` Richard Henderson
2012-10-07 22:40 ` Aurelien Jarno
1 sibling, 1 reply; 28+ messages in thread
From: Blue Swirl @ 2012-10-07 18:48 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Fri, Oct 5, 2012 at 11:55 PM, Richard Henderson <rth@twiddle.net> wrote:
> Aka "normal" comparisons. We now have the infrastructure to
> pass back non-boolean results from gen_compare. This will
> automatically get used by both branches and conditional moves.
This is not yet optimal, we could do the same trick as is done for x86
for cmp/jcc case (target-i386/translate.c:889), but it's still an
improvement so I applied it with others.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-sparc/translate.c | 192 ++++++++++++++++++++++++++++++++---------------
> 1 file changed, 131 insertions(+), 61 deletions(-)
>
> diff --git a/target-sparc/translate.c b/target-sparc/translate.c
> index a7f6407..472eb51 100644
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -1046,83 +1046,153 @@ static void free_compare(DisasCompare *cmp)
> }
> }
>
> -static void gen_compare(DisasCompare *cmp, unsigned int cc, unsigned int cond,
> +static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
> DisasContext *dc)
> {
> + static int subcc_cond[16] = {
> + -1, /* never */
> + TCG_COND_EQ,
> + TCG_COND_LE,
> + TCG_COND_LT,
> + TCG_COND_LEU,
> + TCG_COND_LTU,
> + -1, /* neg */
> + -1, /* overflow */
> + -1, /* always */
> + TCG_COND_NE,
> + TCG_COND_GT,
> + TCG_COND_GE,
> + TCG_COND_GTU,
> + TCG_COND_GEU,
> + -1, /* pos */
> + -1, /* no overflow */
> + };
> +
> TCGv_i32 r_src;
> TCGv r_dst;
>
> - /* For now we still generate a straight boolean result. */
> - cmp->cond = TCG_COND_NE;
> - cmp->is_bool = true;
> - cmp->g1 = cmp->g2 = false;
> - cmp->c1 = r_dst = tcg_temp_new();
> - cmp->c2 = tcg_const_tl(0);
> -
> #ifdef TARGET_SPARC64
> - if (cc)
> + if (xcc) {
> r_src = cpu_xcc;
> - else
> + } else {
> r_src = cpu_psr;
> + }
> #else
> r_src = cpu_psr;
> #endif
> +
> switch (dc->cc_op) {
> - case CC_OP_FLAGS:
> + case CC_OP_SUB:
> + switch (cond) {
> + case 6: /* neg */
> + case 14: /* pos */
> + cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE);
> + cmp->is_bool = false;
> + cmp->g2 = false;
> + cmp->c2 = tcg_const_tl(0);
> +#ifdef TARGET_SPARC64
> + if (!xcc) {
> + cmp->g1 = false;
> + cmp->c1 = tcg_temp_new();
> + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst);
> + break;
> + }
> +#endif
> + cmp->g1 = true;
> + cmp->c1 = cpu_cc_dst;
> + break;
> +
> + case 0: /* never */
> + case 8: /* always */
> + case 7: /* overflow */
> + case 15: /* !overflow */
> + goto do_dynamic;
> +
> + default:
> + cmp->cond = subcc_cond[cond];
> + cmp->is_bool = false;
> +#ifdef TARGET_SPARC64
> + if (!xcc) {
> + /* Note that sign-extension works for unsigned compares as
> + long as both operands are sign-extended. */
> + cmp->g1 = cmp->g2 = false;
> + cmp->c1 = tcg_temp_new();
> + cmp->c2 = tcg_temp_new();
> + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src);
> + tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2);
> + }
> +#endif
> + cmp->g1 = cmp->g2 = true;
> + cmp->c1 = cpu_cc_src;
> + cmp->c2 = cpu_cc_src2;
> + break;
> + }
> break;
> +
> default:
> + do_dynamic:
> gen_helper_compute_psr(cpu_env);
> dc->cc_op = CC_OP_FLAGS;
> - break;
> - }
> - switch (cond) {
> - case 0x0:
> - gen_op_eval_bn(r_dst);
> - break;
> - case 0x1:
> - gen_op_eval_be(r_dst, r_src);
> - break;
> - case 0x2:
> - gen_op_eval_ble(r_dst, r_src);
> - break;
> - case 0x3:
> - gen_op_eval_bl(r_dst, r_src);
> - break;
> - case 0x4:
> - gen_op_eval_bleu(r_dst, r_src);
> - break;
> - case 0x5:
> - gen_op_eval_bcs(r_dst, r_src);
> - break;
> - case 0x6:
> - gen_op_eval_bneg(r_dst, r_src);
> - break;
> - case 0x7:
> - gen_op_eval_bvs(r_dst, r_src);
> - break;
> - case 0x8:
> - gen_op_eval_ba(r_dst);
> - break;
> - case 0x9:
> - gen_op_eval_bne(r_dst, r_src);
> - break;
> - case 0xa:
> - gen_op_eval_bg(r_dst, r_src);
> - break;
> - case 0xb:
> - gen_op_eval_bge(r_dst, r_src);
> - break;
> - case 0xc:
> - gen_op_eval_bgu(r_dst, r_src);
> - break;
> - case 0xd:
> - gen_op_eval_bcc(r_dst, r_src);
> - break;
> - case 0xe:
> - gen_op_eval_bpos(r_dst, r_src);
> - break;
> - case 0xf:
> - gen_op_eval_bvc(r_dst, r_src);
> + /* FALLTHRU */
> +
> + case CC_OP_FLAGS:
> + /* We're going to generate a boolean result. */
> + cmp->cond = TCG_COND_NE;
> + cmp->is_bool = true;
> + cmp->g1 = cmp->g2 = false;
> + cmp->c1 = r_dst = tcg_temp_new();
> + cmp->c2 = tcg_const_tl(0);
> +
> + switch (cond) {
> + case 0x0:
> + gen_op_eval_bn(r_dst);
> + break;
> + case 0x1:
> + gen_op_eval_be(r_dst, r_src);
> + break;
> + case 0x2:
> + gen_op_eval_ble(r_dst, r_src);
> + break;
> + case 0x3:
> + gen_op_eval_bl(r_dst, r_src);
> + break;
> + case 0x4:
> + gen_op_eval_bleu(r_dst, r_src);
> + break;
> + case 0x5:
> + gen_op_eval_bcs(r_dst, r_src);
> + break;
> + case 0x6:
> + gen_op_eval_bneg(r_dst, r_src);
> + break;
> + case 0x7:
> + gen_op_eval_bvs(r_dst, r_src);
> + break;
> + case 0x8:
> + gen_op_eval_ba(r_dst);
> + break;
> + case 0x9:
> + gen_op_eval_bne(r_dst, r_src);
> + break;
> + case 0xa:
> + gen_op_eval_bg(r_dst, r_src);
> + break;
> + case 0xb:
> + gen_op_eval_bge(r_dst, r_src);
> + break;
> + case 0xc:
> + gen_op_eval_bgu(r_dst, r_src);
> + break;
> + case 0xd:
> + gen_op_eval_bcc(r_dst, r_src);
> + break;
> + case 0xe:
> + gen_op_eval_bpos(r_dst, r_src);
> + break;
> + case 0xf:
> + gen_op_eval_bvc(r_dst, r_src);
> + break;
> + }
> break;
> }
> }
> --
> 1.7.11.4
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC
2012-10-07 18:48 ` Blue Swirl
@ 2012-10-07 19:16 ` Richard Henderson
0 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2012-10-07 19:16 UTC (permalink / raw)
To: Blue Swirl; +Cc: qemu-devel
On 10/07/2012 11:48 AM, Blue Swirl wrote:
> This is not yet optimal, we could do the same trick as is done for x86
> for cmp/jcc case (target-i386/translate.c:889), but it's still an
> improvement so I applied it with others.
It's trickier with sparc, because of the (exceedingly rare) conditional
branch in branch delay slot case. I've yet to come up with a plan to
handle that which is better than the existing cpu_cond global variable.
(Which we now at least initialize with setcond.)
r~
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC
2012-10-05 23:55 ` [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC Richard Henderson
2012-10-07 18:48 ` Blue Swirl
@ 2012-10-07 22:40 ` Aurelien Jarno
1 sibling, 0 replies; 28+ messages in thread
From: Aurelien Jarno @ 2012-10-07 22:40 UTC (permalink / raw)
To: Richard Henderson; +Cc: Blue Swirl, qemu-devel
This patch breaks the boot of a linux sparc64 kernel very early in the
boot process. The boot hangs after:
| OpenBIOS for Sparc64
| Configuration device id QEMU version 1 machine id 0
| kernel addr 404000 size 5be6b8
| kernel cmdline root=/dev/vda4 console=ttyS0
| CPUs: 1 x SUNW,UltraSPARC-IIi
| UUID: 00000000-0000-0000-0000-000000000000
| Welcome to OpenBIOS v1.0 built on Aug 19 2012 13:06
| Type 'help' for detailed information
| [sparc64] Kernel already loaded
|
| [ 0.000000] PROMLIB: Sun IEEE Boot Prom 'OBP 3.10.24 1999/01/01 01:01'
| [ 0.000000] PROMLIB: Root node compatible: sun4u
| [ 0.000000] Initializing cgroup subsys cpuset
| [ 0.000000] Initializing cgroup subsys cpu
| [ 0.000000] Linux version 3.2.0-3-sparc64 (Debian 3.2.23-1) (debian-kernel@lists.debian.org) (gcc version 4.6.3 (Debian 4.6.3-5) ) #1 Fri Aug 3 15:37:15 UTC 2012
| [ 0.000000] bootconsole [earlyprom0] enabled
| [ 0.000000] ARCH: SUN4U
| [ 0.000000] Ethernet address: 52:54:00:12:34:56
| [ 0.000000] Kernel: Using 2 locked TLB entries for main kernel image.
| [ 0.000000] Remapping the kernel... done.
| [ 0.000000] OF stdout device is: /pci@1fe,0/ebus@2/su
| [ 0.000000] PROM: Built device tree with 32122 bytes of memory.
On Fri, Oct 05, 2012 at 04:55:10PM -0700, Richard Henderson wrote:
> Aka "normal" comparisons. We now have the infrastructure to
> pass back non-boolean results from gen_compare. This will
> automatically get used by both branches and conditional moves.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-sparc/translate.c | 192 ++++++++++++++++++++++++++++++++---------------
> 1 file changed, 131 insertions(+), 61 deletions(-)
>
> diff --git a/target-sparc/translate.c b/target-sparc/translate.c
> index a7f6407..472eb51 100644
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -1046,83 +1046,153 @@ static void free_compare(DisasCompare *cmp)
> }
> }
>
> -static void gen_compare(DisasCompare *cmp, unsigned int cc, unsigned int cond,
> +static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
> DisasContext *dc)
> {
> + static int subcc_cond[16] = {
> + -1, /* never */
> + TCG_COND_EQ,
> + TCG_COND_LE,
> + TCG_COND_LT,
> + TCG_COND_LEU,
> + TCG_COND_LTU,
> + -1, /* neg */
> + -1, /* overflow */
> + -1, /* always */
> + TCG_COND_NE,
> + TCG_COND_GT,
> + TCG_COND_GE,
> + TCG_COND_GTU,
> + TCG_COND_GEU,
> + -1, /* pos */
> + -1, /* no overflow */
> + };
> +
> TCGv_i32 r_src;
> TCGv r_dst;
>
> - /* For now we still generate a straight boolean result. */
> - cmp->cond = TCG_COND_NE;
> - cmp->is_bool = true;
> - cmp->g1 = cmp->g2 = false;
> - cmp->c1 = r_dst = tcg_temp_new();
> - cmp->c2 = tcg_const_tl(0);
> -
> #ifdef TARGET_SPARC64
> - if (cc)
> + if (xcc) {
> r_src = cpu_xcc;
> - else
> + } else {
> r_src = cpu_psr;
> + }
> #else
> r_src = cpu_psr;
> #endif
> +
> switch (dc->cc_op) {
> - case CC_OP_FLAGS:
> + case CC_OP_SUB:
> + switch (cond) {
> + case 6: /* neg */
> + case 14: /* pos */
> + cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE);
> + cmp->is_bool = false;
> + cmp->g2 = false;
> + cmp->c2 = tcg_const_tl(0);
> +#ifdef TARGET_SPARC64
> + if (!xcc) {
> + cmp->g1 = false;
> + cmp->c1 = tcg_temp_new();
> + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst);
> + break;
> + }
> +#endif
> + cmp->g1 = true;
> + cmp->c1 = cpu_cc_dst;
> + break;
> +
> + case 0: /* never */
> + case 8: /* always */
> + case 7: /* overflow */
> + case 15: /* !overflow */
> + goto do_dynamic;
> +
> + default:
> + cmp->cond = subcc_cond[cond];
> + cmp->is_bool = false;
> +#ifdef TARGET_SPARC64
> + if (!xcc) {
> + /* Note that sign-extension works for unsigned compares as
> + long as both operands are sign-extended. */
> + cmp->g1 = cmp->g2 = false;
> + cmp->c1 = tcg_temp_new();
> + cmp->c2 = tcg_temp_new();
> + tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src);
> + tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2);
> + }
> +#endif
> + cmp->g1 = cmp->g2 = true;
> + cmp->c1 = cpu_cc_src;
> + cmp->c2 = cpu_cc_src2;
> + break;
> + }
> break;
> +
> default:
> + do_dynamic:
> gen_helper_compute_psr(cpu_env);
> dc->cc_op = CC_OP_FLAGS;
> - break;
> - }
> - switch (cond) {
> - case 0x0:
> - gen_op_eval_bn(r_dst);
> - break;
> - case 0x1:
> - gen_op_eval_be(r_dst, r_src);
> - break;
> - case 0x2:
> - gen_op_eval_ble(r_dst, r_src);
> - break;
> - case 0x3:
> - gen_op_eval_bl(r_dst, r_src);
> - break;
> - case 0x4:
> - gen_op_eval_bleu(r_dst, r_src);
> - break;
> - case 0x5:
> - gen_op_eval_bcs(r_dst, r_src);
> - break;
> - case 0x6:
> - gen_op_eval_bneg(r_dst, r_src);
> - break;
> - case 0x7:
> - gen_op_eval_bvs(r_dst, r_src);
> - break;
> - case 0x8:
> - gen_op_eval_ba(r_dst);
> - break;
> - case 0x9:
> - gen_op_eval_bne(r_dst, r_src);
> - break;
> - case 0xa:
> - gen_op_eval_bg(r_dst, r_src);
> - break;
> - case 0xb:
> - gen_op_eval_bge(r_dst, r_src);
> - break;
> - case 0xc:
> - gen_op_eval_bgu(r_dst, r_src);
> - break;
> - case 0xd:
> - gen_op_eval_bcc(r_dst, r_src);
> - break;
> - case 0xe:
> - gen_op_eval_bpos(r_dst, r_src);
> - break;
> - case 0xf:
> - gen_op_eval_bvc(r_dst, r_src);
> + /* FALLTHRU */
> +
> + case CC_OP_FLAGS:
> + /* We're going to generate a boolean result. */
> + cmp->cond = TCG_COND_NE;
> + cmp->is_bool = true;
> + cmp->g1 = cmp->g2 = false;
> + cmp->c1 = r_dst = tcg_temp_new();
> + cmp->c2 = tcg_const_tl(0);
> +
> + switch (cond) {
> + case 0x0:
> + gen_op_eval_bn(r_dst);
> + break;
> + case 0x1:
> + gen_op_eval_be(r_dst, r_src);
> + break;
> + case 0x2:
> + gen_op_eval_ble(r_dst, r_src);
> + break;
> + case 0x3:
> + gen_op_eval_bl(r_dst, r_src);
> + break;
> + case 0x4:
> + gen_op_eval_bleu(r_dst, r_src);
> + break;
> + case 0x5:
> + gen_op_eval_bcs(r_dst, r_src);
> + break;
> + case 0x6:
> + gen_op_eval_bneg(r_dst, r_src);
> + break;
> + case 0x7:
> + gen_op_eval_bvs(r_dst, r_src);
> + break;
> + case 0x8:
> + gen_op_eval_ba(r_dst);
> + break;
> + case 0x9:
> + gen_op_eval_bne(r_dst, r_src);
> + break;
> + case 0xa:
> + gen_op_eval_bg(r_dst, r_src);
> + break;
> + case 0xb:
> + gen_op_eval_bge(r_dst, r_src);
> + break;
> + case 0xc:
> + gen_op_eval_bgu(r_dst, r_src);
> + break;
> + case 0xd:
> + gen_op_eval_bcc(r_dst, r_src);
> + break;
> + case 0xe:
> + gen_op_eval_bpos(r_dst, r_src);
> + break;
> + case 0xf:
> + gen_op_eval_bvc(r_dst, r_src);
> + break;
> + }
> break;
> }
> }
> --
> 1.7.11.4
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2012-10-07 22:40 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-05 23:54 [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 01/23] target-sparc: Tidy cpu_dump_state Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 02/23] target-sparc: Make CPU_LOG_INT useful by default Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 03/23] target-sparc: Tidy do_branch interfaces Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 04/23] target-sparc: Tidy flush_cond interface Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 05/23] target-sparc: Tidy gen_trap_ifnofpu interface Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 06/23] target-sparc: Tidy save_state interface Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 07/23] target-sparc: Tidy gen_mov_pc_npc interface Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 08/23] target-sparc: Tidy save_npc interface Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 09/23] target-sparc: Tidy gen_generic_branch interface Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 10/23] target-sparc: Introduce DisasCompare and functions to generate it Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 11/23] target-sparc: Use DisasCompare in Tcc Richard Henderson
2012-10-05 23:54 ` [Qemu-devel] [PATCH 12/23] target-sparc: Use DisasCompare and movcond in FMOVR, FMOVCC Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 13/23] target-sparc: Use DisasCompare and movcond in MOVCC Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 14/23] target-sparc: Use DisasCompare and movcond in MOVR Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 15/23] target-sparc: Use movcond in gen_generic_branch Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 16/23] target-sparc: Move sdivx and udivx out of line Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 17/23] target-sparc: Tidy Tcc Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 18/23] target-sparc: Move taddcctv and tsubcctv out of line Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 19/23] target-sparc: Use movcond in mulscc Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 20/23] target-sparc: Use movcond for FMOV*R Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 21/23] target-sparc: Cleanup "global" temporary allocation Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 22/23] target-sparc: Fall through from not-taken trap Richard Henderson
2012-10-05 23:55 ` [Qemu-devel] [PATCH 23/23] target-sparc: Optimize conditionals using SUBCC Richard Henderson
2012-10-07 18:48 ` Blue Swirl
2012-10-07 19:16 ` Richard Henderson
2012-10-07 22:40 ` Aurelien Jarno
2012-10-07 18:44 ` [Qemu-devel] [PATCH 00/23] target-sparc comparison improvements Blue Swirl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).