mirror of https://github.com/xemu-project/xemu.git
CRIS: More TCG conversion.
* Convert moves to/from support function regs (including TLB updates) to TCG. * SCC no longer requires T0 to strictly be 0 or 1, relaxed to 0 or non-zero. * Convert the the condition code evaluation to TCG. * Convert rfe into a helper and TCG. * Convert evaluate_bcc and setf to TCG. * Convert clrf to TCG. * Convert CRIS exception raising to TCG. * Convert btst to TCG. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4376 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
069de56277
commit
dceaf39458
|
@ -1,11 +1,15 @@
|
|||
#define TCG_HELPER_PROTO
|
||||
void TCG_HELPER_PROTO helper_tlb_update(uint32_t T0);
|
||||
|
||||
void TCG_HELPER_PROTO helper_raise_exception(uint32_t index);
|
||||
void TCG_HELPER_PROTO helper_tlb_flush(void);
|
||||
void TCG_HELPER_PROTO helper_dump(uint32_t a0, uint32_t a1, uint32_t a2);
|
||||
void TCG_HELPER_PROTO helper_dummy(void);
|
||||
void TCG_HELPER_PROTO helper_rfe(void);
|
||||
void TCG_HELPER_PROTO helper_store(uint32_t a0);
|
||||
|
||||
void TCG_HELPER_PROTO helper_movl_sreg_reg (uint32_t sreg, uint32_t reg);
|
||||
void TCG_HELPER_PROTO helper_movl_reg_sreg (uint32_t reg, uint32_t sreg);
|
||||
|
||||
void TCG_HELPER_PROTO helper_evaluate_flags_muls(void);
|
||||
void TCG_HELPER_PROTO helper_evaluate_flags_mulu(void);
|
||||
void TCG_HELPER_PROTO helper_evaluate_flags_mcp(void);
|
||||
|
|
|
@ -265,7 +265,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
|
|||
}
|
||||
|
||||
/* Give us the vaddr corresponding to the latest TLB update. */
|
||||
target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo)
|
||||
target_ulong cris_mmu_tlb_latest_update(CPUState *env)
|
||||
{
|
||||
uint32_t sel = env->sregs[SFR_RW_MM_TLB_SEL];
|
||||
uint32_t vaddr;
|
||||
|
|
|
@ -11,7 +11,7 @@ struct cris_mmu_result_t
|
|||
int bf_vec;
|
||||
};
|
||||
|
||||
target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo);
|
||||
target_ulong cris_mmu_tlb_latest_update(CPUState *env);
|
||||
int cris_mmu_translate(struct cris_mmu_result_t *res,
|
||||
CPUState *env, uint32_t vaddr,
|
||||
int rw, int mmu_idx);
|
||||
|
|
|
@ -79,20 +79,10 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
|
|||
env = saved_env;
|
||||
}
|
||||
|
||||
void helper_tlb_update(uint32_t T0)
|
||||
void helper_raise_exception(uint32_t index)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
uint32_t vaddr;
|
||||
uint32_t srs = env->pregs[PR_SRS];
|
||||
|
||||
if (srs != 1 && srs != 2)
|
||||
return;
|
||||
|
||||
vaddr = cris_mmu_tlb_latest_update(env, T0);
|
||||
D(fprintf(logfile, "flush old_vaddr=%x vaddr=%x T0=%x\n", vaddr,
|
||||
env->sregs[SFR_R_MM_CAUSE] & TARGET_PAGE_MASK, T0));
|
||||
tlb_flush_page(env, vaddr);
|
||||
#endif
|
||||
env->exception_index = index;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
|
||||
void helper_tlb_flush(void)
|
||||
|
@ -110,13 +100,105 @@ void helper_dummy(void)
|
|||
|
||||
}
|
||||
|
||||
/* Only used for debugging at the moment. */
|
||||
void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
|
||||
{
|
||||
uint32_t srs;
|
||||
srs = env->pregs[PR_SRS];
|
||||
srs &= 3;
|
||||
env->sregs[srs][sreg] = env->regs[reg];
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (srs == 1 || srs == 2) {
|
||||
if (sreg == 6) {
|
||||
/* Writes to tlb-hi write to mm_cause as a side
|
||||
effect. */
|
||||
env->sregs[SFR_RW_MM_TLB_HI] = T0;
|
||||
env->sregs[SFR_R_MM_CAUSE] = T0;
|
||||
}
|
||||
else if (sreg == 5) {
|
||||
uint32_t set;
|
||||
uint32_t idx;
|
||||
uint32_t lo, hi;
|
||||
uint32_t vaddr;
|
||||
|
||||
vaddr = cris_mmu_tlb_latest_update(env);
|
||||
D(fprintf(logfile, "tlb flush vaddr=%x\n", vaddr));
|
||||
tlb_flush_page(env, vaddr);
|
||||
|
||||
idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
|
||||
set >>= 4;
|
||||
set &= 3;
|
||||
|
||||
idx &= 15;
|
||||
/* We've just made a write to tlb_lo. */
|
||||
lo = env->sregs[SFR_RW_MM_TLB_LO];
|
||||
/* Writes are done via r_mm_cause. */
|
||||
hi = env->sregs[SFR_R_MM_CAUSE];
|
||||
env->tlbsets[srs - 1][set][idx].lo = lo;
|
||||
env->tlbsets[srs - 1][set][idx].hi = hi;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
|
||||
{
|
||||
uint32_t srs;
|
||||
env->pregs[PR_SRS] &= 3;
|
||||
srs = env->pregs[PR_SRS];
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
env->regs[reg] = env->sregs[srs][sreg];
|
||||
RETURN();
|
||||
}
|
||||
|
||||
static void cris_ccs_rshift(CPUState *env)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void helper_rfe(void)
|
||||
{
|
||||
D(fprintf(logfile, "rfe: erp=%x pid=%x ccs=%x btarget=%x\n",
|
||||
env->pregs[PR_ERP], env->pregs[PR_PID],
|
||||
env->pregs[PR_CCS],
|
||||
env->btarget));
|
||||
|
||||
cris_ccs_rshift(env);
|
||||
|
||||
/* RFE sets the P_FLAG only if the R_FLAG is not set. */
|
||||
if (!(env->pregs[PR_CCS] & R_FLAG))
|
||||
env->pregs[PR_CCS] |= P_FLAG;
|
||||
}
|
||||
|
||||
void helper_store(uint32_t a0)
|
||||
|
@ -155,7 +237,6 @@ static void evaluate_flags_writeback(uint32_t flags)
|
|||
env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
|
||||
flags &= env->cc_mask;
|
||||
env->pregs[PR_CCS] |= flags;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void helper_evaluate_flags_muls(void)
|
||||
|
@ -164,8 +245,7 @@ void helper_evaluate_flags_muls(void)
|
|||
uint32_t dst;
|
||||
uint32_t res;
|
||||
uint32_t flags = 0;
|
||||
/* were gonna have to redo the muls. */
|
||||
int64_t tmp, t0 ,t1;
|
||||
int64_t tmp;
|
||||
int32_t mof;
|
||||
int dneg;
|
||||
|
||||
|
@ -173,14 +253,12 @@ void helper_evaluate_flags_muls(void)
|
|||
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;
|
||||
mof = env->pregs[PR_MOF];
|
||||
tmp = mof;
|
||||
tmp <<= 32;
|
||||
tmp |= res;
|
||||
if (tmp == 0)
|
||||
flags |= Z_FLAG;
|
||||
else if (tmp < 0)
|
||||
|
@ -197,21 +275,17 @@ void helper_evaluate_flags_mulu(void)
|
|||
uint32_t dst;
|
||||
uint32_t res;
|
||||
uint32_t flags = 0;
|
||||
/* were gonna have to redo the muls. */
|
||||
uint64_t tmp, t0 ,t1;
|
||||
uint64_t tmp;
|
||||
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;
|
||||
mof = env->pregs[PR_MOF];
|
||||
tmp = mof;
|
||||
tmp <<= 32;
|
||||
tmp |= res;
|
||||
if (tmp == 0)
|
||||
flags |= Z_FLAG;
|
||||
else if (tmp >> 63)
|
||||
|
|
|
@ -223,9 +223,9 @@ static inline void t_gen_mov_preg_TN(int r, TCGv tn)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void t_gen_mov_TN_im(TCGv tn, int32_t val)
|
||||
static inline void t_gen_raise_exception(uint32_t index)
|
||||
{
|
||||
tcg_gen_movi_tl(tn, val);
|
||||
tcg_gen_helper_0_1(helper_raise_exception, tcg_const_tl(index));
|
||||
}
|
||||
|
||||
static void t_gen_lsl(TCGv d, TCGv a, TCGv b)
|
||||
|
@ -375,6 +375,62 @@ static void t_gen_lz_i32(TCGv d, TCGv x)
|
|||
tcg_gen_discard_i32(n);
|
||||
}
|
||||
|
||||
static void t_gen_btst(TCGv d, TCGv s)
|
||||
{
|
||||
TCGv sbit;
|
||||
TCGv bset;
|
||||
int l1;
|
||||
|
||||
/* des ref:
|
||||
The N flag is set according to the selected bit in the dest reg.
|
||||
The Z flag is set if the selected bit and all bits to the right are
|
||||
zero.
|
||||
The X flag is cleared.
|
||||
Other flags are left untouched.
|
||||
The destination reg is not affected.
|
||||
|
||||
unsigned int fz, sbit, bset, mask, masked_t0;
|
||||
|
||||
sbit = T1 & 31;
|
||||
bset = !!(T0 & (1 << sbit));
|
||||
mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
|
||||
masked_t0 = T0 & mask;
|
||||
fz = !(masked_t0 | bset);
|
||||
|
||||
// Clear the X, N and Z flags.
|
||||
T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG);
|
||||
// Set the N and Z flags accordingly.
|
||||
T0 |= (bset << 3) | (fz << 2);
|
||||
*/
|
||||
|
||||
l1 = gen_new_label();
|
||||
sbit = tcg_temp_new(TCG_TYPE_TL);
|
||||
bset = tcg_temp_new(TCG_TYPE_TL);
|
||||
|
||||
/* Compute bset and sbit. */
|
||||
tcg_gen_andi_tl(sbit, s, 31);
|
||||
tcg_gen_shl_tl(s, tcg_const_tl(1), sbit);
|
||||
tcg_gen_and_tl(bset, d, s);
|
||||
tcg_gen_shr_tl(bset, bset, sbit);
|
||||
/* Displace to N_FLAG. */
|
||||
tcg_gen_shli_tl(bset, bset, 3);
|
||||
|
||||
tcg_gen_shl_tl(sbit, tcg_const_tl(2), sbit);
|
||||
tcg_gen_subi_tl(sbit, sbit, 1);
|
||||
tcg_gen_and_tl(sbit, d, sbit);
|
||||
|
||||
tcg_gen_andi_tl(d, cpu_PR[PR_CCS], ~(X_FLAG | N_FLAG | Z_FLAG));
|
||||
/* or in the N_FLAG. */
|
||||
tcg_gen_or_tl(d, d, bset);
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, sbit, tcg_const_tl(0), l1);
|
||||
/* or in the Z_FLAG. */
|
||||
tcg_gen_ori_tl(d, d, Z_FLAG);
|
||||
gen_set_label(l1);
|
||||
|
||||
tcg_gen_discard_tl(sbit);
|
||||
tcg_gen_discard_tl(bset);
|
||||
}
|
||||
|
||||
static void t_gen_cris_dstep(TCGv d, TCGv s)
|
||||
{
|
||||
int l1;
|
||||
|
@ -738,7 +794,7 @@ static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
|
|||
t_gen_lz_i32(cpu_T[0], cpu_T[1]);
|
||||
break;
|
||||
case CC_OP_BTST:
|
||||
gen_op_btst_T0_T1();
|
||||
t_gen_btst(cpu_T[0], cpu_T[1]);
|
||||
writeback = 0;
|
||||
break;
|
||||
case CC_OP_MULS:
|
||||
|
@ -846,83 +902,172 @@ static void gen_tst_cc (DisasContext *dc, int cond)
|
|||
int arith_opt;
|
||||
|
||||
/* TODO: optimize more condition codes. */
|
||||
|
||||
/*
|
||||
* If the flags are live, we've gotta look into the bits of CCS.
|
||||
* Otherwise, if we just did an arithmetic operation we try to
|
||||
* evaluate the condition code faster.
|
||||
*
|
||||
* When this function is done, T0 should be non-zero if the condition
|
||||
* code is true.
|
||||
*/
|
||||
arith_opt = arith_cc(dc) && !dc->flags_live;
|
||||
switch (cond) {
|
||||
case CC_EQ:
|
||||
if (arith_opt)
|
||||
gen_op_tst_cc_eq_fast ();
|
||||
if (arith_opt) {
|
||||
/* If cc_result is zero, T0 should be
|
||||
non-zero otherwise T0 should be zero. */
|
||||
int l1;
|
||||
l1 = gen_new_label();
|
||||
tcg_gen_movi_tl(cpu_T[0], 0);
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, cc_result,
|
||||
tcg_const_tl(0), l1);
|
||||
tcg_gen_movi_tl(cpu_T[0], 1);
|
||||
gen_set_label(l1);
|
||||
}
|
||||
else {
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_eq ();
|
||||
tcg_gen_andi_tl(cpu_T[0],
|
||||
cpu_PR[PR_CCS], Z_FLAG);
|
||||
}
|
||||
break;
|
||||
case CC_NE:
|
||||
if (arith_opt)
|
||||
gen_op_tst_cc_ne_fast ();
|
||||
tcg_gen_mov_tl(cpu_T[0], cc_result);
|
||||
else {
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_ne ();
|
||||
tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS],
|
||||
Z_FLAG);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG);
|
||||
}
|
||||
break;
|
||||
case CC_CS:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_cs ();
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG);
|
||||
break;
|
||||
case CC_CC:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_cc ();
|
||||
tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS],
|
||||
C_FLAG);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], C_FLAG);
|
||||
break;
|
||||
case CC_VS:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_vs ();
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], V_FLAG);
|
||||
break;
|
||||
case CC_VC:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_vc ();
|
||||
tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS],
|
||||
V_FLAG);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG);
|
||||
break;
|
||||
case CC_PL:
|
||||
if (arith_opt)
|
||||
gen_op_tst_cc_pl_fast ();
|
||||
tcg_gen_shli_tl(cpu_T[0], cc_result, 31);
|
||||
else {
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_pl ();
|
||||
tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS],
|
||||
N_FLAG);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG);
|
||||
}
|
||||
break;
|
||||
case CC_MI:
|
||||
if (arith_opt)
|
||||
gen_op_tst_cc_mi_fast ();
|
||||
if (arith_opt) {
|
||||
tcg_gen_shli_tl(cpu_T[0], cc_result, 31);
|
||||
tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1);
|
||||
}
|
||||
else {
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_mi ();
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS],
|
||||
N_FLAG);
|
||||
}
|
||||
break;
|
||||
case CC_LS:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_ls ();
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS],
|
||||
C_FLAG | Z_FLAG);
|
||||
break;
|
||||
case CC_HI:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_hi ();
|
||||
{
|
||||
TCGv tmp;
|
||||
|
||||
tmp = tcg_temp_new(TCG_TYPE_TL);
|
||||
tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS],
|
||||
C_FLAG | Z_FLAG);
|
||||
/* Overlay the C flag on top of the Z. */
|
||||
tcg_gen_shli_tl(cpu_T[0], tmp, 2);
|
||||
tcg_gen_and_tl(cpu_T[0], tmp, cpu_T[0]);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG);
|
||||
|
||||
tcg_gen_discard_tl(tmp);
|
||||
}
|
||||
break;
|
||||
case CC_GE:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_ge ();
|
||||
/* Overlay the V flag on top of the N. */
|
||||
tcg_gen_shli_tl(cpu_T[0], cpu_PR[PR_CCS], 2);
|
||||
tcg_gen_xor_tl(cpu_T[0],
|
||||
cpu_PR[PR_CCS], cpu_T[0]);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG);
|
||||
tcg_gen_xori_tl(cpu_T[0], cpu_T[0], N_FLAG);
|
||||
break;
|
||||
case CC_LT:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_lt ();
|
||||
/* Overlay the V flag on top of the N. */
|
||||
tcg_gen_shli_tl(cpu_T[0], cpu_PR[PR_CCS], 2);
|
||||
tcg_gen_xor_tl(cpu_T[0],
|
||||
cpu_PR[PR_CCS], cpu_T[0]);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG);
|
||||
break;
|
||||
case CC_GT:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_gt ();
|
||||
{
|
||||
TCGv n, z;
|
||||
|
||||
n = tcg_temp_new(TCG_TYPE_TL);
|
||||
z = tcg_temp_new(TCG_TYPE_TL);
|
||||
|
||||
/* To avoid a shift we overlay everything on
|
||||
the V flag. */
|
||||
tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
|
||||
tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
|
||||
/* invert Z. */
|
||||
tcg_gen_xori_tl(z, z, 2);
|
||||
|
||||
tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
|
||||
tcg_gen_xori_tl(n, n, 2);
|
||||
tcg_gen_and_tl(cpu_T[0], z, n);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2);
|
||||
|
||||
tcg_gen_discard_tl(n);
|
||||
tcg_gen_discard_tl(z);
|
||||
}
|
||||
break;
|
||||
case CC_LE:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_le ();
|
||||
{
|
||||
TCGv n, z;
|
||||
|
||||
n = tcg_temp_new(TCG_TYPE_TL);
|
||||
z = tcg_temp_new(TCG_TYPE_TL);
|
||||
|
||||
/* To avoid a shift we overlay everything on
|
||||
the V flag. */
|
||||
tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
|
||||
tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
|
||||
|
||||
tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
|
||||
tcg_gen_or_tl(cpu_T[0], z, n);
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2);
|
||||
|
||||
tcg_gen_discard_tl(n);
|
||||
tcg_gen_discard_tl(z);
|
||||
}
|
||||
break;
|
||||
case CC_P:
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_tst_cc_p ();
|
||||
tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], P_FLAG);
|
||||
break;
|
||||
case CC_A:
|
||||
cris_evaluate_flags(dc);
|
||||
|
@ -944,7 +1089,7 @@ static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
|
|||
if (cond != CC_A)
|
||||
{
|
||||
gen_tst_cc (dc, cond);
|
||||
gen_op_evaluate_bcc ();
|
||||
t_gen_mov_env_TN(btaken, cpu_T[0]);
|
||||
}
|
||||
tcg_gen_movi_tl(env_btarget, dc->delayed_pc);
|
||||
}
|
||||
|
@ -1225,7 +1370,7 @@ static unsigned int dec_subq(DisasContext *dc)
|
|||
cris_cc_mask(dc, CC_MASK_NZVC);
|
||||
/* Fetch register operand, */
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], dc->op1);
|
||||
tcg_gen_movi_tl(cpu_T[1], dc->op1);
|
||||
crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1238,7 +1383,7 @@ static unsigned int dec_cmpq(DisasContext *dc)
|
|||
DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
|
||||
cris_cc_mask(dc, CC_MASK_NZVC);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], imm);
|
||||
tcg_gen_movi_tl(cpu_T[1], imm);
|
||||
crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1251,7 +1396,7 @@ static unsigned int dec_andq(DisasContext *dc)
|
|||
DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], imm);
|
||||
tcg_gen_movi_tl(cpu_T[1], imm);
|
||||
crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1263,7 +1408,7 @@ static unsigned int dec_orq(DisasContext *dc)
|
|||
DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], imm);
|
||||
tcg_gen_movi_tl(cpu_T[1], imm);
|
||||
crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1272,10 +1417,9 @@ static unsigned int dec_btstq(DisasContext *dc)
|
|||
dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
|
||||
DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
|
||||
|
||||
cris_evaluate_flags(dc);
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], dc->op1);
|
||||
tcg_gen_movi_tl(cpu_T[1], dc->op1);
|
||||
crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
|
||||
|
||||
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
||||
|
@ -1289,7 +1433,7 @@ static unsigned int dec_asrq(DisasContext *dc)
|
|||
DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], dc->op1);
|
||||
tcg_gen_movi_tl(cpu_T[1], dc->op1);
|
||||
crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1300,7 +1444,7 @@ static unsigned int dec_lslq(DisasContext *dc)
|
|||
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], dc->op1);
|
||||
tcg_gen_movi_tl(cpu_T[1], dc->op1);
|
||||
crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1311,7 +1455,7 @@ static unsigned int dec_lsrq(DisasContext *dc)
|
|||
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op2);
|
||||
t_gen_mov_TN_im(cpu_T[1], dc->op1);
|
||||
tcg_gen_movi_tl(cpu_T[1], dc->op1);
|
||||
crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
|
||||
return 2;
|
||||
}
|
||||
|
@ -1338,14 +1482,20 @@ static unsigned int dec_scc_r(DisasContext *dc)
|
|||
|
||||
if (cond != CC_A)
|
||||
{
|
||||
int l1;
|
||||
|
||||
gen_tst_cc (dc, cond);
|
||||
tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
|
||||
|
||||
l1 = gen_new_label();
|
||||
tcg_gen_movi_tl(cpu_R[dc->op1], 0);
|
||||
tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[0], tcg_const_tl(0), l1);
|
||||
tcg_gen_movi_tl(cpu_R[dc->op1], 1);
|
||||
gen_set_label(l1);
|
||||
}
|
||||
else
|
||||
tcg_gen_movi_tl(cpu_T[1], 1);
|
||||
tcg_gen_movi_tl(cpu_R[dc->op1], 1);
|
||||
|
||||
cris_cc_mask(dc, 0);
|
||||
crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -1624,7 +1774,6 @@ static unsigned int dec_btst_r(DisasContext *dc)
|
|||
{
|
||||
DIS(fprintf (logfile, "btst $r%u, $r%u\n",
|
||||
dc->op1, dc->op2));
|
||||
cris_evaluate_flags(dc);
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
|
||||
crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
|
||||
|
@ -1772,10 +1921,18 @@ static unsigned int dec_setclrf(DisasContext *dc)
|
|||
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
||||
tcg_gen_movi_tl(cc_op, dc->cc_op);
|
||||
|
||||
if (set)
|
||||
gen_op_setf(flags);
|
||||
if (set) {
|
||||
if (!dc->user && (flags & U_FLAG)) {
|
||||
/* Enter user mode. */
|
||||
t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
|
||||
tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
}
|
||||
tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
|
||||
}
|
||||
else
|
||||
gen_op_clrf(flags);
|
||||
tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
|
||||
|
||||
dc->flags_live = 1;
|
||||
dc->clear_x = 0;
|
||||
return 2;
|
||||
|
@ -1785,28 +1942,19 @@ static unsigned int dec_move_rs(DisasContext *dc)
|
|||
{
|
||||
DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
|
||||
cris_cc_mask(dc, 0);
|
||||
t_gen_mov_TN_reg(cpu_T[0], dc->op1);
|
||||
gen_op_movl_sreg_T0(dc->op2);
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (dc->op2 == 6)
|
||||
gen_op_movl_tlb_hi_T0();
|
||||
else if (dc->op2 == 5) { /* srs is checked at runtime. */
|
||||
tcg_gen_helper_0_1(helper_tlb_update, cpu_T[0]);
|
||||
gen_op_movl_tlb_lo_T0();
|
||||
}
|
||||
#endif
|
||||
tcg_gen_helper_0_2(helper_movl_sreg_reg,
|
||||
tcg_const_tl(dc->op2), tcg_const_tl(dc->op1));
|
||||
return 2;
|
||||
}
|
||||
static unsigned int dec_move_sr(DisasContext *dc)
|
||||
{
|
||||
DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op2, dc->op1));
|
||||
cris_cc_mask(dc, 0);
|
||||
gen_op_movl_T0_sreg(dc->op2);
|
||||
tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
|
||||
crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
|
||||
tcg_gen_helper_0_2(helper_movl_reg_sreg,
|
||||
tcg_const_tl(dc->op1), tcg_const_tl(dc->op2));
|
||||
return 2;
|
||||
}
|
||||
|
||||
static unsigned int dec_move_rp(DisasContext *dc)
|
||||
{
|
||||
DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
|
||||
|
@ -2024,9 +2172,11 @@ static unsigned int dec_test_m(DisasContext *dc)
|
|||
dc->op1, dc->postinc ? "+]" : "]",
|
||||
dc->op2));
|
||||
|
||||
cris_evaluate_flags(dc);
|
||||
|
||||
insn_len = dec_prep_alu_m(dc, 0, memsize);
|
||||
cris_cc_mask(dc, CC_MASK_NZ);
|
||||
gen_op_clrf(3);
|
||||
tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
|
||||
|
||||
tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
|
||||
tcg_gen_movi_tl(cpu_T[1], 0);
|
||||
|
@ -2444,10 +2594,6 @@ static unsigned int dec_rfe_etc(DisasContext *dc)
|
|||
case 2:
|
||||
/* rfe. */
|
||||
cris_evaluate_flags(dc);
|
||||
gen_op_ccs_rshift();
|
||||
/* FIXME: don't set the P-FLAG if R is set. */
|
||||
tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], P_FLAG);
|
||||
/* Debug helper. */
|
||||
tcg_gen_helper_0_0(helper_rfe);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
break;
|
||||
|
@ -2460,7 +2606,9 @@ static unsigned int dec_rfe_etc(DisasContext *dc)
|
|||
tcg_gen_movi_tl(cpu_T[0], dc->pc);
|
||||
t_gen_mov_env_TN(pc, cpu_T[0]);
|
||||
/* Breaks start at 16 in the exception vector. */
|
||||
gen_op_break_im(dc->op1 + 16);
|
||||
t_gen_mov_env_TN(trap_vector,
|
||||
tcg_const_tl(dc->op1 + 16));
|
||||
t_gen_raise_exception(EXCP_BREAK);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
break;
|
||||
default:
|
||||
|
@ -2642,7 +2790,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
|
|||
cris_evaluate_flags (dc);
|
||||
tcg_gen_movi_tl(cpu_T[0], dc->pc);
|
||||
t_gen_mov_env_TN(pc, cpu_T[0]);
|
||||
gen_op_debug();
|
||||
t_gen_raise_exception(EXCP_DEBUG);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
}
|
||||
}
|
||||
|
@ -2689,13 +2837,14 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
|||
|
||||
if (loglevel & CPU_LOG_TB_IN_ASM) {
|
||||
fprintf(logfile,
|
||||
"search=%d pc=%x ccs=%x pid=%x usp=%x\n"
|
||||
"search=%d pc=%x ccs=%x pid=%x usp=%x dbg=%x %x %x\n"
|
||||
"%x.%x.%x.%x\n"
|
||||
"%x.%x.%x.%x\n"
|
||||
"%x.%x.%x.%x\n"
|
||||
"%x.%x.%x.%x\n",
|
||||
search_pc, env->pc, env->pregs[PR_CCS],
|
||||
env->pregs[PR_PID], env->pregs[PR_USP],
|
||||
env->debug1, env->debug2, env->debug3,
|
||||
env->regs[0], env->regs[1], env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5], env->regs[6], env->regs[7],
|
||||
env->regs[8], env->regs[9],
|
||||
|
@ -2733,7 +2882,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
|||
|
||||
dc->clear_x = 1;
|
||||
insn_len = cris_decoder(dc);
|
||||
STATS(gen_op_exec_insn());
|
||||
dc->ppc = dc->pc;
|
||||
dc->pc += insn_len;
|
||||
if (dc->clear_x)
|
||||
|
@ -2778,7 +2926,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
|||
cris_evaluate_flags (dc);
|
||||
done:
|
||||
if (__builtin_expect(env->singlestep_enabled, 0)) {
|
||||
gen_op_debug();
|
||||
t_gen_raise_exception(EXCP_DEBUG);
|
||||
} else {
|
||||
switch(dc->is_jmp) {
|
||||
case DISAS_NEXT:
|
||||
|
@ -2933,13 +3081,16 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
|
|||
pregnames[i]);
|
||||
}
|
||||
|
||||
TCG_HELPER(helper_tlb_update);
|
||||
TCG_HELPER(helper_tlb_flush);
|
||||
TCG_HELPER(helper_rfe);
|
||||
TCG_HELPER(helper_raise_exception);
|
||||
TCG_HELPER(helper_store);
|
||||
TCG_HELPER(helper_dump);
|
||||
TCG_HELPER(helper_dummy);
|
||||
|
||||
TCG_HELPER(helper_tlb_flush);
|
||||
TCG_HELPER(helper_movl_sreg_reg);
|
||||
TCG_HELPER(helper_movl_reg_sreg);
|
||||
TCG_HELPER(helper_rfe);
|
||||
|
||||
TCG_HELPER(helper_evaluate_flags_muls);
|
||||
TCG_HELPER(helper_evaluate_flags_mulu);
|
||||
TCG_HELPER(helper_evaluate_flags_mcp);
|
||||
|
|
Loading…
Reference in New Issue