CRIS: Restructure the translator to allow for better code generation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4594 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index abcf9b4..ebff31a 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -22,6 +22,7 @@
#include <assert.h>
#include "exec.h"
#include "mmu.h"
+#include "helper.h"
#define MMUSUFFIX _mmu
@@ -67,6 +68,9 @@
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
cpu_restore_state(tb, env, pc, NULL);
+
+ /* Evaluate flags after retranslation. */
+ helper_top_evaluate_flags();
}
}
cpu_loop_exit();
@@ -87,12 +91,7 @@
#endif
}
-void helper_tlb_flush(void)
-{
- tlb_flush(env, 1);
-}
-
-void helper_dump(uint32_t a0, uint32_t a1)
+void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2)
{
(fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1));
}
@@ -236,13 +235,7 @@
int x;
/* Extended arithmetics, leave the z flag alone. */
- env->debug3 = env->pregs[PR_CCS];
-
- if (env->cc_x_live)
- x = env->cc_x;
- else
- x = env->pregs[PR_CCS] & X_FLAG;
-
+ x = env->cc_x;
if ((x || env->cc_op == CC_OP_ADDC)
&& flags & Z_FLAG)
env->cc_mask &= ~Z_FLAG;
@@ -359,7 +352,23 @@
src = env->cc_src;
dst = env->cc_dest;
- res = env->cc_result;
+
+ /* Reconstruct the result. */
+ switch (env->cc_op)
+ {
+ case CC_OP_SUB:
+ res = dst - src;
+ break;
+ case CC_OP_ADD:
+ res = dst + src;
+ break;
+ default:
+ res = env->cc_result;
+ break;
+ }
+
+ if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
+ src = ~src;
if ((res & 0x80000000L) != 0L)
{
@@ -396,11 +405,9 @@
void helper_evaluate_flags_move_4 (void)
{
- uint32_t src;
uint32_t res;
uint32_t flags = 0;
- src = env->cc_src;
res = env->cc_result;
if ((int32_t)res < 0)
@@ -440,6 +447,8 @@
dst = env->cc_dest;
res = env->cc_result;
+ if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
+ src = ~src;
/* Now, evaluate the flags. This stuff is based on
Per Zander's CRISv10 simulator. */
@@ -548,3 +557,55 @@
}
evaluate_flags_writeback(flags);
}
+
+void helper_top_evaluate_flags(void)
+{
+ switch (env->cc_op)
+ {
+ case CC_OP_MCP:
+ helper_evaluate_flags_mcp();
+ break;
+ case CC_OP_MULS:
+ helper_evaluate_flags_muls();
+ break;
+ case CC_OP_MULU:
+ helper_evaluate_flags_mulu();
+ break;
+ case CC_OP_MOVE:
+ case CC_OP_AND:
+ case CC_OP_OR:
+ case CC_OP_XOR:
+ case CC_OP_ASR:
+ case CC_OP_LSR:
+ case CC_OP_LSL:
+ switch (env->cc_size)
+ {
+ case 4:
+ helper_evaluate_flags_move_4();
+ break;
+ case 2:
+ helper_evaluate_flags_move_2();
+ break;
+ default:
+ helper_evaluate_flags();
+ break;
+ }
+ break;
+ case CC_OP_FLAGS:
+ /* live. */
+ break;
+ default:
+ {
+ switch (env->cc_size)
+ {
+ case 4:
+ helper_evaluate_flags_alu_4();
+ break;
+ default:
+ helper_evaluate_flags();
+ break;
+ }
+ }
+ break;
+ }
+}