qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [4684] CRIS translator updates
Date: Fri, 06 Jun 2008 11:23:29 +0000	[thread overview]
Message-ID: <E1K4a2b-0007YF-6x@cvs.savannah.gnu.org> (raw)

Revision: 4684
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4684
Author:   edgar_igl
Date:     2008-06-06 11:23:28 +0000 (Fri, 06 Jun 2008)

Log Message:
-----------
CRIS translator updates
* Improve translation of the X flag (still some corner cases missing).
* First shot att P flag support and conditional stores.
* Improve the jump logic.

Modified Paths:
--------------
    trunk/target-cris/translate.c

Modified: trunk/target-cris/translate.c
===================================================================
--- trunk/target-cris/translate.c	2008-06-06 11:17:17 UTC (rev 4683)
+++ trunk/target-cris/translate.c	2008-06-06 11:23:28 UTC (rev 4684)
@@ -73,6 +73,7 @@
 TCGv cc_size;
 TCGv cc_mask;
 
+TCGv env_btaken;
 TCGv env_btarget;
 TCGv env_pc;
 
@@ -104,9 +105,16 @@
 	int flags_x;
 
 	int clear_x; /* Clear x after this insn?  */
-	int user; /* user or kernel mode.  */
+	int cpustate_changed;
+	unsigned int tb_flags; /* tb dependent flags.  */
 	int is_jmp;
 
+#define JMP_NOJMP    0
+#define JMP_DIRECT   1
+#define JMP_INDIRECT 2
+	int jmp; /* 0=nojmp, 1=direct, 2=indirect.  */ 
+	uint32_t jmp_pc;
+
 	int delayed_branch;
 
 	struct TranslationBlock *tb;
@@ -207,8 +215,10 @@
 		tcg_gen_andi_tl(cpu_PR[r], tn, 3);
 	else {
 		tcg_gen_mov_tl(cpu_PR[r], tn);
-		if (r == PR_PID)
+		if (r == PR_PID) 
 			tcg_gen_helper_0_1(helper_tlb_flush_pid, tn);
+		else if (r == PR_CCS)
+			dc->cpustate_changed = 1;
 	}
 }
 
@@ -610,7 +620,7 @@
 	btaken = tcg_temp_new(TCG_TYPE_TL);
 
 	/* Conditional jmp.  */
-	t_gen_mov_TN_env(btaken, btaken);
+	tcg_gen_mov_tl(btaken, env_btaken);
 	tcg_gen_mov_tl(env_pc, pc_false);
 	tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1);
 	tcg_gen_mov_tl(env_pc, pc_true);
@@ -628,7 +638,7 @@
 		tcg_gen_movi_tl(env_pc, dest);
 		tcg_gen_exit_tb((long)tb + n);
 	} else {
-		tcg_gen_mov_tl(env_pc, cpu_T[0]);
+		tcg_gen_movi_tl(env_pc, dest);
 		tcg_gen_exit_tb(0);
 	}
 }
@@ -648,6 +658,9 @@
 
 static inline void cris_clear_x_flag(DisasContext *dc)
 {
+	if (dc->flagx_known && dc->flags_x)
+		dc->flags_uptodate = 0;
+
 	dc->flagx_known = 1;
 	dc->flags_x = 0;
 }
@@ -715,6 +728,15 @@
 			}
 			break;
 		}
+		if (dc->flagx_known) {
+			if (dc->flags_x)
+				tcg_gen_ori_tl(cpu_PR[PR_CCS], 
+					       cpu_PR[PR_CCS], X_FLAG);
+			else
+				tcg_gen_andi_tl(cpu_PR[PR_CCS], 
+						cpu_PR[PR_CCS], ~X_FLAG);
+        }
+
 		dc->flags_uptodate = 1;
 	}
 }
@@ -723,6 +745,11 @@
 {
 	uint32_t ovl;
 
+	if (!mask) {
+		dc->update_cc = 0;
+		return;
+	}	
+
 	/* Check if we need to evaluate the condition codes due to 
 	   CC overlaying.  */
 	ovl = (dc->cc_mask ^ mask) & ~mask;
@@ -732,11 +759,6 @@
 	}
 	dc->cc_mask = mask;
 	dc->update_cc = 1;
-
-	if (mask == 0)
-		dc->update_cc = 0;
-	else
-		dc->flags_uptodate = 0;
 }
 
 static void cris_update_cc_op(DisasContext *dc, int op, int size)
@@ -942,7 +964,7 @@
 
 static void gen_tst_cc (DisasContext *dc, int cond)
 {
-	int arith_opt;
+	int arith_opt, move_opt;
 
 	/* TODO: optimize more condition codes.  */
 
@@ -955,9 +977,10 @@
 	 * code is true.
 	 */
 	arith_opt = arith_cc(dc) && !dc->flags_uptodate;
+	move_opt = (dc->cc_op == CC_OP_MOVE) && !dc->flags_uptodate;
 	switch (cond) {
 		case CC_EQ:
-			if (arith_opt) {
+			if (arith_opt || move_opt) {
 				/* If cc_result is zero, T0 should be 
 				   non-zero otherwise T0 should be zero.  */
 				int l1;
@@ -975,7 +998,7 @@
 			}
 			break;
 		case CC_NE:
-			if (arith_opt)
+			if (arith_opt || move_opt)
 				tcg_gen_mov_tl(cpu_T[0], cc_result);
 			else {
 				cris_evaluate_flags(dc);
@@ -990,8 +1013,7 @@
 			break;
 		case CC_CC:
 			cris_evaluate_flags(dc);
-			tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS],
-					C_FLAG);
+			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:
@@ -1005,9 +1027,17 @@
 			tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG);
 			break;
 		case CC_PL:
-			if (arith_opt)
-				tcg_gen_shli_tl(cpu_T[0], cc_result, 31);
-			else {
+			if (arith_opt || move_opt) {
+				int bits = 31;
+
+				if (dc->cc_size == 1)
+					bits = 7;
+				else if (dc->cc_size == 2)
+					bits = 15;	
+
+				tcg_gen_shri_tl(cpu_T[0], cc_result, bits);
+				tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1);
+			} else {
 				cris_evaluate_flags(dc);
 				tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS],
 						N_FLAG);
@@ -1015,9 +1045,15 @@
 			}
 			break;
 		case CC_MI:
-			if (arith_opt) {
-				tcg_gen_shli_tl(cpu_T[0], cc_result, 31);
-				tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1);
+			if (arith_opt || move_opt) {
+				int bits = 31;
+
+				if (dc->cc_size == 1)
+					bits = 7;
+				else if (dc->cc_size == 2)
+					bits = 15;	
+
+				tcg_gen_shri_tl(cpu_T[0], cc_result, 31);
 			}
 			else {
 				cris_evaluate_flags(dc);
@@ -1121,28 +1157,46 @@
 	};
 }
 
-static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
+static void cris_store_direct_jmp(DisasContext *dc)
 {
+	/* Store the direct jmp state into the cpu-state.  */
+	if (dc->jmp == JMP_DIRECT) {
+		tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
+		tcg_gen_movi_tl(env_btaken, 1);
+	}
+}
+
+static void cris_prepare_cc_branch (DisasContext *dc, 
+				    int offset, int cond)
+{
 	/* This helps us re-schedule the micro-code to insns in delay-slots
 	   before the actual jump.  */
 	dc->delayed_branch = 2;
+	dc->jmp_pc = dc->pc + offset;
+
 	if (cond != CC_A)
 	{
+		dc->jmp = JMP_INDIRECT;
 		gen_tst_cc (dc, cond);
-		t_gen_mov_env_TN(btaken, cpu_T[0]);
-	} else
-		t_gen_mov_env_TN(btaken, tcg_const_tl(1));
-	tcg_gen_movi_tl(env_btarget, dc->pc + offset);
+		tcg_gen_mov_tl(env_btaken, cpu_T[0]);
+		tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
+	} else {
+		/* Allow chaining.  */
+		dc->jmp = JMP_DIRECT;
+	}
 }
 
 
-/* Dynamic jumps, when the dest is in a live reg for example.  */
-void cris_prepare_dyn_jmp (DisasContext *dc)
+/* jumps, when the dest is in a live reg for example. Direct should be set
+   when the dest addr is constant to allow tb chaining.  */
+static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
 {
 	/* This helps us re-schedule the micro-code to insns in delay-slots
 	   before the actual jump.  */
 	dc->delayed_branch = 2;
-	t_gen_mov_env_TN(btaken, tcg_const_tl(1));
+	dc->jmp = type;
+	if (type == JMP_INDIRECT)
+		tcg_gen_movi_tl(env_btaken, 1);
 }
 
 void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
@@ -1150,6 +1204,11 @@
 {
 	int mem_index = cpu_mmu_index(dc->env);
 
+	/* If we get a fault on a delayslot we must keep the jmp state in
+	   the cpu-state to be able to re-execute the jmp.  */
+	if (dc->delayed_branch == 1)
+		cris_store_direct_jmp(dc);
+
 	if (size == 1) {
 		if (sign)
 			tcg_gen_qemu_ld8s(dst, addr, mem_index);
@@ -1172,6 +1231,21 @@
 {
 	int mem_index = cpu_mmu_index(dc->env);
 
+	/* If we get a fault on a delayslot we must keep the jmp state in
+	   the cpu-state to be able to re-execute the jmp.  */
+	if (dc->delayed_branch == 1)
+ 		cris_store_direct_jmp(dc);
+
+
+	/* Conditional writes. We only support the kind were X and P are known
+	   at translation time.  */
+	if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
+		dc->postinc = 0;
+		cris_evaluate_flags(dc);
+		tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
+		return;
+	}
+
 	/* Remember, operands are flipped. CRIS has reversed order.  */
 	if (size == 1)
 		tcg_gen_qemu_st8(val, addr, mem_index);
@@ -1179,6 +1253,11 @@
 		tcg_gen_qemu_st16(val, addr, mem_index);
 	else
 		tcg_gen_qemu_st32(val, addr, mem_index);
+
+	if (dc->flagx_known && dc->flags_x) {
+		cris_evaluate_flags(dc);
+		tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
+	}
 }
 
 static inline void t_gen_sext(TCGv d, TCGv s, int size)
@@ -1352,6 +1431,8 @@
 	tmp = offset;
 	offset = sign_extend(offset, 8);
 
+	DIS(fprintf (logfile, "b%s %x\n", cc_name(cond), dc->pc + offset));
+
 	/* op2 holds the condition-code.  */
 	cris_cc_mask(dc, 0);
 	cris_prepare_cc_branch (dc, offset, cond);
@@ -1463,9 +1544,10 @@
 	DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
 	cris_cc_mask(dc, CC_MASK_NZ);
 
-	cris_alu(dc, CC_OP_ASR,
+	tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
+	cris_alu(dc, CC_OP_MOVE,
 		    cpu_R[dc->op2],
-		    cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
+		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
 	return 2;
 }
 static unsigned int dec_lslq(DisasContext *dc)
@@ -1475,9 +1557,11 @@
 
 	cris_cc_mask(dc, CC_MASK_NZ);
 
-	cris_alu(dc, CC_OP_LSL,
+	tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
+
+	cris_alu(dc, CC_OP_MOVE,
 		    cpu_R[dc->op2],
-		    cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
+		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
 	return 2;
 }
 static unsigned int dec_lsrq(DisasContext *dc)
@@ -1487,9 +1571,10 @@
 
 	cris_cc_mask(dc, CC_MASK_NZ);
 
-	cris_alu(dc, CC_OP_LSR,
+	tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
+	cris_alu(dc, CC_OP_MOVE,
 		    cpu_R[dc->op2],
-		    cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
+		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
 	return 2;
 }
 
@@ -1962,7 +2047,6 @@
 
 	flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
 		| EXTRACT_FIELD(dc->ir, 0, 3);
-	DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
 	if (set && flags == 0) {
 		DIS(fprintf (logfile, "nop\n"));
 		return 2;
@@ -1975,13 +2059,30 @@
 			    flags));
 	}
 
-	if (set && (flags & X_FLAG)) {
+    /* User space is not allowed to touch these. Silently ignore.  */
+	if (dc->tb_flags & U_FLAG) {
+		flags &= ~(I_FLAG | U_FLAG);
+	}
+
+	if (flags & X_FLAG) {
 		dc->flagx_known = 1;
-		dc->flags_x = X_FLAG;
-	} else {
-		dc->flagx_known = 0;
+		if (set)
+			dc->flags_x = X_FLAG;
+		else
+			dc->flags_x = 0;
 	}
 
+	/* Break the TB if the P flag changes.  */
+	if (flags & P_FLAG) {
+		if ((set && !(dc->tb_flags & P_FLAG))
+		    || (!set && (dc->tb_flags & P_FLAG))) {
+			tcg_gen_movi_tl(env_pc, dc->pc + 2);
+			dc->is_jmp = DISAS_UPDATE;
+			dc->cpustate_changed = 1;
+		}
+	}
+
+
 	/* Simply decode the flags.  */
 	cris_evaluate_flags (dc);
 	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
@@ -1989,11 +2090,11 @@
 	tcg_gen_movi_tl(cc_op, dc->cc_op);
 
 	if (set) {
-		if (!dc->user && (flags & U_FLAG)) {
+		if (!(dc->tb_flags & U_FLAG) && (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_NEXT;
+			dc->cpustate_changed = 1;
 		}
 		tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
 	}
@@ -2030,7 +2131,7 @@
 	if (dc->op2 == PR_CCS) {
 		cris_evaluate_flags(dc);
 		t_gen_mov_TN_reg(cpu_T[0], dc->op1);
-		if (dc->user) {
+		if (dc->tb_flags & U_FLAG) {
 			/* User space is not allowed to touch all flags.  */
 			tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x39f);
 			tcg_gen_andi_tl(cpu_T[1], cpu_PR[PR_CCS], ~0x39f);
@@ -2051,16 +2152,12 @@
 {
 	DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
 	cris_cc_mask(dc, 0);
-	/* Support register 0 is hardwired to zero. 
-	   Treat it specially. */
-	if (dc->op2 == 0)
-		tcg_gen_movi_tl(cpu_T[1], 0);
-	else if (dc->op2 == PR_CCS) {
+
+	if (dc->op2 == PR_CCS)
 		cris_evaluate_flags(dc);
-		t_gen_mov_TN_preg(cpu_T[1], dc->op2);
-	} else
-		t_gen_mov_TN_preg(cpu_T[1], dc->op2);
-	cris_alu(dc, CC_OP_MOVE, 
+
+	t_gen_mov_TN_preg(cpu_T[1], dc->op2);
+	cris_alu(dc, CC_OP_MOVE,
 		    cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[1],
 		    preg_sizes[dc->op2]);
 	return 2;
@@ -2410,7 +2507,7 @@
 	cris_cc_mask(dc, 0);
 	if (dc->op2 == PR_CCS) {
 		cris_evaluate_flags(dc);
-		if (dc->user) {
+		if (dc->tb_flags & U_FLAG) {
 			/* User space is not allowed to touch all flags.  */
 			tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 0x39f);
 			tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], ~0x39f);
@@ -2561,7 +2658,7 @@
 	/* rete will often have low bit set to indicate delayslot.  */
 	tcg_gen_andi_tl(env_btarget, cpu_T[0], ~1);
 	cris_cc_mask(dc, 0);
-	cris_prepare_dyn_jmp(dc);
+	cris_prepare_jmp(dc, JMP_INDIRECT);
 	return 2;
 }
 
@@ -2576,7 +2673,7 @@
 		abort();
 	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
 
-	cris_prepare_dyn_jmp(dc);
+	cris_prepare_jmp(dc, JMP_INDIRECT);
 	return 2;
 }
 
@@ -2589,9 +2686,10 @@
 	DIS(fprintf (logfile, "jas 0x%x\n", imm));
 	cris_cc_mask(dc, 0);
 	/* Store the return address in Pd.  */
-	tcg_gen_movi_tl(env_btarget, imm);
 	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
-	cris_prepare_dyn_jmp(dc);
+
+	dc->jmp_pc = imm;
+	cris_prepare_jmp(dc, JMP_DIRECT);
 	return 6;
 }
 
@@ -2604,11 +2702,10 @@
 	DIS(fprintf (logfile, "jasc 0x%x\n", imm));
 	cris_cc_mask(dc, 0);
 	/* Store the return address in Pd.  */
-	tcg_gen_movi_tl(cpu_T[0], imm);
-	tcg_gen_mov_tl(env_btarget, cpu_T[0]);
-	tcg_gen_movi_tl(cpu_T[0], dc->pc + 8 + 4);
-	t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]);
-	cris_prepare_dyn_jmp(dc);
+	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
+
+	dc->jmp_pc = imm;
+	cris_prepare_jmp(dc, JMP_DIRECT);
 	return 6;
 }
 
@@ -2617,11 +2714,9 @@
 	DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
 	cris_cc_mask(dc, 0);
 	/* Store the return address in Pd.  */
-	t_gen_mov_TN_reg(cpu_T[0], dc->op1);
-	tcg_gen_mov_tl(env_btarget, cpu_T[0]);
-	tcg_gen_movi_tl(cpu_T[0], dc->pc + 4 + 4);
-	t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]);
-	cris_prepare_dyn_jmp(dc);
+	tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
+	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
+	cris_prepare_jmp(dc, JMP_INDIRECT);
 	return 2;
 }
 
@@ -2651,12 +2746,11 @@
 
 	DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
 	cris_cc_mask(dc, 0);
-	/* Stor the return address in Pd.  */
-	tcg_gen_movi_tl(cpu_T[0], dc->pc + simm);
-	tcg_gen_mov_tl(env_btarget, cpu_T[0]);
-	tcg_gen_movi_tl(cpu_T[0], dc->pc + 8);
-	t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]);
-	cris_prepare_dyn_jmp(dc);
+	/* Store the return address in Pd.  */
+	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
+
+	dc->jmp_pc = dc->pc + simm;
+	cris_prepare_jmp(dc, JMP_DIRECT);
 	return 6;
 }
 
@@ -2667,12 +2761,11 @@
 
 	DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
 	cris_cc_mask(dc, 0);
-	/* Stor the return address in Pd.  */
-	tcg_gen_movi_tl(cpu_T[0], dc->pc + simm);
-	tcg_gen_mov_tl(env_btarget, cpu_T[0]);
-	tcg_gen_movi_tl(cpu_T[0], dc->pc + 12);
-	t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]);
-	cris_prepare_dyn_jmp(dc);
+	/* Store the return address in Pd.  */
+	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
+
+	dc->jmp_pc = dc->pc + simm;
+	cris_prepare_jmp(dc, JMP_DIRECT);
 	return 6;
 }
 
@@ -2699,8 +2792,7 @@
 			break;
 		case 6:
 			/* break.  */
-			tcg_gen_movi_tl(cpu_T[0], dc->pc);
-			t_gen_mov_env_TN(pc, cpu_T[0]);
+			tcg_gen_movi_tl(env_pc, dc->pc);
 			/* Breaks start at 16 in the exception vector.  */
 			t_gen_mov_env_TN(trap_vector, 
 					 tcg_const_tl(dc->op1 + 16));
@@ -2884,8 +2976,7 @@
 		for(j = 0; j < env->nb_breakpoints; j++) {
 			if (env->breakpoints[j] == dc->pc) {
 				cris_evaluate_flags (dc);
-				tcg_gen_movi_tl(cpu_T[0], dc->pc);
-				t_gen_mov_env_TN(pc, cpu_T[0]);
+				tcg_gen_movi_tl(env_pc, dc->pc);
 				t_gen_raise_exception(EXCP_DEBUG);
 				dc->is_jmp = DISAS_UPDATE;
 			}
@@ -2940,6 +3031,7 @@
 	struct DisasContext ctx;
 	struct DisasContext *dc = &ctx;
 	uint32_t next_page_start;
+	target_ulong npc;
 
 	if (!logfile)
 		logfile = stderr;
@@ -2968,18 +3060,24 @@
 	dc->cc_size_uptodate = -1;
 
 	/* Decode TB flags.  */
-	dc->user = tb->flags & U_FLAG;
+	dc->tb_flags = tb->flags & (P_FLAG | U_FLAG | X_FLAG);
 	dc->delayed_branch = !!(tb->flags & 7);
+	if (dc->delayed_branch)
+		dc->jmp = JMP_INDIRECT;
+	else
+		dc->jmp = JMP_NOJMP;
 
+	dc->cpustate_changed = 0;
+
 	if (loglevel & CPU_LOG_TB_IN_ASM) {
 		fprintf(logfile,
-			"srch=%d pc=%x %x bt=%x ds=%lld ccs=%x\n"
+			"srch=%d pc=%x %x flg=%llx bt=%x ds=%lld ccs=%x\n"
 			"pid=%x usp=%x\n"
 			"%x.%x.%x.%x\n"
 			"%x.%x.%x.%x\n"
 			"%x.%x.%x.%x\n"
 			"%x.%x.%x.%x\n",
-			search_pc, dc->pc, dc->ppc, 
+			search_pc, dc->pc, dc->ppc, tb->flags,
 			env->btarget, tb->flags & 7,
 			env->pregs[PR_CCS], 
 			env->pregs[PR_PID], env->pregs[PR_USP],
@@ -2997,9 +3095,6 @@
 	do
 	{
 		check_breakpoint(env, dc);
-		if (dc->is_jmp == DISAS_JUMP
-		    || dc->is_jmp == DISAS_SWI)
-			goto done;
 
 		if (search_pc) {
 			j = gen_opc_ptr - gen_opc_buf;
@@ -3034,13 +3129,20 @@
 		   actually genereating any host code, the simulator will just
 		   loop doing nothing for on this program location.  */
 		if (dc->delayed_branch) {
-			t_gen_mov_env_TN(dslot, tcg_const_tl(0));
 			dc->delayed_branch--;
 			if (dc->delayed_branch == 0)
 			{
-				t_gen_cc_jmp(env_btarget, 
-					     tcg_const_tl(dc->pc));
-				dc->is_jmp = DISAS_JUMP;
+				if (tb->flags & 7)
+					t_gen_mov_env_TN(dslot, 
+						tcg_const_tl(0));
+				if (dc->jmp == JMP_DIRECT) {
+					dc->is_jmp = DISAS_NEXT;
+				} else {
+					t_gen_cc_jmp(env_btarget, 
+						     tcg_const_tl(dc->pc));
+					dc->is_jmp = DISAS_JUMP;
+				}
+				break;
 			}
 		}
 
@@ -3051,28 +3153,33 @@
 	} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end
 		 && (dc->pc < next_page_start));
 
+	npc = dc->pc;
+	if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
+		npc = dc->jmp_pc;
+
+	/* Force an update if the per-tb cpu state has changed.  */
+	if (dc->is_jmp == DISAS_NEXT
+	    && (dc->cpustate_changed || !dc->flagx_known 
+	    || (dc->flags_x != (tb->flags & X_FLAG)))) {
+		dc->is_jmp = DISAS_UPDATE;
+		tcg_gen_movi_tl(env_pc, npc);
+	}
 	/* Broken branch+delayslot sequence.  */
 	if (dc->delayed_branch == 1) {
 		/* Set env->dslot to the size of the branch insn.  */
 		t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
+		cris_store_direct_jmp(dc);
 	}
 
-	if (!dc->is_jmp) {
-		D(fprintf(logfile, "!jmp pc=%x jmp=%d db=%d\n", dc->pc, 
-			 dc->is_jmp, dc->delayed_branch));
-		/* T0 and env_pc should hold the new pc.  */
-		tcg_gen_movi_tl(cpu_T[0], dc->pc);
-		tcg_gen_mov_tl(env_pc, cpu_T[0]);
-	}
+	cris_evaluate_flags (dc);
 
-	cris_evaluate_flags (dc);
-  done:
 	if (__builtin_expect(env->singlestep_enabled, 0)) {
+		tcg_gen_movi_tl(env_pc, npc);
 		t_gen_raise_exception(EXCP_DEBUG);
 	} else {
 		switch(dc->is_jmp) {
 			case DISAS_NEXT:
-				gen_goto_tb(dc, 1, dc->pc);
+				gen_goto_tb(dc, 1, npc);
 				break;
 			default:
 			case DISAS_JUMP:
@@ -3207,7 +3314,9 @@
 	env_btarget = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
 					 offsetof(CPUState, btarget),
 					 "btarget");
-
+	env_btaken = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+					 offsetof(CPUState, btaken),
+					 "btaken");
 	for (i = 0; i < 16; i++) {
 		cpu_R[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
 					      offsetof(CPUState, regs[i]),

                 reply	other threads:[~2008-06-06 11:23 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E1K4a2b-0007YF-6x@cvs.savannah.gnu.org \
    --to=edgar.iglesias@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).