diff options
Diffstat (limited to 'target-cris/op_helper.c')
-rw-r--r-- | target-cris/op_helper.c | 93 |
1 files changed, 77 insertions, 16 deletions
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index abcf9b47ff..ebff31a1de 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 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) /* 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 @@ void helper_tlb_flush_pid(uint32_t pid) #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 @@ static void evaluate_flags_writeback(uint32_t flags) 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 @@ void helper_evaluate_flags_alu_4(void) 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_alu_4(void) 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 @@ void helper_evaluate_flags (void) 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 @@ void helper_evaluate_flags (void) } 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; + } +} |