📄 opcodes.c
字号:
#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 + -