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

📄 opcodes.c

📁 这是模拟器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#define DEST_REG		arm->gp_reg [(OPCODE>>12)&0xF]
#define BASE_REG		arm->gp_reg [(OPCODE>>16)&0xF]
#define OP_REG			arm->gp_reg [(OPCODE&0xF)]
#define SHFT_AMO_REG	arm->gp_reg [(OPCODE>>8)&0xF]

#define HDT_CALC_IMM_OFFSET	((OPCODE&0xF00)>>4)|(OPCODE&0xF)

__inline u32 DP_IMM_OPERAND (void)
{		
	u32 value = OPCODE;

	__asm {
		mov ecx, value
		mov bl, cl
		and ecx, 0xF00
		shr ecx, 7		
		ror ebx, cl
		mov value, ebx
	}
		
	return value;
}

//-------------Barrel-Shifter ("evil"(tm))----------------------------------------------

#define IMM_SHIFT	((OPCODE>>7)&0x1F)
#define REG_SHIFT	(SHFT_AMO_REG&0xFF)

__inline DP_REG_OPERAND (u32 shift)
{
	u32 shift_amount = shift;
	u32 op = OP_REG;
	switch ((OPCODE>>5)&0x3)	
	{							
		case 0: return (op << shift_amount);	
		case 1: if (shift_amount) return (op >> shift_amount); else return 0;
		case 2: 
			if (shift_amount) {
				if (op&0x80000000)
					return ((0xFFFFFFFF<<(32-shift_amount))|(op>>shift_amount)); 
				else
					return (op >> shift_amount);
			}
			else {
				if (op&0x80000000) return 0xFFFFFFFF; else return 0;
			}
		case 3: 
			if (shift_amount) {
				return (op << (32-shift_amount)|(op>>shift_amount));
			}
			else
				return ((op>>1)|(CFLAG<<31));
	}
	return 0;
}

__inline DP_REG_OPERAND_C (u32 shift)
{
	u32 op = OP_REG;

	switch ((OPCODE>>5)&0x3)	
	{							
		case 0:
			CFLAG = (op&(0x80000000>>(shift-1))) ? (1):(0);
			return (op << shift);
		case 1: 
			if (shift) {
				CFLAG = (op&(1<<(shift-1))) ? (1):(0);
				return (op >> shift);
			} 
			else {
				CFLAG = op>>31; return 0;
			}
		case 2: 
			if (shift) {
				CFLAG = (op&(1<<(shift-1))) ? (1):(0);
				if (op&0x80000000)
					return ((0xFFFFFFFF<<(32-shift))|(op>>shift)); 
				else
					return (op >> shift);
			} else {
				CFLAG = op>>31;
				if (CFLAG) return 0xFFFFFFFF; else return 0;
			}
		case 3: 
			if (shift) {
				CFLAG = (op&(1<<(shift-1))) ? (1):(0);
				return (op << (32-shift)|(op>>shift));
			}
			else {
				if (CFLAG) {
					CFLAG = op&0x1;
					return ((op>>1)|0x80000000);
				}
				else {
					CFLAG = op&0x1;	
					return (op>>1);
				}
			}
	}
	return 0;
}

//--------------------------------------------------------------------------------------

//---------------------Flag macros------------------------------------------------------

#define TOPBIT 0x80000000

// Arithmetic Data Processing 
__inline void SET_SUB_FLAGS (u32 a, u32 b, u32 c)
{
	if (c) ZFLAG = 0; else ZFLAG = 1;
	NFLAG = ((c&TOPBIT)>>31); 
	CFLAG = ((a&(~b))|(a&(~c))|((~b)&(~c)))>>31;
	//VFLAG = ((a&~(b|c))|((~a)&b&c))>>31;
	//VFLAG = ((a&(~b)&(~c))|((~a)&b&c))>>31;

	VFLAG = ((a&~(b|c))|((b&c)&~a))>>31;
}

__inline void SET_ADD_FLAGS (u32 a, u32 b, u32 c)
{
	if (c) ZFLAG = 0; else ZFLAG = 1;
	NFLAG = (c>>31); 
	CFLAG = ((a&b)|(a&(~c))|(b&(~c)))>>31;
	VFLAG = ((a&b&(~c))|((~a)&(~b)&c))>>31;
}

// Logical Data Processing (value is supposed to be 32 bit)
#define SET_DP_LOG_FLAGS(value)\
	if (value) ZFLAG = 0; else ZFLAG = 1;\
	NFLAG = (value>>31)

//--------------------------------------------------------------------------------------

/***********************************************************************************************/
/*									Opcodes													   */
/***********************************************************************************************/

int unknown_opcode(void ) 
{
	return 1;
}

int ins_bpl (void)
{
	arm->gp_reg [15] += ((OPCODE&0x7FFFFF)<<2);
	fill_instruction_pipe(); return 3;
}

int ins_bmi (void)
{
	arm->gp_reg [15] += (((OPCODE&0xFFFFFF)<<2)-0x4000000);
	fill_instruction_pipe(); return 3;
}

int ins_blpl (void)
{
	arm->gp_reg [14] = arm->gp_reg [15] - 4;
	arm->gp_reg [15] += ((OPCODE&0xFFFFFF)<<2);
	fill_instruction_pipe(); return 3;
}

int ins_blmi (void)
{
	arm->gp_reg [14] = arm->gp_reg [15] - 4;
	arm->gp_reg [15] += (((OPCODE&0xFFFFFF)<<2)-0x4000000);
	fill_instruction_pipe(); return 3;
}

int ins_bx (void)
{
	arm->gp_reg [15] = OP_REG & ~0x1;
	if (OP_REG&0x1) {
		CPSR |= T_BIT;
		arm->state = OP_REG & 0x1;
		exec = thumb_exec;
		tfill_instruction_pipe();
	}
	else {
		CPSR &= ~T_BIT;
		exec = arm_exec;
		fill_instruction_pipe();
	}
	return 3;
}

int ins_mul(void)
{
	BASE_REG = OP_REG * SHFT_AMO_REG;
	advance_instruction_pipe(); return 4;
}

int ins_muls(void)
{
	BASE_REG = OP_REG * SHFT_AMO_REG;
	SET_DP_LOG_FLAGS(BASE_REG);
	advance_instruction_pipe(); return 4;
}

int ins_mla(void)
{
	BASE_REG = (OP_REG * SHFT_AMO_REG) + DEST_REG;
	advance_instruction_pipe();	return 4;
}

int ins_mlas(void)
{
	BASE_REG = (OP_REG * SHFT_AMO_REG) + DEST_REG;
	SET_DP_LOG_FLAGS(BASE_REG);
	advance_instruction_pipe();	return 4;
}

int ins_mull(void)
{
	INT64 temp64 = (INT64)OP_REG;

	temp64 *= ((s32)SHFT_AMO_REG);

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32) & 0xFFFFFFFF); 

	advance_instruction_pipe();	return 4;
}

int ins_mulls(void)
{
	INT64 temp64 = (INT64)OP_REG;

	temp64 *= ((s32)SHFT_AMO_REG);

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32) & 0xFFFFFFFF); 

	if (!temp64)					ZFLAG = 1; else ZFLAG = 0;
	if (temp64&0x8000000000000000)	NFLAG = 1; else NFLAG = 0;

	advance_instruction_pipe();	return 4;
}

int ins_mull_unsigned(void)
{
	UINT64 temp64 = (UINT64)OP_REG;

	temp64 *= SHFT_AMO_REG;

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32) & 0xFFFFFFFF); 

	advance_instruction_pipe();	return 4;
}

int ins_mulls_unsigned(void)
{
	UINT64 temp64 = (UINT64)OP_REG;

	temp64 *= SHFT_AMO_REG;

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32)&0xFFFFFFFF); 

	if (!temp64)					ZFLAG = 1; else ZFLAG = 0;
	if (temp64&0x8000000000000000)	NFLAG = 1; else NFLAG = 0;

	advance_instruction_pipe();	return 4;
}

int ins_mlal(void)
{
	INT64 temp64 = (INT64)OP_REG;
	INT64 operand = (INT64)DEST_REG;
	operand |= ((INT64)BASE_REG)<<32;
		
	temp64 = (temp64 * ((INT64)SHFT_AMO_REG)) + operand;

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32)&0xFFFFFFFF); 
	
	advance_instruction_pipe();	return 4;
}

int ins_mlals(void)
{
	INT64 temp64 = (INT64)OP_REG;
	INT64 operand = (INT64)DEST_REG;
	operand |= ((INT64)BASE_REG)<<32;
		
	temp64 = (temp64 * ((INT64)SHFT_AMO_REG)) + operand;

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32)&0xFFFFFFFF); 

	if (!temp64)					ZFLAG = 1; else ZFLAG = 0;
	if (temp64&0x8000000000000000)	NFLAG = 1; else ZFLAG = 0;

	advance_instruction_pipe();	return 4;
}

int ins_mlal_unsigned(void)
{
	UINT64 temp64 = (UINT64)OP_REG;
	UINT64 operand = (UINT64)DEST_REG;
	operand |= ((UINT64)BASE_REG)<<32;

	temp64 = (temp64 * ((UINT64)SHFT_AMO_REG)) + operand;

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32)&0xFFFFFFFF); 
	
	advance_instruction_pipe();	return 4;
}

int ins_mlals_unsigned(void)
{
	UINT64 temp64 = (UINT64)OP_REG;
	UINT64 operand = (UINT64)DEST_REG;
	operand |= ((UINT64)BASE_REG)<<32;

	temp64 = (temp64 * ((UINT64)SHFT_AMO_REG)) + operand;

	DEST_REG = (u32)(temp64 & 0xFFFFFFFF);
	BASE_REG = (u32)((temp64>>32)&0xFFFFFFFF); 

	if (!temp64)					ZFLAG = 1; else ZFLAG = 0;
	if (temp64&0x8000000000000000)	NFLAG = 1; else NFLAG = 0;

	advance_instruction_pipe();	return 4;
}

/*-------------------------------------------------------------
				Data Processing
--------------------------------------------------------------*/

// AND

int ins_and(void)
{
	DEST_REG = BASE_REG & DP_REG_OPERAND(IMM_SHIFT);
	
	advance_instruction_pipe(); return 1;
}

int ins_and_reg(void)
{
	DEST_REG = BASE_REG & DP_REG_OPERAND(REG_SHIFT);
	
	advance_instruction_pipe(); return 2;
}

int ins_and_imm(void)
{
	DEST_REG = BASE_REG & DP_IMM_OPERAND();
	
	advance_instruction_pipe(); return 1;
}

int ins_ands(void)
{
	DEST_REG = BASE_REG & DP_REG_OPERAND_C(IMM_SHIFT);
	SET_DP_LOG_FLAGS(DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

int ins_ands_reg (void)
{
	DEST_REG = BASE_REG & DP_REG_OPERAND_C(REG_SHIFT);
	SET_DP_LOG_FLAGS(DEST_REG);
	
	advance_instruction_pipe(); return 2;
}
int ins_ands_imm(void)
{
	DEST_REG = BASE_REG & DP_IMM_OPERAND();
	SET_DP_LOG_FLAGS(DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

//---------------------------------------------------------------

// EOR

int ins_eor(void)
{
	DEST_REG = BASE_REG ^ DP_REG_OPERAND(IMM_SHIFT);
	
	advance_instruction_pipe();	return 1;
}

int ins_eor_reg (void)
{
	DEST_REG = BASE_REG ^ DP_REG_OPERAND(REG_SHIFT);
	
	advance_instruction_pipe(); return 2;
}

int ins_eor_imm(void)
{
	DEST_REG = BASE_REG ^ DP_IMM_OPERAND();
	
	advance_instruction_pipe(); return 1;
}

int ins_eors(void)
{
	DEST_REG = BASE_REG ^ DP_REG_OPERAND_C(IMM_SHIFT);
	SET_DP_LOG_FLAGS(DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

int ins_eors_reg (void)
{
	DEST_REG = BASE_REG ^ DP_REG_OPERAND_C(REG_SHIFT);
	SET_DP_LOG_FLAGS(DEST_REG);
	
	advance_instruction_pipe(); return 2;
}

int ins_eors_imm(void)
{
	DEST_REG = BASE_REG ^ DP_IMM_OPERAND();
	SET_DP_LOG_FLAGS(DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

//---------------------------------------------------------------

// SUB

int ins_sub(void)	
{
	DEST_REG = BASE_REG - DP_REG_OPERAND(IMM_SHIFT);
	
	advance_instruction_pipe(); return 1;
}

int ins_sub_reg (void)
{
	DEST_REG = BASE_REG - DP_REG_OPERAND(REG_SHIFT);
	
	advance_instruction_pipe(); return 2;
}

int ins_sub_imm(void)
{
	DEST_REG = BASE_REG - DP_IMM_OPERAND();
	
	advance_instruction_pipe(); return 1;
}

int ins_subs(void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_REG_OPERAND(IMM_SHIFT);
	DEST_REG = op1 - op2;
	SET_SUB_FLAGS(op1, op2, DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

int ins_subs_reg (void) 
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_REG_OPERAND(REG_SHIFT);
	DEST_REG = op1 - op2;
	SET_SUB_FLAGS(op1, op2, DEST_REG);
	
	advance_instruction_pipe(); return 2;
}

int ins_subs_imm(void)
{
	u32 op1, op2;
	
	op1 = BASE_REG;
	op2 = DP_IMM_OPERAND();

	DEST_REG = op1 - op2;	
	SET_SUB_FLAGS(op1, op2, DEST_REG);
	
	advance_instruction_pipe();	return 1;
}

//---------------------------------------------------------------

// RSB

int ins_rsb(void)	
{
	DEST_REG = DP_REG_OPERAND(IMM_SHIFT) - BASE_REG;
	
	advance_instruction_pipe();	return 1;
}

int ins_rsb_reg (void)
{
	DEST_REG = DP_REG_OPERAND(REG_SHIFT) - BASE_REG;
	
	advance_instruction_pipe(); return 2;
}

int ins_rsb_imm(void)	
{
	DEST_REG = DP_IMM_OPERAND() - BASE_REG;
	
	advance_instruction_pipe(); return 1;
}

int ins_rsbs(void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_REG_OPERAND(IMM_SHIFT);
	DEST_REG = op2 - op1;
	SET_SUB_FLAGS(op2, op1, DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

int ins_rsbs_reg (void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_REG_OPERAND(REG_SHIFT);
	DEST_REG = op2 - op1;
	SET_SUB_FLAGS(op2, op1, DEST_REG);
	
	advance_instruction_pipe(); return 2;
}

int ins_rsbs_imm(void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_IMM_OPERAND();
	DEST_REG = op2 - op1;
	SET_SUB_FLAGS(op2, op1, DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

//---------------------------------------------------------------

// ADD

int ins_add(void)
{
	DEST_REG = BASE_REG + DP_REG_OPERAND(IMM_SHIFT);
	
	advance_instruction_pipe(); return 1;
}

int ins_add_reg(void)
{
	DEST_REG = BASE_REG + DP_REG_OPERAND(REG_SHIFT);
	
	advance_instruction_pipe(); return 2;
}

int ins_add_imm(void)
{
	DEST_REG = BASE_REG + DP_IMM_OPERAND();
	
	advance_instruction_pipe();	return 1;
}

int ins_adds(void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_REG_OPERAND(IMM_SHIFT);
	DEST_REG = op1 + op2;
	SET_ADD_FLAGS(op1, op2, DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

int ins_adds_reg (void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_REG_OPERAND(REG_SHIFT);
	DEST_REG = op1 + op2;
	SET_ADD_FLAGS(op1, op2, DEST_REG);
	
	advance_instruction_pipe(); return 2;
}

int ins_adds_imm(void)
{
	u32 op1 = BASE_REG;
	u32 op2 = DP_IMM_OPERAND();
	DEST_REG = op1 + op2;
	SET_ADD_FLAGS(op1, op2, DEST_REG);
	
	advance_instruction_pipe(); return 1;
}

⌨️ 快捷键说明

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