📄 armemu.c
字号:
}
else if (MULDESTReg != 15)
state->Reg[MULDESTReg] =
state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
else
UNDEF_MULPCDest;
for (dest = 0, temp = 0; dest < 32; dest++)
if (rhs & (1L << dest))
temp = dest;
/* Mult takes this many/2 I cycles. */
ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
}
else
{
rhs = DPRegRHS;
dest = LHS ^ rhs;
WRITEDEST (dest);
}
break;
case 0x03: /* EORS reg and MLAS */
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
/* LDR register offset, write-back, down, post-indexed. */
LHPOSTDOWN ();
/* Fall through to rest of the decoding. */
#endif
if (BITS (4, 7) == 9)
{
/* MLAS */
rhs = state->Reg[MULRHSReg];
if (MULLHSReg == MULDESTReg)
{
UNDEF_MULDestEQOp1;
dest = state->Reg[MULACCReg];
ARMul_NegZero (state, dest);
state->Reg[MULDESTReg] = dest;
}
else if (MULDESTReg != 15)
{
dest =
state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
ARMul_NegZero (state, dest);
state->Reg[MULDESTReg] = dest;
}
else
UNDEF_MULPCDest;
for (dest = 0, temp = 0; dest < 32; dest++)
if (rhs & (1L << dest))
temp = dest;
/* Mult takes this many/2 I cycles. */
ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
}
else
{
/* EORS Reg. */
rhs = DPSRegRHS;
dest = LHS ^ rhs;
WRITESDEST (dest);
}
break;
case 0x04: /* SUB reg */
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
/* STRH immediate offset, no write-back, down, post indexed. */
SHDOWNWB ();
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 0x05: /* SUBS reg */
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
/* LDR immediate offset, no write-back, down, post indexed. */
LHPOSTDOWN ();
/* Fall through to the rest of the instruction decoding. */
#endif
lhs = LHS;
rhs = DPRegRHS;
dest = lhs - rhs;
if ((lhs >= rhs) || ((rhs | lhs) >> 31))
{
ARMul_SubCarry (state, lhs, rhs, dest);
ARMul_SubOverflow (state, lhs, rhs, dest);
}
else
{
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x06: /* RSB reg */
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
/* STRH immediate offset, write-back, down, post indexed. */
SHDOWNWB ();
break;
}
#endif
rhs = DPRegRHS;
dest = rhs - LHS;
WRITEDEST (dest);
break;
case 0x07: /* RSBS reg */
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
/* LDR immediate offset, write-back, down, post indexed. */
LHPOSTDOWN ();
/* Fall through to remainder of instruction decoding. */
#endif
lhs = LHS;
rhs = DPRegRHS;
dest = rhs - lhs;
if ((rhs >= lhs) || ((rhs | lhs) >> 31))
{
ARMul_SubCarry (state, rhs, lhs, dest);
ARMul_SubOverflow (state, rhs, lhs, dest);
}
else
{
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x08: /* ADD reg */
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
/* STRH register offset, no write-back, up, post indexed. */
SHUPWB ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
#ifdef MODET
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32 = 64 */
ARMul_Icycles (state,
Multiply64 (state, instr, LUNSIGNED,
LDEFAULT), 0L);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS + rhs;
WRITEDEST (dest);
break;
case 0x09: /* ADDS reg */
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
/* LDR register offset, no write-back, up, post indexed. */
LHPOSTUP ();
/* Fall through to remaining instruction decoding. */
#endif
#ifdef MODET
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
Multiply64 (state, instr, LUNSIGNED, LSCC),
0L);
break;
}
#endif
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;
}
WRITESDEST (dest);
break;
case 0x0a: /* ADC reg */
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
/* STRH register offset, write-back, up, post-indexed. */
SHUPWB ();
break;
}
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
MultiplyAdd64 (state, instr, LUNSIGNED,
LDEFAULT), 0L);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS + rhs + CFLAG;
WRITEDEST (dest);
break;
case 0x0b: /* ADCS reg */
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
/* LDR register offset, write-back, up, post indexed. */
LHPOSTUP ();
/* Fall through to remaining instruction decoding. */
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
MultiplyAdd64 (state, instr, LUNSIGNED,
LSCC), 0L);
break;
}
#endif
lhs = LHS;
rhs = DPRegRHS;
dest = lhs + rhs + CFLAG;
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;
}
WRITESDEST (dest);
break;
case 0x0c: /* SBC reg */
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
/* STRH immediate offset, no write-back, up post indexed. */
SHUPWB ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
Multiply64 (state, instr, LSIGNED, LDEFAULT),
0L);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS - rhs - !CFLAG;
WRITEDEST (dest);
break;
case 0x0d: /* SBCS reg */
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
/* LDR immediate offset, no write-back, up, post indexed. */
LHPOSTUP ();
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
Multiply64 (state, instr, LSIGNED, LSCC),
0L);
break;
}
#endif
lhs = LHS;
rhs = DPRegRHS;
dest = lhs - rhs - !CFLAG;
if ((lhs >= rhs) || ((rhs | lhs) >> 31))
{
ARMul_SubCarry (state, lhs, rhs, dest);
ARMul_SubOverflow (state, lhs, rhs, dest);
}
else
{
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x0e: /* RSC reg */
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
/* STRH immediate offset, write-back, up, post indexed. */
SHUPWB ();
break;
}
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
MultiplyAdd64 (state, instr, LSIGNED,
LDEFAULT), 0L);
break;
}
#endif
rhs = DPRegRHS;
dest = rhs - LHS - !CFLAG;
WRITEDEST (dest);
break;
case 0x0f: /* RSCS reg */
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
/* LDR immediate offset, write-back, up, post indexed. */
LHPOSTUP ();
/* Fall through to remaining instruction decoding. */
if (BITS (4, 7) == 0x9)
{
/* MULL */
/* 32x32=64 */
ARMul_Icycles (state,
MultiplyAdd64 (state, instr, LSIGNED, LSCC),
0L);
break;
}
#endif
lhs = LHS;
rhs = DPRegRHS;
dest = rhs - lhs - !CFLAG;
if ((rhs >= lhs) || ((rhs | lhs) >> 31))
{
ARMul_SubCarry (state, rhs, lhs, dest);
ARMul_SubOverflow (state, rhs, lhs, dest);
}
else
{
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x10: /* TST reg and MRS CPSR and SWP word. */
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1)
{
/* ElSegundo SMLAxy 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;
op1 *= op2;
if (AddOverflow (op1, Rn, op1 + Rn))
SETS;
state->Reg[BITS (16, 19)] = op1 + Rn;
break;
}
if (BITS (4, 11) == 5)
{
/* ElSegundo QADD insn. */
ARMword op1 = state->Reg[BITS (0, 3)];
ARMword op2 = state->Reg[BITS (16, 19)];
ARMword result = op1 + op2;
if (AddOverflow (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, 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_LoadWordN (state, temp);
(void) ARMul_LoadWordN (state, temp);
}
else
#endif
dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
if (temp & 3)
DEST = ARMul_Align (state, temp, dest);
else
DEST = dest;
if (state->abortSig || state->Aborted)
TAKEABORT;
}
else if ((BITS (0, 11) == 0) && (LHSReg == 15))
{ /* MRS CPSR */
UNDEF_MRSPC;
DEST = ECC | EINT | EMODE;
}
else
{
UNDEF_Test;
}
break;
case 0x11: /* TSTP reg */
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -