translate.c

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

C
2,711
字号
/* *  CRIS emulation for qemu: main translation routines. * *  Copyright (c) 2008 AXIS Communications AB *  Written by Edgar E. Iglesias. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * FIXME: * The condition code translation is in need of attention. */#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include <assert.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"#include "tcg-op.h"#include "helper.h"#include "crisv32-decode.h"#include "qemu-common.h"#define DISAS_CRIS 0#if DISAS_CRIS#define DIS(x) x#else#define DIS(x)#endif#define D(x)#define BUG() (gen_BUG(dc, __FILE__, __LINE__))#define BUG_ON(x) ({if (x) BUG();})#define DISAS_SWI 5/* Used by the decoder.  */#define EXTRACT_FIELD(src, start, end) \            (((src) >> start) & ((1 << (end - start + 1)) - 1))#define CC_MASK_NZ 0xc#define CC_MASK_NZV 0xe#define CC_MASK_NZVC 0xf#define CC_MASK_RNZV 0x10eTCGv cpu_env;TCGv cpu_T[2];TCGv cpu_R[16];TCGv cpu_PR[16];TCGv cc_src;TCGv cc_dest;TCGv cc_result;TCGv cc_op;TCGv cc_size;TCGv cc_mask;TCGv env_btarget;TCGv env_pc;/* This is the state at translation time.  */typedef struct DisasContext {	CPUState *env;	target_ulong pc, ppc;	/* Decoder.  */	uint32_t ir;	uint32_t opcode;	unsigned int op1;	unsigned int op2;	unsigned int zsize, zzsize;	unsigned int mode;	unsigned int postinc;	int update_cc;	int cc_op;	int cc_size;	uint32_t cc_mask;	int flags_live; /* Wether or not $ccs is uptodate.  */	int flagx_live; /* Wether or not flags_x has the x flag known at			   translation time.  */	int flags_x;	int clear_x; /* Clear x after this insn?  */	int user; /* user or kernel mode.  */	int is_jmp;	int delayed_branch;	struct TranslationBlock *tb;	int singlestep_enabled;} DisasContext;static void gen_BUG(DisasContext *dc, char *file, int line){	printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);	fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);	cpu_abort(dc->env, "%s:%d\n", file, line);}const char *regnames[] ={	"$r0", "$r1", "$r2", "$r3",	"$r4", "$r5", "$r6", "$r7",	"$r8", "$r9", "$r10", "$r11",	"$r12", "$r13", "$sp", "$acr",};const char *pregnames[] ={	"$bz", "$vr", "$pid", "$srs",	"$wz", "$exs", "$eda", "$mof",	"$dz", "$ebp", "$erp", "$srp",	"$nrp", "$ccs", "$usp", "$spc",};/* We need this table to handle preg-moves with implicit width.  */int preg_sizes[] = {	1, /* bz.  */	1, /* vr.  */	4, /* pid.  */	1, /* srs.  */	2, /* wz.  */	4, 4, 4,	4, 4, 4, 4,	4, 4, 4, 4,};#define t_gen_mov_TN_env(tn, member) \ _t_gen_mov_TN_env((tn), offsetof(CPUState, member))#define t_gen_mov_env_TN(member, tn) \ _t_gen_mov_env_TN(offsetof(CPUState, member), (tn))static inline void t_gen_mov_TN_reg(TCGv tn, int r){	if (r < 0 || r > 15)		fprintf(stderr, "wrong register read $r%d\n", r);	tcg_gen_mov_tl(tn, cpu_R[r]);}static inline void t_gen_mov_reg_TN(int r, TCGv tn){	if (r < 0 || r > 15)		fprintf(stderr, "wrong register write $r%d\n", r);	tcg_gen_mov_tl(cpu_R[r], tn);}static inline void _t_gen_mov_TN_env(TCGv tn, int offset){	if (offset > sizeof (CPUState))		fprintf(stderr, "wrong load from env from off=%d\n", offset);	tcg_gen_ld_tl(tn, cpu_env, offset);}static inline void _t_gen_mov_env_TN(int offset, TCGv tn){	if (offset > sizeof (CPUState))		fprintf(stderr, "wrong store to env at off=%d\n", offset);	tcg_gen_st_tl(tn, cpu_env, offset);}static inline void t_gen_mov_TN_preg(TCGv tn, int r){	if (r < 0 || r > 15)		fprintf(stderr, "wrong register read $p%d\n", r);	if (r == PR_BZ || r == PR_WZ || r == PR_DZ)		tcg_gen_mov_tl(tn, tcg_const_tl(0));	else if (r == PR_VR)		tcg_gen_mov_tl(tn, tcg_const_tl(32));	else if (r == PR_EXS) {		printf("read from EXS!\n");		tcg_gen_mov_tl(tn, cpu_PR[r]);	}	else if (r == PR_EDA) {		printf("read from EDA!\n");		tcg_gen_mov_tl(tn, cpu_PR[r]);	}	else		tcg_gen_mov_tl(tn, cpu_PR[r]);}static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn){	if (r < 0 || r > 15)		fprintf(stderr, "wrong register write $p%d\n", r);	if (r == PR_BZ || r == PR_WZ || r == PR_DZ)		return;	else if (r == PR_SRS)		tcg_gen_andi_tl(cpu_PR[r], tn, 3);	else {		tcg_gen_mov_tl(cpu_PR[r], tn);		if (r == PR_PID)			tcg_gen_helper_0_1(helper_tlb_flush_pid, tn);	}}static inline void t_gen_raise_exception(uint32_t index){	tcg_gen_helper_0_1(helper_raise_exception, tcg_const_tl(index));}static void t_gen_lsl(TCGv d, TCGv a, TCGv b){	int l1;	l1 = gen_new_label();	/* Speculative shift. */	tcg_gen_shl_tl(d, a, b);	tcg_gen_brcond_tl(TCG_COND_LEU, b, tcg_const_tl(31), l1);	/* Clear dst if shift operands were to large.  */	tcg_gen_movi_tl(d, 0);	gen_set_label(l1);}static void t_gen_lsr(TCGv d, TCGv a, TCGv b){	int l1;	l1 = gen_new_label();	/* Speculative shift. */	tcg_gen_shr_tl(d, a, b);	tcg_gen_brcond_tl(TCG_COND_LEU, b, tcg_const_tl(31), l1);	/* Clear dst if shift operands were to large.  */	tcg_gen_movi_tl(d, 0);	gen_set_label(l1);}static void t_gen_asr(TCGv d, TCGv a, TCGv b){	int l1;	l1 = gen_new_label();	/* Speculative shift. */	tcg_gen_sar_tl(d, a, b);	tcg_gen_brcond_tl(TCG_COND_LEU, b, tcg_const_tl(31), l1);	/* Clear dst if shift operands were to large.  */	tcg_gen_sar_tl(d, a, tcg_const_tl(30));	gen_set_label(l1);}/* 64-bit signed mul, lower result in d and upper in d2.  */static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b){	TCGv t0, t1;	t0 = tcg_temp_new(TCG_TYPE_I64);	t1 = tcg_temp_new(TCG_TYPE_I64);	tcg_gen_ext32s_i64(t0, a);	tcg_gen_ext32s_i64(t1, b);	tcg_gen_mul_i64(t0, t0, t1);	tcg_gen_trunc_i64_i32(d, t0);	tcg_gen_shri_i64(t0, t0, 32);	tcg_gen_trunc_i64_i32(d2, t0);	tcg_gen_discard_i64(t0);	tcg_gen_discard_i64(t1);}/* 64-bit unsigned muls, lower result in d and upper in d2.  */static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b){	TCGv t0, t1;	t0 = tcg_temp_new(TCG_TYPE_I64);	t1 = tcg_temp_new(TCG_TYPE_I64);	tcg_gen_extu_i32_i64(t0, a);	tcg_gen_extu_i32_i64(t1, b);	tcg_gen_mul_i64(t0, t0, t1);	tcg_gen_trunc_i64_i32(d, t0);	tcg_gen_shri_i64(t0, t0, 32);	tcg_gen_trunc_i64_i32(d2, t0);	tcg_gen_discard_i64(t0);	tcg_gen_discard_i64(t1);}/* 32bit branch-free binary search for counting leading zeros.  */static void t_gen_lz_i32(TCGv d, TCGv x){	TCGv y, m, n;	y = tcg_temp_new(TCG_TYPE_I32);	m = tcg_temp_new(TCG_TYPE_I32);	n = tcg_temp_new(TCG_TYPE_I32);	/* y = -(x >> 16)  */	tcg_gen_shri_i32(y, x, 16);	tcg_gen_neg_i32(y, y);	/* m = (y >> 16) & 16  */	tcg_gen_sari_i32(m, y, 16);	tcg_gen_andi_i32(m, m, 16);	/* n = 16 - m  */	tcg_gen_sub_i32(n, tcg_const_i32(16), m);	/* x = x >> m  */	tcg_gen_shr_i32(x, x, m);	/* y = x - 0x100  */	tcg_gen_subi_i32(y, x, 0x100);	/* m = (y >> 16) & 8  */	tcg_gen_sari_i32(m, y, 16);	tcg_gen_andi_i32(m, m, 8);	/* n = n + m  */	tcg_gen_add_i32(n, n, m);	/* x = x << m  */	tcg_gen_shl_i32(x, x, m);	/* y = x - 0x1000  */	tcg_gen_subi_i32(y, x, 0x1000);	/* m = (y >> 16) & 4  */	tcg_gen_sari_i32(m, y, 16);	tcg_gen_andi_i32(m, m, 4);	/* n = n + m  */	tcg_gen_add_i32(n, n, m);	/* x = x << m  */	tcg_gen_shl_i32(x, x, m);	/* y = x - 0x4000  */	tcg_gen_subi_i32(y, x, 0x4000);	/* m = (y >> 16) & 2  */	tcg_gen_sari_i32(m, y, 16);	tcg_gen_andi_i32(m, m, 2);	/* n = n + m  */	tcg_gen_add_i32(n, n, m);	/* x = x << m  */	tcg_gen_shl_i32(x, x, m);	/* y = x >> 14  */	tcg_gen_shri_i32(y, x, 14);	/* m = y & ~(y >> 1)  */	tcg_gen_sari_i32(m, y, 1);	tcg_gen_xori_i32(m, m, 0xffffffff);	tcg_gen_and_i32(m, m, y);	/* d = n + 2 - m  */	tcg_gen_addi_i32(d, n, 2);	tcg_gen_sub_i32(d, d, m);	tcg_gen_discard_i32(y);	tcg_gen_discard_i32(m);	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;	l1 = gen_new_label();	/* 	 * d <<= 1	 * if (d >= s)	 *    d -= s;	 */	tcg_gen_shli_tl(d, d, 1);	tcg_gen_brcond_tl(TCG_COND_LTU, d, s, l1);	tcg_gen_sub_tl(d, d, s);	gen_set_label(l1);}/* Extended arithmetics on CRIS.  */static inline void t_gen_add_flag(TCGv d, int flag){	TCGv c;	c = tcg_temp_new(TCG_TYPE_TL);	t_gen_mov_TN_preg(c, PR_CCS);	/* Propagate carry into d.  */	tcg_gen_andi_tl(c, c, 1 << flag);	if (flag)		tcg_gen_shri_tl(c, c, flag);	tcg_gen_add_tl(d, d, c);	tcg_gen_discard_tl(c);}static inline void t_gen_addx_carry(TCGv d){	TCGv x, c;	x = tcg_temp_new(TCG_TYPE_TL);	c = tcg_temp_new(TCG_TYPE_TL);	t_gen_mov_TN_preg(x, PR_CCS);	tcg_gen_mov_tl(c, x);	/* Propagate carry into d if X is set. Branch free.  */	tcg_gen_andi_tl(c, c, C_FLAG);	tcg_gen_andi_tl(x, x, X_FLAG);	tcg_gen_shri_tl(x, x, 4);	tcg_gen_and_tl(x, x, c);	tcg_gen_add_tl(d, d, x);        	tcg_gen_discard_tl(x);	tcg_gen_discard_tl(c);}static inline void t_gen_subx_carry(DisasContext *dc, TCGv d){	if (dc->flagx_live) {		TCGv x, c;		x = tcg_temp_new(TCG_TYPE_TL);		c = tcg_temp_new(TCG_TYPE_TL);		t_gen_mov_TN_preg(x, PR_CCS);		tcg_gen_mov_tl(c, x);		/* Propagate carry into d if X is set. Branch free.  */		tcg_gen_andi_tl(c, c, C_FLAG);		tcg_gen_andi_tl(x, x, X_FLAG);		tcg_gen_shri_tl(x, x, 4);		tcg_gen_and_tl(x, x, c);		tcg_gen_sub_tl(d, d, x);		tcg_gen_discard_tl(x);		tcg_gen_discard_tl(c);	} else {		if (dc->flags_x) {			TCGv c;					c = tcg_temp_new(TCG_TYPE_TL);			/* C flag is already at bit 0.  */			tcg_gen_andi_tl(c, c, C_FLAG);			tcg_gen_add_tl(d, d, c);			tcg_gen_discard_tl(c);		}	}}/* Swap the two bytes within each half word of the s operand.   T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff)  */static inline void t_gen_swapb(TCGv d, TCGv s){	TCGv t, org_s;	t = tcg_temp_new(TCG_TYPE_TL);	org_s = tcg_temp_new(TCG_TYPE_TL);	/* d and s may refer to the same object.  */	tcg_gen_mov_tl(org_s, s);	tcg_gen_shli_tl(t, org_s, 8);	tcg_gen_andi_tl(d, t, 0xff00ff00);	tcg_gen_shri_tl(t, org_s, 8);	tcg_gen_andi_tl(t, t, 0x00ff00ff);	tcg_gen_or_tl(d, d, t);	tcg_gen_discard_tl(t);	tcg_gen_discard_tl(org_s);}/* Swap the halfwords of the s operand.  */static inline void t_gen_swapw(TCGv d, TCGv s){	TCGv t;	/* d and s refer the same object.  */	t = tcg_temp_new(TCG_TYPE_TL);	tcg_gen_mov_tl(t, s);	tcg_gen_shli_tl(d, t, 16);	tcg_gen_shri_tl(t, t, 16);	tcg_gen_or_tl(d, d, t);	tcg_gen_discard_tl(t);}/* Reverse the within each byte.   T0 = (((T0 << 7) & 0x80808080) |   ((T0 << 5) & 0x40404040) |   ((T0 << 3) & 0x20202020) |   ((T0 << 1) & 0x10101010) |   ((T0 >> 1) & 0x08080808) |   ((T0 >> 3) & 0x04040404) |   ((T0 >> 5) & 0x02020202) |   ((T0 >> 7) & 0x01010101));

⌨️ 快捷键说明

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