summaryrefslogtreecommitdiff
path: root/target-cris/op.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-cris/op.c')
-rw-r--r--target-cris/op.c397
1 files changed, 46 insertions, 351 deletions
diff --git a/target-cris/op.c b/target-cris/op.c
index d44185c4d4..a446e20d93 100644
--- a/target-cris/op.c
+++ b/target-cris/op.c
@@ -192,17 +192,32 @@ void OPPROTO op_ccs_lshift (void)
}
void OPPROTO op_ccs_rshift (void)
{
- uint32_t ccs;
+ register uint32_t ccs;
/* Apply the ccs shift. */
ccs = env->pregs[PR_CCS];
ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
+ if (ccs & U_FLAG)
+ {
+ /* Enter user mode. */
+ env->ksp = env->regs[R_SP];
+ env->regs[R_SP] = env->pregs[PR_USP];
+ }
+
env->pregs[PR_CCS] = ccs;
+
RETURN();
}
void OPPROTO op_setf (void)
{
+ if (!(env->pregs[PR_CCS] & U_FLAG) && (PARAM1 & U_FLAG))
+ {
+ /* Enter user mode. */
+ env->ksp = env->regs[R_SP];
+ env->regs[R_SP] = env->pregs[PR_USP];
+ }
+
env->pregs[PR_CCS] |= PARAM1;
RETURN();
}
@@ -265,7 +280,11 @@ void OPPROTO op_movl_flags_T0 (void)
void OPPROTO op_movl_sreg_T0 (void)
{
- env->sregs[env->pregs[PR_SRS]][PARAM1] = T0;
+ uint32_t srs;
+ srs = env->pregs[PR_SRS];
+ srs &= 3;
+
+ env->sregs[srs][PARAM1] = T0;
RETURN();
}
@@ -285,7 +304,10 @@ void OPPROTO op_movl_tlb_hi_T0 (void)
void OPPROTO op_movl_tlb_lo_T0 (void)
{
uint32_t srs;
+
+ env->pregs[PR_SRS] &= 3;
srs = env->pregs[PR_SRS];
+
if (srs == 1 || srs == 2)
{
uint32_t set;
@@ -309,7 +331,28 @@ void OPPROTO op_movl_tlb_lo_T0 (void)
void OPPROTO op_movl_T0_sreg (void)
{
- T0 = env->sregs[env->pregs[PR_SRS]][PARAM1];
+ uint32_t srs;
+ env->pregs[PR_SRS] &= 3;
+ srs = env->pregs[PR_SRS];
+
+ if (srs == 1 || srs == 2)
+ {
+ uint32_t set;
+ uint32_t idx;
+ uint32_t lo, hi;
+
+ idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
+ set >>= 4;
+ set &= 3;
+ idx &= 15;
+
+ /* Update the mirror regs. */
+ hi = env->tlbsets[srs - 1][set][idx].hi;
+ lo = env->tlbsets[srs - 1][set][idx].lo;
+ env->sregs[SFR_RW_MM_TLB_HI] = hi;
+ env->sregs[SFR_RW_MM_TLB_LO] = lo;
+ }
+ T0 = env->sregs[srs][PARAM1];
RETURN();
}
@@ -363,340 +406,6 @@ void OPPROTO op_update_cc_x (void)
RETURN();
}
-/* FIXME: is this allowed? */
-extern inline 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;
-
- if ((x || env->cc_op == CC_OP_ADDC)
- && flags & Z_FLAG)
- env->cc_mask &= ~Z_FLAG;
-
- /* all insn clear the x-flag except setf or clrf. */
- env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
- flags &= env->cc_mask;
- env->pregs[PR_CCS] |= flags;
- RETURN();
-}
-
-void OPPROTO op_evaluate_flags_muls(void)
-{
- uint32_t src;
- uint32_t dst;
- uint32_t res;
- uint32_t flags = 0;
- /* were gonna have to redo the muls. */
- int64_t tmp, t0 ,t1;
- int32_t mof;
- int dneg;
-
- src = env->cc_src;
- dst = env->cc_dest;
- res = env->cc_result;
-
-
- /* cast into signed values to make GCC sign extend. */
- t0 = (int32_t)src;
- t1 = (int32_t)dst;
- dneg = ((int32_t)res) < 0;
-
- tmp = t0 * t1;
- mof = tmp >> 32;
- if (tmp == 0)
- flags |= Z_FLAG;
- else if (tmp < 0)
- flags |= N_FLAG;
- if ((dneg && mof != -1)
- || (!dneg && mof != 0))
- flags |= V_FLAG;
- evaluate_flags_writeback(flags);
- RETURN();
-}
-
-void OPPROTO op_evaluate_flags_mulu(void)
-{
- uint32_t src;
- uint32_t dst;
- uint32_t res;
- uint32_t flags = 0;
- /* were gonna have to redo the muls. */
- uint64_t tmp, t0 ,t1;
- uint32_t mof;
-
- src = env->cc_src;
- dst = env->cc_dest;
- res = env->cc_result;
-
-
- /* cast into signed values to make GCC sign extend. */
- t0 = src;
- t1 = dst;
-
- tmp = t0 * t1;
- mof = tmp >> 32;
- if (tmp == 0)
- flags |= Z_FLAG;
- else if (tmp >> 63)
- flags |= N_FLAG;
- if (mof)
- flags |= V_FLAG;
-
- evaluate_flags_writeback(flags);
- RETURN();
-}
-
-void OPPROTO op_evaluate_flags_mcp(void)
-{
- uint32_t src;
- uint32_t dst;
- uint32_t res;
- uint32_t flags = 0;
-
- src = env->cc_src;
- dst = env->cc_dest;
- res = env->cc_result;
-
- if ((res & 0x80000000L) != 0L)
- {
- flags |= N_FLAG;
- if (((src & 0x80000000L) == 0L)
- && ((dst & 0x80000000L) == 0L))
- {
- flags |= V_FLAG;
- }
- else if (((src & 0x80000000L) != 0L) &&
- ((dst & 0x80000000L) != 0L))
- {
- flags |= R_FLAG;
- }
- }
- else
- {
- if (res == 0L)
- flags |= Z_FLAG;
- if (((src & 0x80000000L) != 0L)
- && ((dst & 0x80000000L) != 0L))
- flags |= V_FLAG;
- if ((dst & 0x80000000L) != 0L
- || (src & 0x80000000L) != 0L)
- flags |= R_FLAG;
- }
-
- evaluate_flags_writeback(flags);
- RETURN();
-}
-
-void OPPROTO op_evaluate_flags_alu_4(void)
-{
- uint32_t src;
- uint32_t dst;
- uint32_t res;
- uint32_t flags = 0;
-
- src = env->cc_src;
- dst = env->cc_dest;
- res = env->cc_result;
-
- if ((res & 0x80000000L) != 0L)
- {
- flags |= N_FLAG;
- if (((src & 0x80000000L) == 0L)
- && ((dst & 0x80000000L) == 0L))
- {
- flags |= V_FLAG;
- }
- else if (((src & 0x80000000L) != 0L) &&
- ((dst & 0x80000000L) != 0L))
- {
- flags |= C_FLAG;
- }
- }
- else
- {
- if (res == 0L)
- flags |= Z_FLAG;
- if (((src & 0x80000000L) != 0L)
- && ((dst & 0x80000000L) != 0L))
- flags |= V_FLAG;
- if ((dst & 0x80000000L) != 0L
- || (src & 0x80000000L) != 0L)
- flags |= C_FLAG;
- }
-
- if (env->cc_op == CC_OP_SUB
- || env->cc_op == CC_OP_CMP) {
- flags ^= C_FLAG;
- }
- evaluate_flags_writeback(flags);
- RETURN();
-}
-
-void OPPROTO op_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)
- flags |= N_FLAG;
- else if (res == 0L)
- flags |= Z_FLAG;
-
- evaluate_flags_writeback(flags);
- RETURN();
-}
-void OPPROTO op_evaluate_flags_move_2 (void)
-{
- uint32_t src;
- uint32_t flags = 0;
- uint16_t res;
-
- src = env->cc_src;
- res = env->cc_result;
-
- if ((int16_t)res < 0L)
- flags |= N_FLAG;
- else if (res == 0)
- flags |= Z_FLAG;
-
- evaluate_flags_writeback(flags);
- RETURN();
-}
-
-/* TODO: This is expensive. We could split things up and only evaluate part of
- CCR on a need to know basis. For now, we simply re-evaluate everything. */
-void OPPROTO op_evaluate_flags (void)
-{
- uint32_t src;
- uint32_t dst;
- uint32_t res;
- uint32_t flags = 0;
-
- src = env->cc_src;
- dst = env->cc_dest;
- res = env->cc_result;
-
-
- /* Now, evaluate the flags. This stuff is based on
- Per Zander's CRISv10 simulator. */
- switch (env->cc_size)
- {
- case 1:
- if ((res & 0x80L) != 0L)
- {
- flags |= N_FLAG;
- if (((src & 0x80L) == 0L)
- && ((dst & 0x80L) == 0L))
- {
- flags |= V_FLAG;
- }
- else if (((src & 0x80L) != 0L)
- && ((dst & 0x80L) != 0L))
- {
- flags |= C_FLAG;
- }
- }
- else
- {
- if ((res & 0xFFL) == 0L)
- {
- flags |= Z_FLAG;
- }
- if (((src & 0x80L) != 0L)
- && ((dst & 0x80L) != 0L))
- {
- flags |= V_FLAG;
- }
- if ((dst & 0x80L) != 0L
- || (src & 0x80L) != 0L)
- {
- flags |= C_FLAG;
- }
- }
- break;
- case 2:
- if ((res & 0x8000L) != 0L)
- {
- flags |= N_FLAG;
- if (((src & 0x8000L) == 0L)
- && ((dst & 0x8000L) == 0L))
- {
- flags |= V_FLAG;
- }
- else if (((src & 0x8000L) != 0L)
- && ((dst & 0x8000L) != 0L))
- {
- flags |= C_FLAG;
- }
- }
- else
- {
- if ((res & 0xFFFFL) == 0L)
- {
- flags |= Z_FLAG;
- }
- if (((src & 0x8000L) != 0L)
- && ((dst & 0x8000L) != 0L))
- {
- flags |= V_FLAG;
- }
- if ((dst & 0x8000L) != 0L
- || (src & 0x8000L) != 0L)
- {
- flags |= C_FLAG;
- }
- }
- break;
- case 4:
- if ((res & 0x80000000L) != 0L)
- {
- flags |= N_FLAG;
- if (((src & 0x80000000L) == 0L)
- && ((dst & 0x80000000L) == 0L))
- {
- flags |= V_FLAG;
- }
- else if (((src & 0x80000000L) != 0L) &&
- ((dst & 0x80000000L) != 0L))
- {
- flags |= C_FLAG;
- }
- }
- else
- {
- if (res == 0L)
- flags |= Z_FLAG;
- if (((src & 0x80000000L) != 0L)
- && ((dst & 0x80000000L) != 0L))
- flags |= V_FLAG;
- if ((dst & 0x80000000L) != 0L
- || (src & 0x80000000L) != 0L)
- flags |= C_FLAG;
- }
- break;
- default:
- break;
- }
-
- if (env->cc_op == CC_OP_SUB
- || env->cc_op == CC_OP_CMP) {
- flags ^= C_FLAG;
- }
- evaluate_flags_writeback(flags);
- RETURN();
-}
-
void OPPROTO op_extb_T0_T0 (void)
{
T0 = ((int8_t)T0);
@@ -1274,17 +983,3 @@ void OPPROTO op_jmp1 (void)
env->pc = env->btarget;
RETURN();
}
-
-/* Load and store */
-#define MEMSUFFIX _raw
-#include "op_mem.c"
-#undef MEMSUFFIX
-#if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _user
-#include "op_mem.c"
-#undef MEMSUFFIX
-
-#define MEMSUFFIX _kernel
-#include "op_mem.c"
-#undef MEMSUFFIX
-#endif