📄 armemu.c
字号:
/* LDR register offset, no write-back, down, pre indexed. */
LHPREDOWN ();
/* Continue with remaining instruction decode. */
#endif
if (DESTReg == 15)
{
/* TSTP reg */
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS & rhs;
SETR15PSR (temp);
#endif
}
else
{
/* TST reg */
rhs = DPSRegRHS;
dest = LHS & rhs;
ARMul_NegZero (state, dest);
}
break;
case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
if (state->is_v5)
{
if (BITS (4, 7) == 3)
{
/* BLX(2) */
ARMword temp;
if (TFLAG)
temp = (pc + 2) | 1;
else
temp = pc + 4;
WriteR15Branch (state, state->Reg[RHSReg]);
state->Reg[14] = temp;
break;
}
}
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1
&& (BIT (5) == 0 || BITS (12, 15) == 0))
{
/* ElSegundo SMLAWy/SMULWy insn. */
unsigned long long op1 = state->Reg[BITS (0, 3)];
unsigned long long op2 = state->Reg[BITS (8, 11)];
unsigned long long result;
if (BIT (6))
op2 >>= 16;
if (op1 & 0x80000000)
op1 -= 1ULL << 32;
op2 &= 0xFFFF;
if (op2 & 0x8000)
op2 -= 65536;
result = (op1 * op2) >> 16;
if (BIT (5) == 0)
{
ARMword Rn = state->Reg[BITS (12, 15)];
if (AddOverflow (result, Rn, result + Rn))
SETS;
result += Rn;
}
state->Reg[BITS (16, 19)] = result;
break;
}
if (BITS (4, 11) == 5)
{
/* ElSegundo QSUB insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
ARMword op2 = state->Reg[BITS (16, 19)];
ARMword result = op1 - op2;
if (SubOverflow (op1, op2, result))
{
result = POS (result) ? 0x80000000 : 0x7fffffff;
SETS;
}
state->Reg[BITS (12, 15)] = result;
break;
}
}
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
/* STRH register offset, write-back, down, pre indexed. */
SHPREDOWNWB ();
break;
}
if (BITS (4, 27) == 0x12FFF1)
{
/* BX */
WriteR15Branch (state, state->Reg[RHSReg]);
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
if (state->is_v5)
{
if (BITS (4, 7) == 0x7)
{
ARMword value;
extern int SWI_vector_installed;
/* Hardware is allowed to optionally override this
instruction and treat it as a breakpoint. Since
this is a simulator not hardware, we take the position
that if a SWI vector was not installed, then an Abort
vector was probably not installed either, and so
normally this instruction would be ignored, even if an
Abort is generated. This is a bad thing, since GDB
uses this instruction for its breakpoints (at least in
Thumb mode it does). So intercept the instruction here
and generate a breakpoint SWI instead. */
if (!SWI_vector_installed)
ARMul_OSHandleSWI (state, SWI_Breakpoint);
else
{
/* BKPT - normally this will cause an abort, but on the
XScale we must check the DCSR. */
XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT,
pc);
if (!XScale_debug_moe
(state, ARMul_CP14_R10_MOE_BT))
break;
}
/* Force the next instruction to be refetched. */
state->NextInstr = RESUME;
break;
}
}
if (DESTReg == 15)
{
/* MSR reg to CPSR. */
UNDEF_MSRPC;
temp = DPRegRHS;
#ifdef MODET
/* Don't allow TBIT to be set by MSR. */
temp &= ~TBIT;
#endif
ARMul_FixCPSR (state, instr, temp);
}
else
UNDEF_Test;
break;
case 0x13: /* TEQP reg */
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
/* LDR register offset, write-back, down, pre indexed. */
LHPREDOWNWB ();
/* Continue with remaining instruction decode. */
#endif
if (DESTReg == 15)
{
/* TEQP reg */
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS ^ rhs;
SETR15PSR (temp);
#endif
}
else
{
/* TEQ Reg. */
rhs = DPSRegRHS;
dest = LHS ^ rhs;
ARMul_NegZero (state, dest);
}
break;
case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1)
{
/* ElSegundo SMLALxy insn. */
unsigned long long op1 = state->Reg[BITS (0, 3)];
unsigned long long op2 = state->Reg[BITS (8, 11)];
unsigned long long dest;
unsigned long long result;
if (BIT (5))
op1 >>= 16;
if (BIT (6))
op2 >>= 16;
op1 &= 0xFFFF;
if (op1 & 0x8000)
op1 -= 65536;
op2 &= 0xFFFF;
if (op2 & 0x8000)
op2 -= 65536;
dest =
(unsigned long long) state->Reg[BITS (16, 19)] << 32;
dest |= state->Reg[BITS (12, 15)];
dest += op1 * op2;
state->Reg[BITS (12, 15)] = dest;
state->Reg[BITS (16, 19)] = dest >> 32;
break;
}
if (BITS (4, 11) == 5)
{
/* ElSegundo QDADD insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
ARMword op2 = state->Reg[BITS (16, 19)];
ARMword op2d = op2 + op2;
ARMword result;
if (AddOverflow (op2, op2, op2d))
{
SETS;
op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
}
result = op1 + op2d;
if (AddOverflow (op1, op2d, result))
{
SETS;
result = POS (result) ? 0x80000000 : 0x7fffffff;
}
state->Reg[BITS (12, 15)] = result;
break;
}
}
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
/* STRH immediate offset, no write-back, down, pre indexed. */
SHPREDOWN ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
if (BITS (4, 11) == 9)
{
/* SWP */
UNDEF_SWPPC;
temp = LHS;
BUSUSEDINCPCS;
#ifndef MODE32
if (VECTORACCESS (temp) || ADDREXCEPT (temp))
{
INTERNALABORT (temp);
(void) ARMul_LoadByte (state, temp);
(void) ARMul_LoadByte (state, temp);
}
else
#endif
DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
if (state->abortSig || state->Aborted)
TAKEABORT;
}
else if ((BITS (0, 11) == 0) && (LHSReg == 15))
{
/* MRS SPSR */
UNDEF_MRSPC;
DEST = GETSPSR (state->Bank);
}
else
UNDEF_Test;
break;
case 0x15: /* CMPP reg. */
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
/* LDR immediate offset, no write-back, down, pre indexed. */
LHPREDOWN ();
/* Continue with remaining instruction decode. */
#endif
if (DESTReg == 15)
{
/* CMPP reg. */
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS - rhs;
SETR15PSR (temp);
#endif
}
else
{
/* CMP reg. */
lhs = LHS;
rhs = DPRegRHS;
dest = lhs - rhs;
ARMul_NegZero (state, dest);
if ((lhs >= rhs) || ((rhs | lhs) >> 31))
{
ARMul_SubCarry (state, lhs, rhs, dest);
ARMul_SubOverflow (state, lhs, rhs, dest);
}
else
{
CLEARC;
CLEARV;
}
}
break;
case 0x16: /* CMN reg and MSR reg to SPSR */
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
{
/* ElSegundo SMULxy insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
ARMword op2 = state->Reg[BITS (8, 11)];
ARMword Rn = state->Reg[BITS (12, 15)];
if (BIT (5))
op1 >>= 16;
if (BIT (6))
op2 >>= 16;
op1 &= 0xFFFF;
op2 &= 0xFFFF;
if (op1 & 0x8000)
op1 -= 65536;
if (op2 & 0x8000)
op2 -= 65536;
state->Reg[BITS (16, 19)] = op1 * op2;
break;
}
if (BITS (4, 11) == 5)
{
/* ElSegundo QDSUB insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
ARMword op2 = state->Reg[BITS (16, 19)];
ARMword op2d = op2 + op2;
ARMword result;
if (AddOverflow (op2, op2, op2d))
{
SETS;
op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
}
result = op1 - op2d;
if (SubOverflow (op1, op2d, result))
{
SETS;
result = POS (result) ? 0x80000000 : 0x7fffffff;
}
state->Reg[BITS (12, 15)] = result;
break;
}
}
if (state->is_v5)
{
if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
{
/* ARM5 CLZ insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
int result = 32;
if (op1)
for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
result++;
state->Reg[BITS (12, 15)] = result;
break;
}
}
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
/* STRH immediate offset, write-back, down, pre indexed. */
SHPREDOWNWB ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
if (DESTReg == 15)
{
/* MSR */
UNDEF_MSRPC;
ARMul_FixSPSR (state, instr, DPRegRHS);
}
else
{
UNDEF_Test;
}
break;
case 0x17: /* CMNP reg */
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
/* LDR immediate offset, write-back, down, pre indexed. */
LHPREDOWNWB ();
/* Continue with remaining instruction decoding. */
#endif
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS + rhs;
SETR15PSR (temp);
#endif
break;
}
else
{
/* CMN reg. */
lhs = LHS;
rhs = DPRegRHS;
dest = lhs + rhs;
ASSIGNZ (dest == 0);
if ((lhs | rhs) >> 30)
{
/* Possible C,V,N to set. */
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
}
break;
case 0x18: /* ORR reg */
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
/* STRH register offset, no write-back, up, pre indexed. */
SHPREUP ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS | rhs;
WRITEDEST (dest);
break;
case 0x19: /* ORRS reg */
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
/* LDR register offset, no write-back, up, pre indexed. */
LHPREUP ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -