translate.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,711 行 · 第 1/5 页

C
2,711
字号
 */static inline void t_gen_swapr(TCGv d, TCGv s){	struct {		int shift; /* LSL when positive, LSR when negative.  */		uint32_t mask;	} bitrev [] = {		{7, 0x80808080},		{5, 0x40404040},		{3, 0x20202020},		{1, 0x10101010},		{-1, 0x08080808},		{-3, 0x04040404},		{-5, 0x02020202},		{-7, 0x01010101}	};	int i;	TCGv t, org_s;	/* d and s refer the same object.  */	t = tcg_temp_new(TCG_TYPE_TL);	org_s = tcg_temp_new(TCG_TYPE_TL);	tcg_gen_mov_tl(org_s, s);	tcg_gen_shli_tl(t, org_s,  bitrev[0].shift);	tcg_gen_andi_tl(d, t,  bitrev[0].mask);	for (i = 1; i < sizeof bitrev / sizeof bitrev[0]; i++) {		if (bitrev[i].shift >= 0) {			tcg_gen_shli_tl(t, org_s,  bitrev[i].shift);		} else {			tcg_gen_shri_tl(t, org_s,  -bitrev[i].shift);		}		tcg_gen_andi_tl(t, t,  bitrev[i].mask);		tcg_gen_or_tl(d, d, t);	}	tcg_gen_discard_tl(t);	tcg_gen_discard_tl(org_s);}static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false){	TCGv btaken;	int l1;	l1 = gen_new_label();	btaken = tcg_temp_new(TCG_TYPE_TL);	/* Conditional jmp.  */	t_gen_mov_TN_env(btaken, btaken);	tcg_gen_mov_tl(env_pc, pc_false);	tcg_gen_brcond_tl(TCG_COND_EQ, btaken, tcg_const_tl(0), l1);	tcg_gen_mov_tl(env_pc, pc_true);	gen_set_label(l1);	tcg_gen_discard_tl(btaken);}static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest){	TranslationBlock *tb;	tb = dc->tb;	if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {		tcg_gen_goto_tb(n);		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_exit_tb(0);	}}/* Sign extend at translation time.  */static int sign_extend(unsigned int val, unsigned int width){	int sval;	/* LSL.  */	val <<= 31 - width;	sval = val;	/* ASR.  */	sval >>= 31 - width;	return sval;}static inline void cris_clear_x_flag(DisasContext *dc){	if (!dc->flagx_live 	    || (dc->flagx_live && dc->flags_x)	    || dc->cc_op == CC_OP_FLAGS)		tcg_gen_andi_i32(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG);	dc->flagx_live = 1;	dc->flags_x = 0;}static void cris_evaluate_flags(DisasContext *dc){	if (!dc->flags_live) {		tcg_gen_movi_tl(cc_op, dc->cc_op);		tcg_gen_movi_tl(cc_size, dc->cc_size);		tcg_gen_movi_tl(cc_mask, dc->cc_mask);		switch (dc->cc_op)		{			case CC_OP_MCP:				tcg_gen_helper_0_0(helper_evaluate_flags_mcp);				break;			case CC_OP_MULS:				tcg_gen_helper_0_0(helper_evaluate_flags_muls);				break;			case CC_OP_MULU:				tcg_gen_helper_0_0(helper_evaluate_flags_mulu);				break;			case CC_OP_MOVE:				switch (dc->cc_size)				{					case 4:						tcg_gen_helper_0_0(helper_evaluate_flags_move_4);						break;					case 2:						tcg_gen_helper_0_0(helper_evaluate_flags_move_2);						break;					default:						tcg_gen_helper_0_0(helper_evaluate_flags);						break;				}				break;			case CC_OP_FLAGS:				/* live.  */				break;			default:			{				switch (dc->cc_size)				{					case 4:						tcg_gen_helper_0_0(helper_evaluate_flags_alu_4);						break;					default:						tcg_gen_helper_0_0(helper_evaluate_flags);						break;				}			}			break;		}		dc->flags_live = 1;	}}static void cris_cc_mask(DisasContext *dc, unsigned int mask){	uint32_t ovl;	/* Check if we need to evaluate the condition codes due to 	   CC overlaying.  */	ovl = (dc->cc_mask ^ mask) & ~mask;	if (ovl) {		/* TODO: optimize this case. It trigs all the time.  */		cris_evaluate_flags (dc);	}	dc->cc_mask = mask;	dc->update_cc = 1;	if (mask == 0)		dc->update_cc = 0;	else		dc->flags_live = 0;}static void cris_update_cc_op(DisasContext *dc, int op, int size){	dc->cc_op = op;	dc->cc_size = size;	dc->flags_live = 0;}/* op is the operation.   T0, T1 are the operands.   dst is the destination reg.*/static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size){	int writeback = 1;	if (dc->update_cc) {		cris_update_cc_op(dc, op, size);		if (op != CC_OP_MOVE)			tcg_gen_mov_tl(cc_dest, cpu_T[0]);		/* FIXME: This shouldn't be needed. But we don't pass the		   tests without it. Investigate.  */		t_gen_mov_env_TN(cc_x_live, tcg_const_tl(dc->flagx_live));		t_gen_mov_env_TN(cc_x, tcg_const_tl(dc->flags_x));	}	/* Emit the ALU insns.  */	switch (op)	{		case CC_OP_ADD:			tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			/* Extended arithmetics.  */			t_gen_addx_carry(cpu_T[0]);			break;		case CC_OP_ADDC:			tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			t_gen_add_flag(cpu_T[0], 0); /* C_FLAG.  */			break;		case CC_OP_MCP:			tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			t_gen_add_flag(cpu_T[0], 8); /* R_FLAG.  */			break;		case CC_OP_SUB:			tcg_gen_neg_tl(cpu_T[1], cpu_T[1]);			tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			tcg_gen_neg_tl(cpu_T[1], cpu_T[1]);			/* CRIS flag evaluation needs ~src.  */			tcg_gen_xori_tl(cpu_T[1], cpu_T[1], -1);			/* Extended arithmetics.  */			t_gen_subx_carry(dc, cpu_T[0]);			break;		case CC_OP_MOVE:			tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);			break;		case CC_OP_OR:			tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			break;		case CC_OP_AND:			tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			break;		case CC_OP_XOR:			tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			break;		case CC_OP_LSL:			t_gen_lsl(cpu_T[0], cpu_T[0], cpu_T[1]);			break;		case CC_OP_LSR:			t_gen_lsr(cpu_T[0], cpu_T[0], cpu_T[1]);			break;		case CC_OP_ASR:			t_gen_asr(cpu_T[0], cpu_T[0], cpu_T[1]);			break;		case CC_OP_NEG:			tcg_gen_neg_tl(cpu_T[0], cpu_T[1]);			/* Extended arithmetics.  */			t_gen_subx_carry(dc, cpu_T[0]);			break;		case CC_OP_LZ:			t_gen_lz_i32(cpu_T[0], cpu_T[1]);			break;		case CC_OP_BTST:			t_gen_btst(cpu_T[0], cpu_T[1]);			writeback = 0;			break;		case CC_OP_MULS:		{			TCGv mof;			mof = tcg_temp_new(TCG_TYPE_TL);			t_gen_muls(cpu_T[0], mof, cpu_T[0], cpu_T[1]);			t_gen_mov_preg_TN(dc, PR_MOF, mof);			tcg_gen_discard_tl(mof);		}		break;		case CC_OP_MULU:		{			TCGv mof;			mof = tcg_temp_new(TCG_TYPE_TL);			t_gen_mulu(cpu_T[0], mof, cpu_T[0], cpu_T[1]);			t_gen_mov_preg_TN(dc, PR_MOF, mof);			tcg_gen_discard_tl(mof);		}		break;		case CC_OP_DSTEP:			t_gen_cris_dstep(cpu_T[0], cpu_T[1]);			break;		case CC_OP_BOUND:		{			int l1;			l1 = gen_new_label();			tcg_gen_brcond_tl(TCG_COND_LEU, 					  cpu_T[0], cpu_T[1], l1);			tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);			gen_set_label(l1);		}		break;		case CC_OP_CMP:			tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);			/* CRIS flag evaluation needs ~src.  */			tcg_gen_xori_tl(cpu_T[1], cpu_T[1], ~0);			/* Extended arithmetics.  */			t_gen_subx_carry(dc, cpu_T[0]);			writeback = 0;			break;		default:			fprintf (logfile, "illegal ALU op.\n");			BUG();			break;	}	if (dc->update_cc)		tcg_gen_mov_tl(cc_src, cpu_T[1]);	if (size == 1)		tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);	else if (size == 2)		tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);	/* Writeback.  */	if (writeback) {		if (size == 4)			tcg_gen_mov_tl(cpu_R[rd], cpu_T[0]);		else {			if (size == 1)				tcg_gen_andi_tl(cpu_R[rd], cpu_R[rd], ~0xff);			else				tcg_gen_andi_tl(cpu_R[rd], cpu_R[rd], ~0xffff);			tcg_gen_or_tl(cpu_R[rd], cpu_R[rd], cpu_T[0]);		}	}	if (dc->update_cc)		tcg_gen_mov_tl(cc_result, cpu_T[0]);}static int arith_cc(DisasContext *dc){	if (dc->update_cc) {		switch (dc->cc_op) {			case CC_OP_ADD: return 1;			case CC_OP_SUB: return 1;			case CC_OP_LSL: return 1;			case CC_OP_LSR: return 1;			case CC_OP_ASR: return 1;			case CC_OP_CMP: return 1;			default:				return 0;		}	}	return 0;}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) {				/* 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);				tcg_gen_andi_tl(cpu_T[0], 						cpu_PR[PR_CCS], Z_FLAG);			}			break;		case CC_NE:			if (arith_opt)				tcg_gen_mov_tl(cpu_T[0], cc_result);			else {				cris_evaluate_flags(dc);				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);			tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG);			break;		case CC_CC:			cris_evaluate_flags(dc);			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);			tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], V_FLAG);			break;		case CC_VC:			cris_evaluate_flags(dc);			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)				tcg_gen_shli_tl(cpu_T[0], cc_result, 31);			else {				cris_evaluate_flags(dc);				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) {				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);				tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS],						N_FLAG);			}			break;		case CC_LS:			cris_evaluate_flags(dc);			tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS],					C_FLAG | Z_FLAG);			break;		case CC_HI:			cris_evaluate_flags(dc);			{				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);			/* 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);			/* 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);			{				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);			{				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);			tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], P_FLAG);			break;		case CC_A:			tcg_gen_movi_tl(cpu_T[0], 1);			break;		default:			BUG();			break;	};}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;	if (cond != CC_A)	{		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);}/* Dynamic jumps, when the dest is in a live reg for example.  */void cris_prepare_dyn_jmp (DisasContext *dc){	/* 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));}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?