⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tb.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "armdefs.h"
//teawater 2005-09-12  for gcc-3.3.x compiling, comment below line
//#include "arm2x86_self.h"

extern mem_bank_t	*bank_ptr(ARMword addr);

/*ywc 2005-04-22, in armmem.c*/
extern mem_bank_t	*insn_bank_ptr(ARMword addr);

//teawater add for new tb manage function 2005.07.10----------------------------
//static uint32_t	tb_tbt_size = 0;
//static uint32_t	tb_tbp_size = (1024 * 1024 * 32);
#define TB_TBT_SIZE	skyeye_config.tb_tbt_size
#define TB_TBP_SIZE	skyeye_config.tb_tbp_size

static tb_t		*tbt_table = NULL;
static int		tbt_table_size = 0;

static uint8_t		*tbp_begin = NULL;
static uint8_t		*tbp_now = NULL;
static uint32_t		tbp_now_size = 0;
static int		tbp_dynamic = 0;
static LIST_HEAD(tbp_dynamic_list);
//AJ2D--------------------------------------------------------------------------
#ifdef  __FreeBSD__
#define MAP_ANONYMOUS MAP_ANON 
#endif

static __inline__ int
translate_word(ARMul_State *state, ARMword insn, uint8_t *tbp)
{
	int		toplen = 0, len = 0;
	ARMword		cond, val, op1, shift, rm, rs, rn, rd, sh;
	uint8_t		*begin = tbp;

	//init
	begin = tbp;
	state->trap = 0;

//teawater change for debug function 2005.07.09---------------------------------
	//breakpoint
	if (insn == 0xe7ffdefe) {
		GEN_OP(tbp, len, op_begin);
		gen_op_movl_trap_im_use_T2(state, &tbp, &len, TRAP_BREAKPOINT);
		GEN_OP(tbp, len, op_return);
		goto out;
	}
//AJ2D--------------------------------------------------------------------------

	//return if debug || irq || fiq || condition
	cond = (insn >> 28) & 0xff;
	if (cond == AL || cond == NV) {
		GEN_OP(tbp, len, op_begin);
		//some insn need it
		//if (cond == NV)
		//	goto translate_word_out;
	}
	else {
		gen_op_movl_Tx_im(state, &tbp, &len, 0, cond);
		GEN_OP(tbp, len, op_begin_test_T0);
		toplen = len;
	}

	if (((insn & 0x0e000000) == 0 && (insn & 0x00000090) != 0x90) || ((insn & 0x0e000000) == (1 << 25))) {
		ARMword		set_cc, logic_cc, shiftop;

		if (cond == NV)
			goto translate_word_out;

		op1 = (insn >> 21) & 0xf;
		set_cc = (insn >> 20) & 1;

		if ((op1 == 0x8 || op1 == 0xa) && !set_cc) {
			//mrs
			gen_op_mrs(state, &tbp, &len, insn);
			goto translate_word_end;
		}

		logic_cc = table_logic_cc[op1] & set_cc;
		//in arm_arm A 5.1
		if (insn & (1 << 25)) {
			//immediate operand arm_arm A 5.1.3
			val = insn & 0xff;
			shift = (uint8_t)((insn >> 8) & 0xf) * 2;
			//ror
			if (shift)
				val = (val >> shift) | (val << (32 - shift));
			//op=set val to t1
			gen_op_movl_Tx_im(state, &tbp, &len, 1, val);

			if (logic_cc && shift) {
				//val = ((insn & 0xff) >> (shift - 1)) & 1;
				//op=set val[31] to C
				if (val >> 31) {
					GEN_OP(tbp, len, op_logic_1_sc);
				}
				else {
					GEN_OP(tbp, len, op_logic_0_sc);
				}
			}
		}
		else {
			//register
			rm = (insn) & 0xf;
			//op=set rm(0-15) to t1
			gen_op_movl_Tx_reg(state, &tbp, &len, 1, rm);

//teawater add check thumb 2005.07.21-------------------------------------------
			if (op1 == 0x9 && !set_cc && ((insn >> 8) & 0xf) == 0xf) {
				//bx or blx(2)
				uint32_t	tmp = (insn >> 4) & 0xf;

				if (tmp == 0x1) {
					//bx
					GEN_OP(tbp, len, op_bx_T1);
				}
				else if (tmp == 0x2){
					//blx(2)
					GEN_OP(tbp, len, op_blx_T1);
				}
				if (tmp == 0x1 || tmp == 0x2) {
					state->trap = 1;
					goto translate_word_end;
				}
			}
//AJ2D--------------------------------------------------------------------------

			shiftop = (insn >> 5) & 3;
			if (!(insn & (1 << 4))) {
				//imm
				shift = (uint8_t)(insn >> 7) & 0x1f;
				if (shift != 0) {
					//op=shift, & set CF if logic_cc
					if (logic_cc) {
						gen_op_shift_T1_im_sc(state, &tbp, &len, shiftop, shift);
					}
					gen_op_shift_T1_im(state, &tbp, &len, shiftop, shift);
				}
				else {
					GEN_OP(tbp, len, op_movl_T2_T1);
					GEN_OP(tbp, len, op_shift_T1_0[shiftop]);
					if (logic_cc) {
						GEN_OP(tbp, len, op_shift_T2_0_sc[shiftop]);
						GEN_OP(tbp, len, op_set_cf);
					}
				}
			}
			else {
				//reg
				rs = (insn >> 8) & 0xf;
				//op=set rs(0-15) to t0
				gen_op_movl_Tx_reg(state, &tbp, &len, 0, rs);
				//op=shift, & set CF if logic_cc
				if (logic_cc) {
					//op=shift & set CF
					gen_op_shift_T1_T0_sc(state, &tbp, &len, shiftop);
				}
				else {
					//op=shift
					gen_op_shift_T1_T0(state, &tbp, &len, shiftop);
				}
			}
		}

		if ((op1 == 0x9 || op1 == 0xb) && !set_cc) {
			//msr	T1, psr
			gen_op_msr(state, &tbp, &len, insn);
			goto translate_word_end;
		}

		//data processing instruction
		if (op1 != 0x0f && op1 != 0x0d) {	//!mov && !mvn
			rn = (insn >> 16) & 0xf;
			//op=set rn(0-15) to t0
			gen_op_movl_Tx_reg(state, &tbp, &len, 0, rn);
		}
		rd = (insn >> 12) & 0xf;
		arm2x86_get_dp_op[op1](state, &tbp, &len, set_cc, rd);
		arm2x86_get_dp_op_setcpsr[op1](state, &tbp, &len, set_cc, rd);
	}
	else {
		//other instructions
		op1 = (insn >> 24) & 0xf;
		sh = (insn >> 5) & 3;

		if (cond == NV) {
			if (state->is_v5 && sh >= 12 && sh <= 14) {
				//cdp2 ldc2 stc2 mrc2 mcr2 in arm_arm A 4.1.11
			}
//teawater add check thumb 2005.07.21-------------------------------------------
			else if (state->is_v5 && (op1 == 0xa || op1 == 0xb)) {
				//blx(1)
				gen_op_movl_trap_im_use_T2(state, &tbp, &len, TRAP_UNPREDICTABLE);
				GEN_OP(tbp, len, op_return);
				goto out;
			}
//AJ2D--------------------------------------------------------------------------
			else {
				goto translate_word_out;
			}
		}

		if (sh != 0 && (op1 == 0 || op1 == 1)) {
			//ldrh strh ldrsh ldrsb
			gen_op_ldrhstrh(state, &tbp, &len, insn, sh);
		}
		else {
			arm2x86_get_other_op[op1](state, insn, &tbp, &len);
		}
	}

translate_word_end:
	if (state->trap) {
		GEN_OP(tbp, len, op_return);
	}
	if (toplen && begin) {
		//set jmp length of condition code
		//begin[toplen-1] = (uint8_t)(len - toplen);
		int	*p_tmp = (int *)(begin + (toplen - sizeof(int)));
		*p_tmp = len - toplen;
	}

translate_word_out:
	//r15 += 4
	if (!state->trap || toplen) {
		GEN_OP(tbp, len, op_addpc);
		state->trap = 0;
	}
	//TEA_OUT(GEN_OP(tbp, len, op_return));

out:
	if (len > TB_INSN_LEN_MAX) {
		fprintf(stderr, "SKYEYE: TB_INSN_LEN_MAX: insn %x len %d > TB_INSN_LEN_MAX %d.\n", insn, len, TB_INSN_LEN_MAX);
		exit(-1);
	}
/*#ifdef TEA_DEBUG
	{
		static int	insn_max = 0;
		if (len > insn_max) {
			insn_max = len;
			fprintf(stderr, "\nSKYEYE: insn_max = %d.\n", insn_max);
		}
	}
#endif	//TEA_DEBUG*/

	return(len);
}

static uint8_t *
tb_translate(ARMul_State * state, ARMword *addr, ARMword *tb_begin_addr, uint8_t *tbp, ARMword *tran_addr, uint8_t **tbp_now)
{
	int		len;
	uint8_t		*ret = NULL;
	ARMword		*tb_end_addr = tb_begin_addr + (TB_LEN - (*tran_addr - TB_ALIGN(*tran_addr)))  / sizeof(ARMword);

	for( ; tb_begin_addr < tb_end_addr; tb_begin_addr++) {
		if (addr == tb_begin_addr) {
			ret = tbp;
		}
		len = translate_word(state, *tb_begin_addr, tbp);
		tbp += len;
//teawater change for if trap translate stop 2005.07.23-------------------------
		*tran_addr += 4;
		if (state->trap && ret) {
			break;
		}
//AJ2D--------------------------------------------------------------------------
	}
//teawater change for if trap translate stop 2005.07.23-------------------------
	*tbp_now = tbp;
	if (!state->trap) {
		GEN_OP(tbp, len, op_return);
	}
//AJ2D--------------------------------------------------------------------------

	return(ret);
}

static uint8_t *
tb_translate_find(ARMul_State * state, ARMword *addr, ARMword *tb_begin_addr, uint8_t *tbp)
{
	int		len;
	uint8_t		*ret = NULL;
	ARMword		*tb_end_addr = tb_begin_addr + TB_LEN  / sizeof(ARMword);

	for( ; tb_begin_addr < tb_end_addr; tb_begin_addr++) {
		if (addr == tb_begin_addr) {
			ret = tbp;
			break;
		}
		len = translate_word(state, *tb_begin_addr, NULL);
		tbp += len;
	}

	return(ret);
}

static inline void
tb_insert_cache(tb_t *tbt, ARMword addr, uint8_t *ret)
{
	tb_cache_t	*e = malloc(sizeof(tb_cache_t));

	if (e) {
		uint32_t	cache_num = addr & (TB_TBT_CACHE_MAX - 1);

		if (!tbt->cache[cache_num].next)
			INIT_LIST_HEAD(&tbt->cache[cache_num]);
		e->addr = addr;
		e->tp = ret;
		list_add_tail(&e->list, &tbt->cache[cache_num]);
	}
	else {
		TEA_OUT(fprintf(stderr, "SKYEYE: tb_find: Error allocating mem for cache.\n"));
	}
}

static inline uint8_t *
tb_find_cache(tb_t *tbt, ARMword addr)
{
	tb_cache_t		*e;
	struct list_head	*list,*n;
	uint32_t		cache_num = addr & (TB_TBT_CACHE_MAX - 1);

	if (tbt->cache[cache_num].next) {
		list_for_each_safe(list, n, &tbt->cache[cache_num]) {
			e = list_entry(list, tb_cache_t, list);
			if (e->addr == addr) {
				return(e->tp);
			}
		}
	}

	return(NULL);
}

static inline void
tb_clear_cache(tb_t *tbt)
{
	tb_cache_t		*e;
	struct list_head	*list,*n;
	uint32_t		cache_num;

	for(cache_num = 0; cache_num < TB_TBT_CACHE_MAX; cache_num++) {
		if (tbt->cache[cache_num].next) {
			list_for_each_safe(list, n, &tbt->cache[cache_num]) {
				e = list_entry(list, tb_cache_t, list);
				list_del_init(&e->list);
				free(e);
			}
		}
	}
}

static inline void
tb_get_tbp(tb_t *tbt)
{
	tb_t			*e;
	struct list_head	*list;

	if (tbp_now_size) {
		tbt->tbp = tbp_now;
		tbp_now += TB_TBP_MAX;
		tbp_now_size -= TB_TBP_MAX;
	}
	else {
		//get the oldest tbt from tbp_dynamic_list's head
		if (list_empty(&tbp_dynamic_list)) {
			fprintf(stderr, "SKYEYE: mem_reset: some bug.\n");
			exit(-1);
		}
		e = list_entry(tbp_dynamic_list.next, tb_t, list);
		tbt->tbp = e->tbp;
		e->tbp = NULL;
		if (e->ted) {
			tb_clear_cache(e);
			e->ted = 0;
		}
		list_del_init(&e->list);
	}
}

static inline mem_bank_t *
tb_get_mbp(ARMword addr, int *bank_num)
{
	mem_bank_t	*ret;

	ret = insn_bank_ptr(addr);
	if(ret) {
		*bank_num = ret - skyeye_config.mem.mem_banks;
	}

	return(ret);
}

uint8_t *
tb_find(ARMul_State * state, ARMword ADDR)
{
	uint8_t			*ret = NULL;
	ARMword			addr, align_addr;
	ARMword			*real_begin_addr, *real_addr;
	static ARMword		save_align_addr = 0x1;
	static tb_t		*tbt;
	static uint8_t		*tbp;
	static mem_bank_t 	*mbp;
	static int		bank_num = -1;

	//get addr & align_addr
	if (mmu_v2p_dbct(state,ADDR,&addr)) {
		goto out;
	}
	align_addr = TB_ALIGN(addr);
	if (align_addr == save_align_addr) {
		goto get_ret;
	}

	//init
	bank_num = -1;
	save_align_addr = 0x1;

	//get tbt
	if (tbt_table_size) {
		//dynamic tbt
		tbt = &(tbt_table[align_addr & (uint32_t)(tbt_table_size - 1)]);
		if (tbt->addr != align_addr) {
			if (tbt->ted) {
				tb_clear_cache(tbt);
				tbt->ted = 0;
			}
			tbt->addr = align_addr;
		}

		//get tbt->tbp
		if (!tbt->tbp) {
			tb_get_tbp(tbt);
		}
		else {
			if (tbp_dynamic) {
				list_del_init(&tbt->list);
			}
		}
	}
	else {
		//static tbt
		mbp = tb_get_mbp(align_addr, &bank_num);
		if(!mbp) {
			goto out;
		}
		if (!state->mem.tbt[bank_num]) {
			if (!tbp_dynamic) {
				state->mem.tbp[bank_num] = mmap(NULL, state->mem.rom_size[bank_num] / sizeof(ARMword) * TB_INSN_LEN_MAX + state->mem.rom_size[bank_num] / TB_LEN * op_return.len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
				if (state->mem.tbp[bank_num] == MAP_FAILED) {

⌨️ 快捷键说明

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