#include "armdefs.h"
#include "armemu.h"
#include "armos.h"
static ARMword GetDPRegRHS (ARMul_State *, ARMword);
static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
static void WriteR15 (ARMul_State *, ARMword);
static void WriteSR15 (ARMul_State *, ARMword);
static void WriteR15Branch (ARMul_State *, ARMword);
static ARMword GetLSRegRHS (ARMul_State *, ARMword);
static ARMword GetLS7RHS (ARMul_State *, ARMword);
static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
static void Handle_Load_Double (ARMul_State *, ARMword);
static void Handle_Store_Double (ARMul_State *, ARMword);
#define LUNSIGNED (0)
#define LSIGNED (1)
#define LDEFAULT (0)
#define LSCC (1)
#ifdef NEED_UI_LOOP_HOOK
#define UI_LOOP_POLL_INTERVAL 0x32000
static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
extern int (*ui_loop_hook) (int);
#endif
extern int stop_simulator;
#define SHDOWNWB() \
lhs = LHS ; \
if (StoreHalfWord (state, instr, lhs)) \
LSBase = lhs - GetLS7RHS (state, instr);
#define SHUPWB() \
lhs = LHS ; \
if (StoreHalfWord (state, instr, lhs)) \
LSBase = lhs + GetLS7RHS (state, instr);
#define SHPREDOWN() \
(void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
#define SHPREDOWNWB() \
temp = LHS - GetLS7RHS (state, instr); \
if (StoreHalfWord (state, instr, temp)) \
LSBase = temp;
#define SHPREUP() \
(void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
#define SHPREUPWB() \
temp = LHS + GetLS7RHS (state, instr); \
if (StoreHalfWord (state, instr, temp)) \
LSBase = temp;
#define LHPOSTDOWN() \
{ \
int done = 1; \
lhs = LHS; \
temp = lhs - GetLS7RHS (state, instr); \
\
switch (BITS (5, 6)) \
{ \
case 1: \
if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
LSBase = temp; \
break; \
case 2: \
if (LoadByte (state, instr, lhs, LSIGNED)) \
LSBase = temp; \
break; \
case 3: \
if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
LSBase = temp; \
break; \
case 0: \
default: \
done = 0; \
break; \
} \
if (done) \
break; \
}
#define LHPOSTUP() \
{ \
int done = 1; \
lhs = LHS; \
temp = lhs + GetLS7RHS (state, instr); \
\
switch (BITS (5, 6)) \
{ \
case 1: \
if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
LSBase = temp; \
break; \
case 2: \
if (LoadByte (state, instr, lhs, LSIGNED)) \
LSBase = temp; \
break; \
case 3: \
if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
LSBase = temp; \
break; \
case 0: \
default: \
done = 0; \
break; \
} \
if (done) \
break; \
}
#define LHPREDOWN() \
{ \
int done = 1; \
\
temp = LHS - GetLS7RHS (state, instr); \
switch (BITS (5, 6)) \
{ \
case 1: \
(void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
break; \
case 2: \
(void) LoadByte (state, instr, temp, LSIGNED); \
break; \
case 3: \
(void) LoadHalfWord (state, instr, temp, LSIGNED); \
break; \
case 0: \
\
default: \
done = 0; \
break; \
} \
if (done) \
break; \
}
#define LHPREDOWNWB() \
{ \
int done = 1; \
\
temp = LHS - GetLS7RHS (state, instr); \
switch (BITS (5, 6)) \
{ \
case 1: \
if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
LSBase = temp; \
break; \
case 2: \
if (LoadByte (state, instr, temp, LSIGNED)) \
LSBase = temp; \
break; \
case 3: \
if (LoadHalfWord (state, instr, temp, LSIGNED)) \
LSBase = temp; \
break; \
case 0: \
\
default: \
done = 0; \
break; \
} \
if (done) \
break; \
}
#define LHPREUP() \
{ \
int done = 1; \
\
temp = LHS + GetLS7RHS (state, instr); \
switch (BITS (5, 6)) \
{ \
case 1: \
(void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
break; \
case 2: \
(void) LoadByte (state, instr, temp, LSIGNED); \
break; \
case 3: \
(void) LoadHalfWord (state, instr, temp, LSIGNED); \
break; \
case 0: \
\
default: \
done = 0; \
break; \
} \
if (done) \
break; \
}
#define LHPREUPWB() \
{ \
int done = 1; \
\
temp = LHS + GetLS7RHS (state, instr); \
switch (BITS (5, 6)) \
{ \
case 1: \
if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
LSBase = temp; \
break; \
case 2: \
if (LoadByte (state, instr, temp, LSIGNED)) \
LSBase = temp; \
break; \
case 3: \
if (LoadHalfWord (state, instr, temp, LSIGNED)) \
LSBase = temp; \
break; \
case 0: \
\
default: \
done = 0; \
break; \
} \
if (done) \
break; \
}
ARMword isize;
ARMword
#ifdef MODE32
ARMul_Emulate32 (ARMul_State * state)
#else
ARMul_Emulate26 (ARMul_State * state)
#endif
{
ARMword instr;
ARMword dest = 0;
ARMword temp;
ARMword pc = 0;
ARMword lhs;
ARMword rhs;
ARMword decoded = 0;
ARMword loaded = 0;
if (state->NextInstr < PRIMEPIPE)
{
decoded = state->decoded;
loaded = state->loaded;
pc = state->pc;
}
do
{
isize = INSN_SIZE;
switch (state->NextInstr)
{
case SEQ:
state->Reg[15] += isize;
pc += isize;
instr = decoded;
decoded = loaded;
loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
break;
case NONSEQ:
state->Reg[15] += isize;
pc += isize;
instr = decoded;
decoded = loaded;
loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
NORMALCYCLE;
break;
case PCINCEDSEQ:
pc += isize;
instr = decoded;
decoded = loaded;
loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
NORMALCYCLE;
break;
case PCINCEDNONSEQ:
pc += isize;
instr = decoded;
decoded = loaded;
loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
NORMALCYCLE;
break;
case RESUME:
pc = state->Reg[15];
#ifndef MODE32
pc = pc & R15PCBITS;
#endif
state->Reg[15] = pc + (isize * 2);
state->Aborted = 0;
instr = ARMul_ReLoadInstr (state, pc, isize);
decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
NORMALCYCLE;
break;
default:
pc = state->Reg[15];
#ifndef MODE32
pc = pc & R15PCBITS;
#endif
state->Reg[15] = pc + (isize * 2);
state->Aborted = 0;
instr = ARMul_LoadInstrN (state, pc, isize);
decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
NORMALCYCLE;
break;
}
if (state->EventSet)
ARMul_EnvokeEvent (state);
#if 0
fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
if (instr == 0)
abort ();
#endif
if (state->Exception)
{
if (state->NresetSig == LOW)
{
ARMul_Abort (state, ARMul_ResetV);
break;
}
else if (!state->NfiqSig && !FFLAG)
{
ARMul_Abort (state, ARMul_FIQV);
break;
}
else if (!state->NirqSig && !IFLAG)
{
ARMul_Abort (state, ARMul_IRQV);
break;
}
}
if (state->CallDebug > 0)
{
instr = ARMul_Debug (state, pc, instr);
if (state->Emulate < ONCE)
{
state->NextInstr = RESUME;
break;
}
if (state->Debug)
{
fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
state->Mode);
(void) fgetc (stdin);
}
}
else if (state->Emulate < ONCE)
{
state->NextInstr = RESUME;
break;
}
state->NumInstrs++;
#ifdef MODET
if (TFLAG)
{
ARMword new;
switch (ARMul_ThumbDecode (state, pc, instr, &new))
{
case t_undefined:
ARMul_UndefInstr (state, instr);
goto donext;
case t_branch:
goto donext;
case t_decoded:
instr = new;
break;
default:
break;
}
}
#endif
if ((temp = TOPBITS (28)) == AL)
goto mainswitch;
switch ((int) TOPBITS (28))
{
case AL:
temp = TRUE;
break;
case NV:
if (state->is_v5)
{
if (BITS (25, 27) == 5)
{
ARMword dest;
state->Reg[14] = pc + 4;
dest = pc + 8 + 1;
if (BIT (23))
dest += (NEGBRANCH + (BIT (24) << 1));
else
dest += POSBRANCH + (BIT (24) << 1);
WriteR15Branch (state, dest);
goto donext;
}
else if ((instr & 0xFC70F000) == 0xF450F000)
goto donext;
else
ARMul_UndefInstr (state, instr);
}
temp = FALSE;
break;
case EQ:
temp = ZFLAG;
break;
case NE:
temp = !ZFLAG;
break;
case VS:
temp = VFLAG;
break;
case VC:
temp = !VFLAG;
break;
case MI:
temp = NFLAG;
break;
case PL:
temp = !NFLAG;
break;
case CS:
temp = CFLAG;
break;
case CC:
temp = !CFLAG;
break;
case HI:
temp = (CFLAG && !ZFLAG);
break;
case LS:
temp = (!CFLAG || ZFLAG);
break;
case GE:
temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
break;
case LT:
temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
break;
case GT:
temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
break;
case LE:
temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
break;
}
if (state->is_XScale)
{
ARMword cp14r0;
int ok;
ok = state->CPRead[14] (state, 0, & cp14r0);
if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
{
unsigned long newcycles, nowtime = ARMul_Time (state);
newcycles = nowtime - state->LastTime;
state->LastTime = nowtime;
if (cp14r0 & ARMul_CP14_R0_CCD)
{
if (state->CP14R0_CCD == -1)
state->CP14R0_CCD = newcycles;
else
state->CP14R0_CCD += newcycles;
if (state->CP14R0_CCD >= 64)
{
newcycles = 0;
while (state->CP14R0_CCD >= 64)
state->CP14R0_CCD -= 64, newcycles++;
goto check_PMUintr;
}
}
else
{
ARMword cp14r1;
int do_int = 0;
state->CP14R0_CCD = -1;
check_PMUintr:
cp14r0 |= ARMul_CP14_R0_FLAG2;
(void) state->CPWrite[14] (state, 0, cp14r0);
ok = state->CPRead[14] (state, 1, & cp14r1);
while (ok && newcycles)
{
if (cp14r1 == 0xffffffff)
{
cp14r1 = 0;
do_int = 1;
}
else
cp14r1 ++;
newcycles --;
}
(void) state->CPWrite[14] (state, 1, cp14r1);
if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
{
ARMword temp;
if (state->CPRead[13] (state, 8, & temp)
&& (temp & ARMul_CP13_R8_PMUS))
ARMul_Abort (state, ARMul_FIQV);
else
ARMul_Abort (state, ARMul_IRQV);
}
}
}
}
if (state->is_XScale)
{
if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
|| (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
{
if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
ARMul_OSHandleSWI (state, SWI_Breakpoint);
}
}
if (temp)
{
mainswitch:
if (state->is_XScale)
{
if (BIT (20) == 0 && BITS (25, 27) == 0)
{
if (BITS (4, 7) == 0xD)
{
ARMword temp = GetLS7RHS (state, instr);
ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
ARMword addr = BIT (24) ? temp2 : LHS;
if (BIT (12))
ARMul_UndefInstr (state, instr);
else if (addr & 7)
ARMul_Abort (state, ARMul_DataAbortV);
else
{
int wb = BIT (21) || (! BIT (24));
state->Reg[BITS (12, 15)] =
ARMul_LoadWordN (state, addr);
state->Reg[BITS (12, 15) + 1] =
ARMul_LoadWordN (state, addr + 4);
if (wb)
LSBase = temp2;
}
goto donext;
}
else if (BITS (4, 7) == 0xF)
{
ARMword temp = GetLS7RHS (state, instr);
ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
ARMword addr = BIT (24) ? temp2 : LHS;
if (BIT (12))
ARMul_UndefInstr (state, instr);
else if (addr & 7)
ARMul_Abort (state, ARMul_DataAbortV);
else
{
ARMul_StoreWordN (state, addr,
state->Reg[BITS (12, 15)]);
ARMul_StoreWordN (state, addr + 4,
state->Reg[BITS (12, 15) + 1]);
if (BIT (21)|| ! BIT (24))
LSBase = temp2;
}
goto donext;
}
}
}
switch ((int) BITS (20, 27))
{
case 0x00:
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
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
if (BITS (4, 7) == 9)
{
rhs = state->Reg[MULRHSReg];
if (MULLHSReg == MULDESTReg)
{
UNDEF_MULDestEQOp1;
state->Reg[MULDESTReg] = 0;
}
else if (MULDESTReg != 15)
state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
else
UNDEF_MULPCDest;
for (dest = 0, temp = 0; dest < 32; dest ++)
if (rhs & (1L << dest))
temp = dest;
ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
}
else
{
rhs = DPRegRHS;
dest = LHS & rhs;
WRITEDEST (dest);
}
break;
case 0x01:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPOSTDOWN ();
#endif
if (BITS (4, 7) == 9)
{
rhs = state->Reg[MULRHSReg];
if (MULLHSReg == MULDESTReg)
{
UNDEF_MULDestEQOp1;
state->Reg[MULDESTReg] = 0;
CLEARN;
SETZ;
}
else if (MULDESTReg != 15)
{
dest = state->Reg[MULLHSReg] * rhs;
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;
ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
}
else
{
rhs = DPSRegRHS;
dest = LHS & rhs;
WRITESDEST (dest);
}
break;
case 0x02:
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
SHDOWNWB ();
break;
}
#endif
if (BITS (4, 7) == 9)
{
rhs = state->Reg[MULRHSReg];
if (MULLHSReg == MULDESTReg)
{
UNDEF_MULDestEQOp1;
state->Reg[MULDESTReg] = state->Reg[MULACCReg];
}
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;
ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
}
else
{
rhs = DPRegRHS;
dest = LHS ^ rhs;
WRITEDEST (dest);
}
break;
case 0x03:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPOSTDOWN ();
#endif
if (BITS (4, 7) == 9)
{
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;
ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
}
else
{
rhs = DPSRegRHS;
dest = LHS ^ rhs;
WRITESDEST (dest);
}
break;
case 0x04:
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
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:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPOSTDOWN ();
#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:
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
SHDOWNWB ();
break;
}
#endif
rhs = DPRegRHS;
dest = rhs - LHS;
WRITEDEST (dest);
break;
case 0x07:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPOSTDOWN ();
#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:
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
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)
{
ARMul_Icycles (state,
Multiply64 (state, instr, LUNSIGNED,
LDEFAULT), 0L);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS + rhs;
WRITEDEST (dest);
break;
case 0x09:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPOSTUP ();
#endif
#ifdef MODET
if (BITS (4, 7) == 0x9)
{
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)
{
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x0a:
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
SHUPWB ();
break;
}
if (BITS (4, 7) == 0x9)
{
ARMul_Icycles (state,
MultiplyAdd64 (state, instr, LUNSIGNED,
LDEFAULT), 0L);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS + rhs + CFLAG;
WRITEDEST (dest);
break;
case 0x0b:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPOSTUP ();
if (BITS (4, 7) == 0x9)
{
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)
{
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x0c:
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
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)
{
ARMul_Icycles (state,
Multiply64 (state, instr, LSIGNED, LDEFAULT),
0L);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS - rhs - !CFLAG;
WRITEDEST (dest);
break;
case 0x0d:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPOSTUP ();
if (BITS (4, 7) == 0x9)
{
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:
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
SHUPWB ();
break;
}
if (BITS (4, 7) == 0x9)
{
ARMul_Icycles (state,
MultiplyAdd64 (state, instr, LSIGNED,
LDEFAULT), 0L);
break;
}
#endif
rhs = DPRegRHS;
dest = rhs - LHS - !CFLAG;
WRITEDEST (dest);
break;
case 0x0f:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPOSTUP ();
if (BITS (4, 7) == 0x9)
{
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:
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1)
{
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)
{
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)
{
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)
{
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))
{
UNDEF_MRSPC;
DEST = ECC | EINT | EMODE;
}
else
{
UNDEF_Test;
}
break;
case 0x11:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPREDOWN ();
#endif
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS & rhs;
SETR15PSR (temp);
#endif
}
else
{
rhs = DPSRegRHS;
dest = LHS & rhs;
ARMul_NegZero (state, dest);
}
break;
case 0x12:
if (state->is_v5)
{
if (BITS (4, 7) == 3)
{
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))
{
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)
{
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)
{
SHPREDOWNWB ();
break;
}
if (BITS (4, 27) == 0x12FFF1)
{
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;
if (! SWI_vector_installed)
ARMul_OSHandleSWI (state, SWI_Breakpoint);
else
{
XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
break;
}
state->NextInstr = RESUME;
break;
}
}
if (DESTReg == 15)
{
UNDEF_MSRPC;
temp = DPRegRHS;
#ifdef MODET
temp &= ~ TBIT;
#endif
ARMul_FixCPSR (state, instr, temp);
}
else
UNDEF_Test;
break;
case 0x13:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPREDOWNWB ();
#endif
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS ^ rhs;
SETR15PSR (temp);
#endif
}
else
{
rhs = DPSRegRHS;
dest = LHS ^ rhs;
ARMul_NegZero (state, dest);
}
break;
case 0x14:
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1)
{
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)
{
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)
{
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)
{
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))
{
UNDEF_MRSPC;
DEST = GETSPSR (state->Bank);
}
else
UNDEF_Test;
break;
case 0x15:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPREDOWN ();
#endif
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
rhs = DPRegRHS;
temp = LHS - rhs;
SETR15PSR (temp);
#endif
}
else
{
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:
if (state->is_v5e)
{
if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
{
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)
{
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)
{
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)
{
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)
{
UNDEF_MSRPC;
ARMul_FixSPSR (state, instr, DPRegRHS);
}
else
{
UNDEF_Test;
}
break;
case 0x17:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPREDOWNWB ();
#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
{
lhs = LHS;
rhs = DPRegRHS;
dest = lhs + rhs;
ASSIGNZ (dest == 0);
if ((lhs | rhs) >> 30)
{
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
}
break;
case 0x18:
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
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:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPREUP ();
#endif
rhs = DPSRegRHS;
dest = LHS | rhs;
WRITESDEST (dest);
break;
case 0x1a:
#ifdef MODET
if (BITS (4, 11) == 0xB)
{
SHPREUPWB ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
dest = DPRegRHS;
WRITEDEST (dest);
break;
case 0x1b:
#ifdef MODET
if ((BITS (4, 11) & 0xF9) == 0x9)
LHPREUPWB ();
#endif
dest = DPSRegRHS;
WRITESDEST (dest);
break;
case 0x1c:
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
SHPREUP ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
else if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
rhs = DPRegRHS;
dest = LHS & ~rhs;
WRITEDEST (dest);
break;
case 0x1d:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPREUP ();
#endif
rhs = DPSRegRHS;
dest = LHS & ~rhs;
WRITESDEST (dest);
break;
case 0x1e:
#ifdef MODET
if (BITS (4, 7) == 0xB)
{
SHPREUPWB ();
break;
}
if (BITS (4, 7) == 0xD)
{
Handle_Load_Double (state, instr);
break;
}
if (BITS (4, 7) == 0xF)
{
Handle_Store_Double (state, instr);
break;
}
#endif
dest = ~DPRegRHS;
WRITEDEST (dest);
break;
case 0x1f:
#ifdef MODET
if ((BITS (4, 7) & 0x9) == 0x9)
LHPREUPWB ();
#endif
dest = ~DPSRegRHS;
WRITESDEST (dest);
break;
case 0x20:
dest = LHS & DPImmRHS;
WRITEDEST (dest);
break;
case 0x21:
DPSImmRHS;
dest = LHS & rhs;
WRITESDEST (dest);
break;
case 0x22:
dest = LHS ^ DPImmRHS;
WRITEDEST (dest);
break;
case 0x23:
DPSImmRHS;
dest = LHS ^ rhs;
WRITESDEST (dest);
break;
case 0x24:
dest = LHS - DPImmRHS;
WRITEDEST (dest);
break;
case 0x25:
lhs = LHS;
rhs = DPImmRHS;
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 0x26:
dest = DPImmRHS - LHS;
WRITEDEST (dest);
break;
case 0x27:
lhs = LHS;
rhs = DPImmRHS;
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 0x28:
dest = LHS + DPImmRHS;
WRITEDEST (dest);
break;
case 0x29:
lhs = LHS;
rhs = DPImmRHS;
dest = lhs + rhs;
ASSIGNZ (dest == 0);
if ((lhs | rhs) >> 30)
{
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x2a:
dest = LHS + DPImmRHS + CFLAG;
WRITEDEST (dest);
break;
case 0x2b:
lhs = LHS;
rhs = DPImmRHS;
dest = lhs + rhs + CFLAG;
ASSIGNZ (dest == 0);
if ((lhs | rhs) >> 30)
{
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
WRITESDEST (dest);
break;
case 0x2c:
dest = LHS - DPImmRHS - !CFLAG;
WRITEDEST (dest);
break;
case 0x2d:
lhs = LHS;
rhs = DPImmRHS;
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 0x2e:
dest = DPImmRHS - LHS - !CFLAG;
WRITEDEST (dest);
break;
case 0x2f:
lhs = LHS;
rhs = DPImmRHS;
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 0x30:
UNDEF_Test;
break;
case 0x31:
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
temp = LHS & DPImmRHS;
SETR15PSR (temp);
#endif
}
else
{
DPSImmRHS;
dest = LHS & rhs;
ARMul_NegZero (state, dest);
}
break;
case 0x32:
if (DESTReg == 15)
ARMul_FixCPSR (state, instr, DPImmRHS);
else
UNDEF_Test;
break;
case 0x33:
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
temp = LHS ^ DPImmRHS;
SETR15PSR (temp);
#endif
}
else
{
DPSImmRHS;
dest = LHS ^ rhs;
ARMul_NegZero (state, dest);
}
break;
case 0x34:
UNDEF_Test;
break;
case 0x35:
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
temp = LHS - DPImmRHS;
SETR15PSR (temp);
#endif
break;
}
else
{
lhs = LHS;
rhs = DPImmRHS;
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 0x36:
if (DESTReg == 15)
ARMul_FixSPSR (state, instr, DPImmRHS);
else
UNDEF_Test;
break;
case 0x37:
if (DESTReg == 15)
{
#ifdef MODE32
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
#else
temp = LHS + DPImmRHS;
SETR15PSR (temp);
#endif
break;
}
else
{
lhs = LHS;
rhs = DPImmRHS;
dest = lhs + rhs;
ASSIGNZ (dest == 0);
if ((lhs | rhs) >> 30)
{
ASSIGNN (NEG (dest));
ARMul_AddCarry (state, lhs, rhs, dest);
ARMul_AddOverflow (state, lhs, rhs, dest);
}
else
{
CLEARN;
CLEARC;
CLEARV;
}
}
break;
case 0x38:
dest = LHS | DPImmRHS;
WRITEDEST (dest);
break;
case 0x39:
DPSImmRHS;
dest = LHS | rhs;
WRITESDEST (dest);
break;
case 0x3a:
dest = DPImmRHS;
WRITEDEST (dest);
break;
case 0x3b:
DPSImmRHS;
WRITESDEST (rhs);
break;
case 0x3c:
dest = LHS & ~DPImmRHS;
WRITEDEST (dest);
break;
case 0x3d:
DPSImmRHS;
dest = LHS & ~rhs;
WRITESDEST (dest);
break;
case 0x3e:
dest = ~DPImmRHS;
WRITEDEST (dest);
break;
case 0x3f:
DPSImmRHS;
WRITESDEST (~rhs);
break;
case 0x40:
lhs = LHS;
if (StoreWord (state, instr, lhs))
LSBase = lhs - LSImmRHS;
break;
case 0x41:
lhs = LHS;
if (LoadWord (state, instr, lhs))
LSBase = lhs - LSImmRHS;
break;
case 0x42:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
temp = lhs - LSImmRHS;
state->NtransSig = LOW;
if (StoreWord (state, instr, lhs))
LSBase = temp;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x43:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (LoadWord (state, instr, lhs))
LSBase = lhs - LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x44:
lhs = LHS;
if (StoreByte (state, instr, lhs))
LSBase = lhs - LSImmRHS;
break;
case 0x45:
lhs = LHS;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = lhs - LSImmRHS;
break;
case 0x46:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreByte (state, instr, lhs))
LSBase = lhs - LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x47:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = lhs - LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x48:
lhs = LHS;
if (StoreWord (state, instr, lhs))
LSBase = lhs + LSImmRHS;
break;
case 0x49:
lhs = LHS;
if (LoadWord (state, instr, lhs))
LSBase = lhs + LSImmRHS;
break;
case 0x4a:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreWord (state, instr, lhs))
LSBase = lhs + LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x4b:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (LoadWord (state, instr, lhs))
LSBase = lhs + LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x4c:
lhs = LHS;
if (StoreByte (state, instr, lhs))
LSBase = lhs + LSImmRHS;
break;
case 0x4d:
lhs = LHS;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = lhs + LSImmRHS;
break;
case 0x4e:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreByte (state, instr, lhs))
LSBase = lhs + LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x4f:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
lhs = LHS;
state->NtransSig = LOW;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = lhs + LSImmRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x50:
(void) StoreWord (state, instr, LHS - LSImmRHS);
break;
case 0x51:
(void) LoadWord (state, instr, LHS - LSImmRHS);
break;
case 0x52:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS - LSImmRHS;
if (StoreWord (state, instr, temp))
LSBase = temp;
break;
case 0x53:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS - LSImmRHS;
if (LoadWord (state, instr, temp))
LSBase = temp;
break;
case 0x54:
(void) StoreByte (state, instr, LHS - LSImmRHS);
break;
case 0x55:
(void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
break;
case 0x56:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS - LSImmRHS;
if (StoreByte (state, instr, temp))
LSBase = temp;
break;
case 0x57:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS - LSImmRHS;
if (LoadByte (state, instr, temp, LUNSIGNED))
LSBase = temp;
break;
case 0x58:
(void) StoreWord (state, instr, LHS + LSImmRHS);
break;
case 0x59:
(void) LoadWord (state, instr, LHS + LSImmRHS);
break;
case 0x5a:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS + LSImmRHS;
if (StoreWord (state, instr, temp))
LSBase = temp;
break;
case 0x5b:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS + LSImmRHS;
if (LoadWord (state, instr, temp))
LSBase = temp;
break;
case 0x5c:
(void) StoreByte (state, instr, LHS + LSImmRHS);
break;
case 0x5d:
(void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
break;
case 0x5e:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS + LSImmRHS;
if (StoreByte (state, instr, temp))
LSBase = temp;
break;
case 0x5f:
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
temp = LHS + LSImmRHS;
if (LoadByte (state, instr, temp, LUNSIGNED))
LSBase = temp;
break;
case 0x60:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
if (StoreWord (state, instr, lhs))
LSBase = lhs - LSRegRHS;
break;
case 0x61:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs - LSRegRHS;
if (LoadWord (state, instr, lhs))
LSBase = temp;
break;
case 0x62:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreWord (state, instr, lhs))
LSBase = lhs - LSRegRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x63:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs - LSRegRHS;
state->NtransSig = LOW;
if (LoadWord (state, instr, lhs))
LSBase = temp;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x64:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
if (StoreByte (state, instr, lhs))
LSBase = lhs - LSRegRHS;
break;
case 0x65:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs - LSRegRHS;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = temp;
break;
case 0x66:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreByte (state, instr, lhs))
LSBase = lhs - LSRegRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x67:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs - LSRegRHS;
state->NtransSig = LOW;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = temp;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x68:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
if (StoreWord (state, instr, lhs))
LSBase = lhs + LSRegRHS;
break;
case 0x69:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs + LSRegRHS;
if (LoadWord (state, instr, lhs))
LSBase = temp;
break;
case 0x6a:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreWord (state, instr, lhs))
LSBase = lhs + LSRegRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x6b:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs + LSRegRHS;
state->NtransSig = LOW;
if (LoadWord (state, instr, lhs))
LSBase = temp;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x6c:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
if (StoreByte (state, instr, lhs))
LSBase = lhs + LSRegRHS;
break;
case 0x6d:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs + LSRegRHS;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = temp;
break;
case 0x6e:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
state->NtransSig = LOW;
if (StoreByte (state, instr, lhs))
LSBase = lhs + LSRegRHS;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x6f:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
lhs = LHS;
temp = lhs + LSRegRHS;
state->NtransSig = LOW;
if (LoadByte (state, instr, lhs, LUNSIGNED))
LSBase = temp;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
break;
case 0x70:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) StoreWord (state, instr, LHS - LSRegRHS);
break;
case 0x71:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) LoadWord (state, instr, LHS - LSRegRHS);
break;
case 0x72:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS - LSRegRHS;
if (StoreWord (state, instr, temp))
LSBase = temp;
break;
case 0x73:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS - LSRegRHS;
if (LoadWord (state, instr, temp))
LSBase = temp;
break;
case 0x74:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) StoreByte (state, instr, LHS - LSRegRHS);
break;
case 0x75:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
break;
case 0x76:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS - LSRegRHS;
if (StoreByte (state, instr, temp))
LSBase = temp;
break;
case 0x77:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS - LSRegRHS;
if (LoadByte (state, instr, temp, LUNSIGNED))
LSBase = temp;
break;
case 0x78:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) StoreWord (state, instr, LHS + LSRegRHS);
break;
case 0x79:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) LoadWord (state, instr, LHS + LSRegRHS);
break;
case 0x7a:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS + LSRegRHS;
if (StoreWord (state, instr, temp))
LSBase = temp;
break;
case 0x7b:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS + LSRegRHS;
if (LoadWord (state, instr, temp))
LSBase = temp;
break;
case 0x7c:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) StoreByte (state, instr, LHS + LSRegRHS);
break;
case 0x7d:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
(void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
break;
case 0x7e:
if (BIT (4))
{
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS + LSRegRHS;
if (StoreByte (state, instr, temp))
LSBase = temp;
break;
case 0x7f:
if (BIT (4))
{
if (BITS (0, 19) == 0xfdefe)
{
if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
ARMul_Abort (state, ARMul_SWIV);
}
else
ARMul_UndefInstr (state, instr);
break;
}
UNDEF_LSRBaseEQOffWb;
UNDEF_LSRBaseEQDestWb;
UNDEF_LSRPCBaseWb;
UNDEF_LSRPCOffWb;
temp = LHS + LSRegRHS;
if (LoadByte (state, instr, temp, LUNSIGNED))
LSBase = temp;
break;
case 0x80:
STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
break;
case 0x81:
LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
break;
case 0x82:
temp = LSBase - LSMNumRegs;
STOREMULT (instr, temp + 4L, temp);
break;
case 0x83:
temp = LSBase - LSMNumRegs;
LOADMULT (instr, temp + 4L, temp);
break;
case 0x84:
STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
break;
case 0x85:
LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
break;
case 0x86:
temp = LSBase - LSMNumRegs;
STORESMULT (instr, temp + 4L, temp);
break;
case 0x87:
temp = LSBase - LSMNumRegs;
LOADSMULT (instr, temp + 4L, temp);
break;
case 0x88:
STOREMULT (instr, LSBase, 0L);
break;
case 0x89:
LOADMULT (instr, LSBase, 0L);
break;
case 0x8a:
temp = LSBase;
STOREMULT (instr, temp, temp + LSMNumRegs);
break;
case 0x8b:
temp = LSBase;
LOADMULT (instr, temp, temp + LSMNumRegs);
break;
case 0x8c:
STORESMULT (instr, LSBase, 0L);
break;
case 0x8d:
LOADSMULT (instr, LSBase, 0L);
break;
case 0x8e:
temp = LSBase;
STORESMULT (instr, temp, temp + LSMNumRegs);
break;
case 0x8f:
temp = LSBase;
LOADSMULT (instr, temp, temp + LSMNumRegs);
break;
case 0x90:
STOREMULT (instr, LSBase - LSMNumRegs, 0L);
break;
case 0x91:
LOADMULT (instr, LSBase - LSMNumRegs, 0L);
break;
case 0x92:
temp = LSBase - LSMNumRegs;
STOREMULT (instr, temp, temp);
break;
case 0x93:
temp = LSBase - LSMNumRegs;
LOADMULT (instr, temp, temp);
break;
case 0x94:
STORESMULT (instr, LSBase - LSMNumRegs, 0L);
break;
case 0x95:
LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
break;
case 0x96:
temp = LSBase - LSMNumRegs;
STORESMULT (instr, temp, temp);
break;
case 0x97:
temp = LSBase - LSMNumRegs;
LOADSMULT (instr, temp, temp);
break;
case 0x98:
STOREMULT (instr, LSBase + 4L, 0L);
break;
case 0x99:
LOADMULT (instr, LSBase + 4L, 0L);
break;
case 0x9a:
temp = LSBase;
STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
break;
case 0x9b:
temp = LSBase;
LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
break;
case 0x9c:
STORESMULT (instr, LSBase + 4L, 0L);
break;
case 0x9d:
LOADSMULT (instr, LSBase + 4L, 0L);
break;
case 0x9e:
temp = LSBase;
STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
break;
case 0x9f:
temp = LSBase;
LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
break;
case 0xa0:
case 0xa1:
case 0xa2:
case 0xa3:
case 0xa4:
case 0xa5:
case 0xa6:
case 0xa7:
state->Reg[15] = pc + 8 + POSBRANCH;
FLUSHPIPE;
break;
case 0xa8:
case 0xa9:
case 0xaa:
case 0xab:
case 0xac:
case 0xad:
case 0xae:
case 0xaf:
state->Reg[15] = pc + 8 + NEGBRANCH;
FLUSHPIPE;
break;
case 0xb0:
case 0xb1:
case 0xb2:
case 0xb3:
case 0xb4:
case 0xb5:
case 0xb6:
case 0xb7:
#ifdef MODE32
state->Reg[14] = pc + 4;
#else
state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
#endif
state->Reg[15] = pc + 8 + POSBRANCH;
FLUSHPIPE;
break;
case 0xb8:
case 0xb9:
case 0xba:
case 0xbb:
case 0xbc:
case 0xbd:
case 0xbe:
case 0xbf:
#ifdef MODE32
state->Reg[14] = pc + 4;
#else
state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
#endif
state->Reg[15] = pc + 8 + NEGBRANCH;
FLUSHPIPE;
break;
case 0xc4:
if (state->is_v5)
{
if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
ARMul_UndefInstr (state, instr);
else if (! CP_ACCESS_ALLOWED (state, CPNum))
ARMul_UndefInstr (state, instr);
else if (state->is_XScale)
{
if (BITS (4, 7) != 0x00)
ARMul_UndefInstr (state, instr);
else if (CPNum != 0x00)
ARMul_UndefInstr (state, instr);
else if (BITS (0, 3) != 0x00)
ARMul_UndefInstr (state, instr);
else
{
state->Accumulator = state->Reg[BITS (12, 15)];
state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
}
}
else
ARMul_UndefInstr (state, instr);
break;
}
case 0xc0:
ARMul_STC (state, instr, LHS);
break;
case 0xc5:
if (state->is_v5)
{
if (DESTReg == 15 || LHSReg == 15)
ARMul_UndefInstr (state, instr);
else if (! CP_ACCESS_ALLOWED (state, CPNum))
ARMul_UndefInstr (state, instr);
else if (state->is_XScale)
{
if (BITS (4, 7) != 0x00)
ARMul_UndefInstr (state, instr);
else if (CPNum != 0x00)
ARMul_UndefInstr (state, instr);
else if (BITS (0, 3) != 0x00)
ARMul_UndefInstr (state, instr);
else
{
ARMword t1 = (state->Accumulator >> 32) & 255;
if (t1 & 128)
t1 -= 256;
state->Reg[BITS (12, 15)] = state->Accumulator;
state->Reg[BITS (16, 19)] = t1;
break;
}
}
else
ARMul_UndefInstr (state, instr);
break;
}
case 0xc1:
ARMul_LDC (state, instr, LHS);
break;
case 0xc2:
case 0xc6:
lhs = LHS;
state->Base = lhs - LSCOff;
ARMul_STC (state, instr, lhs);
break;
case 0xc3:
case 0xc7:
lhs = LHS;
state->Base = lhs - LSCOff;
ARMul_LDC (state, instr, lhs);
break;
case 0xc8:
case 0xcc:
ARMul_STC (state, instr, LHS);
break;
case 0xc9:
case 0xcd:
ARMul_LDC (state, instr, LHS);
break;
case 0xca:
case 0xce:
lhs = LHS;
state->Base = lhs + LSCOff;
ARMul_STC (state, instr, LHS);
break;
case 0xcb:
case 0xcf:
lhs = LHS;
state->Base = lhs + LSCOff;
ARMul_LDC (state, instr, LHS);
break;
case 0xd0:
case 0xd4:
ARMul_STC (state, instr, LHS - LSCOff);
break;
case 0xd1:
case 0xd5:
ARMul_LDC (state, instr, LHS - LSCOff);
break;
case 0xd2:
case 0xd6:
lhs = LHS - LSCOff;
state->Base = lhs;
ARMul_STC (state, instr, lhs);
break;
case 0xd3:
case 0xd7:
lhs = LHS - LSCOff;
state->Base = lhs;
ARMul_LDC (state, instr, lhs);
break;
case 0xd8:
case 0xdc:
ARMul_STC (state, instr, LHS + LSCOff);
break;
case 0xd9:
case 0xdd:
ARMul_LDC (state, instr, LHS + LSCOff);
break;
case 0xda:
case 0xde:
lhs = LHS + LSCOff;
state->Base = lhs;
ARMul_STC (state, instr, lhs);
break;
case 0xdb:
case 0xdf:
lhs = LHS + LSCOff;
state->Base = lhs;
ARMul_LDC (state, instr, lhs);
break;
case 0xe2:
if (! CP_ACCESS_ALLOWED (state, CPNum))
{
ARMul_UndefInstr (state, instr);
break;
}
if (state->is_XScale)
switch (BITS (18, 19))
{
case 0x0:
if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
{
long long Rm = state->Reg[MULLHSReg];
long long Rs = state->Reg[MULACCReg];
if (Rm & (1 << 31))
Rm -= 1ULL << 32;
if (Rs & (1 << 31))
Rs -= 1ULL << 32;
state->Accumulator += Rm * Rs;
goto donext;
}
break;
case 0x2:
if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
{
ARMword t1 = state->Reg[MULLHSReg] >> 16;
ARMword t2 = state->Reg[MULACCReg] >> 16;
ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
ARMword t4 = state->Reg[MULACCReg] & 0xffff;
long long t5;
if (t1 & (1 << 15))
t1 -= 1 << 16;
if (t2 & (1 << 15))
t2 -= 1 << 16;
if (t3 & (1 << 15))
t3 -= 1 << 16;
if (t4 & (1 << 15))
t4 -= 1 << 16;
t1 *= t2;
t5 = t1;
if (t5 & (1 << 31))
t5 -= 1ULL << 32;
state->Accumulator += t5;
t3 *= t4;
t5 = t3;
if (t5 & (1 << 31))
t5 -= 1ULL << 32;
state->Accumulator += t5;
goto donext;
}
break;
case 0x3:
if (BITS (4, 11) == 1)
{
ARMword t1;
ARMword t2;
long long t5;
if (BIT (17))
t1 = state->Reg[MULLHSReg] >> 16;
else
t1 = state->Reg[MULLHSReg] & 0xffff;
if (BIT (16))
t2 = state->Reg[MULACCReg] >> 16;
else
t2 = state->Reg[MULACCReg] & 0xffff;
if (t1 & (1 << 15))
t1 -= 1 << 16;
if (t2 & (1 << 15))
t2 -= 1 << 16;
t1 *= t2;
t5 = t1;
if (t5 & (1 << 31))
t5 -= 1ULL << 32;
state->Accumulator += t5;
goto donext;
}
break;
default:
break;
}
case 0xe0:
case 0xe4:
case 0xe6:
case 0xe8:
case 0xea:
case 0xec:
case 0xee:
if (BIT (4))
{
if (DESTReg == 15)
{
UNDEF_MCRPC;
#ifdef MODE32
ARMul_MCR (state, instr, state->Reg[15] + isize);
#else
ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
((state->Reg[15] + isize) & R15PCBITS));
#endif
}
else
ARMul_MCR (state, instr, DEST);
}
else
ARMul_CDP (state, instr);
break;
case 0xe1:
case 0xe3:
case 0xe5:
case 0xe7:
case 0xe9:
case 0xeb:
case 0xed:
case 0xef:
if (BIT (4))
{
temp = ARMul_MRC (state, instr);
if (DESTReg == 15)
{
ASSIGNN ((temp & NBIT) != 0);
ASSIGNZ ((temp & ZBIT) != 0);
ASSIGNC ((temp & CBIT) != 0);
ASSIGNV ((temp & VBIT) != 0);
}
else
DEST = temp;
}
else
ARMul_CDP (state, instr);
break;
case 0xf0:
case 0xf1:
case 0xf2:
case 0xf3:
case 0xf4:
case 0xf5:
case 0xf6:
case 0xf7:
case 0xf8:
case 0xf9:
case 0xfa:
case 0xfb:
case 0xfc:
case 0xfd:
case 0xfe:
case 0xff:
if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
ARMul_Abort (state, ARMul_PrefetchAbortV);
break;
}
if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
ARMul_Abort (state, ARMul_SWIV);
break;
}
}
#ifdef MODET
donext:
#endif
#ifdef NEED_UI_LOOP_HOOK
if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
{
ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
ui_loop_hook (0);
}
#endif
if (state->Emulate == ONCE)
state->Emulate = STOP;
else if (state->Emulate == CHANGEMODE)
continue;
else if (state->Emulate != RUN)
break;
}
while (!stop_simulator);
state->decoded = decoded;
state->loaded = loaded;
state->pc = pc;
return pc;
}
static ARMword
GetDPRegRHS (ARMul_State * state, ARMword instr)
{
ARMword shamt, base;
base = RHSReg;
if (BIT (4))
{
UNDEF_Shift;
INCPC;
#ifndef MODE32
if (base == 15)
base = ECC | ER15INT | R15PC | EMODE;
else
#endif
base = state->Reg[base];
ARMul_Icycles (state, 1, 0L);
shamt = state->Reg[BITS (8, 11)] & 0xff;
switch ((int) BITS (5, 6))
{
case LSL:
if (shamt == 0)
return (base);
else if (shamt >= 32)
return (0);
else
return (base << shamt);
case LSR:
if (shamt == 0)
return (base);
else if (shamt >= 32)
return (0);
else
return (base >> shamt);
case ASR:
if (shamt == 0)
return (base);
else if (shamt >= 32)
return ((ARMword) ((long int) base >> 31L));
else
return ((ARMword) ((long int) base >> (int) shamt));
case ROR:
shamt &= 0x1f;
if (shamt == 0)
return (base);
else
return ((base << (32 - shamt)) | (base >> shamt));
}
}
else
{
#ifndef MODE32
if (base == 15)
base = ECC | ER15INT | R15PC | EMODE;
else
#endif
base = state->Reg[base];
shamt = BITS (7, 11);
switch ((int) BITS (5, 6))
{
case LSL:
return (base << shamt);
case LSR:
if (shamt == 0)
return (0);
else
return (base >> shamt);
case ASR:
if (shamt == 0)
return ((ARMword) ((long int) base >> 31L));
else
return ((ARMword) ((long int) base >> (int) shamt));
case ROR:
if (shamt == 0)
return ((base >> 1) | (CFLAG << 31));
else
return ((base << (32 - shamt)) | (base >> shamt));
}
}
return 0;
}
static ARMword
GetDPSRegRHS (ARMul_State * state, ARMword instr)
{
ARMword shamt, base;
base = RHSReg;
if (BIT (4))
{
UNDEF_Shift;
INCPC;
#ifndef MODE32
if (base == 15)
base = ECC | ER15INT | R15PC | EMODE;
else
#endif
base = state->Reg[base];
ARMul_Icycles (state, 1, 0L);
shamt = state->Reg[BITS (8, 11)] & 0xff;
switch ((int) BITS (5, 6))
{
case LSL:
if (shamt == 0)
return (base);
else if (shamt == 32)
{
ASSIGNC (base & 1);
return (0);
}
else if (shamt > 32)
{
CLEARC;
return (0);
}
else
{
ASSIGNC ((base >> (32 - shamt)) & 1);
return (base << shamt);
}
case LSR:
if (shamt == 0)
return (base);
else if (shamt == 32)
{
ASSIGNC (base >> 31);
return (0);
}
else if (shamt > 32)
{
CLEARC;
return (0);
}
else
{
ASSIGNC ((base >> (shamt - 1)) & 1);
return (base >> shamt);
}
case ASR:
if (shamt == 0)
return (base);
else if (shamt >= 32)
{
ASSIGNC (base >> 31L);
return ((ARMword) ((long int) base >> 31L));
}
else
{
ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
return ((ARMword) ((long int) base >> (int) shamt));
}
case ROR:
if (shamt == 0)
return (base);
shamt &= 0x1f;
if (shamt == 0)
{
ASSIGNC (base >> 31);
return (base);
}
else
{
ASSIGNC ((base >> (shamt - 1)) & 1);
return ((base << (32 - shamt)) | (base >> shamt));
}
}
}
else
{
#ifndef MODE32
if (base == 15)
base = ECC | ER15INT | R15PC | EMODE;
else
#endif
base = state->Reg[base];
shamt = BITS (7, 11);
switch ((int) BITS (5, 6))
{
case LSL:
ASSIGNC ((base >> (32 - shamt)) & 1);
return (base << shamt);
case LSR:
if (shamt == 0)
{
ASSIGNC (base >> 31);
return (0);
}
else
{
ASSIGNC ((base >> (shamt - 1)) & 1);
return (base >> shamt);
}
case ASR:
if (shamt == 0)
{
ASSIGNC (base >> 31L);
return ((ARMword) ((long int) base >> 31L));
}
else
{
ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
return ((ARMword) ((long int) base >> (int) shamt));
}
case ROR:
if (shamt == 0)
{
shamt = CFLAG;
ASSIGNC (base & 1);
return ((base >> 1) | (shamt << 31));
}
else
{
ASSIGNC ((base >> (shamt - 1)) & 1);
return ((base << (32 - shamt)) | (base >> shamt));
}
}
}
return 0;
}
static void
WriteR15 (ARMul_State * state, ARMword src)
{
#ifdef MODET
if (TFLAG)
src &= 0xfffffffe;
else
#endif
src &= 0xfffffffc;
#ifdef MODE32
state->Reg[15] = src & PCBITS;
#else
state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
ARMul_R15Altered (state);
#endif
FLUSHPIPE;
}
static void
WriteSR15 (ARMul_State * state, ARMword src)
{
#ifdef MODE32
if (state->Bank > 0)
{
state->Cpsr = state->Spsr[state->Bank];
ARMul_CPSRAltered (state);
}
#ifdef MODET
if (TFLAG)
src &= 0xfffffffe;
else
#endif
src &= 0xfffffffc;
state->Reg[15] = src & PCBITS;
#else
#ifdef MODET
if (TFLAG)
abort ();
else
#endif
src &= 0xfffffffc;
if (state->Bank == USERBANK)
state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
else
state->Reg[15] = src;
ARMul_R15Altered (state);
#endif
FLUSHPIPE;
}
static void
WriteR15Branch (ARMul_State * state, ARMword src)
{
#ifdef MODET
if (src & 1)
{
SETT;
state->Reg[15] = src & 0xfffffffe;
}
else
{
CLEART;
state->Reg[15] = src & 0xfffffffc;
}
FLUSHPIPE;
#else
WriteR15 (state, src);
#endif
}
static ARMword
GetLSRegRHS (ARMul_State * state, ARMword instr)
{
ARMword shamt, base;
base = RHSReg;
#ifndef MODE32
if (base == 15)
base = ECC | ER15INT | R15PC | EMODE;
else
#endif
base = state->Reg[base];
shamt = BITS (7, 11);
switch ((int) BITS (5, 6))
{
case LSL:
return (base << shamt);
case LSR:
if (shamt == 0)
return (0);
else
return (base >> shamt);
case ASR:
if (shamt == 0)
return ((ARMword) ((long int) base >> 31L));
else
return ((ARMword) ((long int) base >> (int) shamt));
case ROR:
if (shamt == 0)
return ((base >> 1) | (CFLAG << 31));
else
return ((base << (32 - shamt)) | (base >> shamt));
default:
break;
}
return 0;
}
static ARMword
GetLS7RHS (ARMul_State * state, ARMword instr)
{
if (BIT (22) == 0)
{
#ifndef MODE32
if (RHSReg == 15)
return ECC | ER15INT | R15PC | EMODE;
#endif
return state->Reg[RHSReg];
}
return BITS (0, 3) | (BITS (8, 11) << 4);
}
static unsigned
LoadWord (ARMul_State * state, ARMword instr, ARMword address)
{
ARMword dest;
BUSUSEDINCPCS;
#ifndef MODE32
if (ADDREXCEPT (address))
INTERNALABORT (address);
#endif
dest = ARMul_LoadWordN (state, address);
if (state->Aborted)
{
TAKEABORT;
return state->lateabtSig;
}
if (address & 3)
dest = ARMul_Align (state, address, dest);
WRITEDESTB (dest);
ARMul_Icycles (state, 1, 0L);
return (DESTReg != LHSReg);
}
#ifdef MODET
static unsigned
LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
int signextend)
{
ARMword dest;
BUSUSEDINCPCS;
#ifndef MODE32
if (ADDREXCEPT (address))
INTERNALABORT (address);
#endif
dest = ARMul_LoadHalfWord (state, address);
if (state->Aborted)
{
TAKEABORT;
return state->lateabtSig;
}
UNDEF_LSRBPC;
if (signextend)
if (dest & 1 << (16 - 1))
dest = (dest & ((1 << 16) - 1)) - (1 << 16);
WRITEDEST (dest);
ARMul_Icycles (state, 1, 0L);
return (DESTReg != LHSReg);
}
#endif
static unsigned
LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
{
ARMword dest;
BUSUSEDINCPCS;
#ifndef MODE32
if (ADDREXCEPT (address))
INTERNALABORT (address);
#endif
dest = ARMul_LoadByte (state, address);
if (state->Aborted)
{
TAKEABORT;
return state->lateabtSig;
}
UNDEF_LSRBPC;
if (signextend)
if (dest & 1 << (8 - 1))
dest = (dest & ((1 << 8) - 1)) - (1 << 8);
WRITEDEST (dest);
ARMul_Icycles (state, 1, 0L);
return (DESTReg != LHSReg);
}
static void
Handle_Load_Double (ARMul_State * state, ARMword instr)
{
ARMword dest_reg;
ARMword addr_reg;
ARMword write_back = BIT (21);
ARMword immediate = BIT (22);
ARMword add_to_base = BIT (23);
ARMword pre_indexed = BIT (24);
ARMword offset;
ARMword addr;
ARMword sum;
ARMword base;
ARMword value1;
ARMword value2;
BUSUSEDINCPCS;
if (write_back && ! pre_indexed)
{
ARMul_UndefInstr (state, instr);
return;
}
addr_reg = LHSReg;
dest_reg = DESTReg;
if ((dest_reg & 1)
|| (dest_reg == 14))
{
ARMul_UndefInstr (state, instr);
return;
}
base = state->Reg[addr_reg];
offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
if (add_to_base)
sum = base + offset;
else
sum = base - offset;
if (pre_indexed)
addr = sum;
else
addr = base;
if (addr & 0x7)
{
#ifdef ABORTS
ARMul_DATAABORT (addr);
#else
ARMul_UndefInstr (state, instr);
#endif
return;
}
if ((! pre_indexed || write_back)
&& ( addr_reg == dest_reg
|| addr_reg == dest_reg + 1))
{
ARMul_UndefInstr (state, instr);
return;
}
value1 = ARMul_LoadWordN (state, addr);
value2 = ARMul_LoadWordN (state, addr + 4);
if (state->Aborted)
{
TAKEABORT;
return;
}
ARMul_Icycles (state, 2, 0L);
state->Reg[dest_reg] = value1;
state->Reg[dest_reg + 1] = value2;
if (! pre_indexed)
addr = sum;
if (! pre_indexed || write_back)
state->Reg[addr_reg] = addr;
}
static void
Handle_Store_Double (ARMul_State * state, ARMword instr)
{
ARMword src_reg;
ARMword addr_reg;
ARMword write_back = BIT (21);
ARMword immediate = BIT (22);
ARMword add_to_base = BIT (23);
ARMword pre_indexed = BIT (24);
ARMword offset;
ARMword addr;
ARMword sum;
ARMword base;
BUSUSEDINCPCS;
if (write_back && ! pre_indexed)
{
ARMul_UndefInstr (state, instr);
return;
}
addr_reg = LHSReg;
if (addr_reg == 15)
{
ARMul_UndefInstr (state, instr);
return;
}
src_reg = DESTReg;
if (src_reg & 1)
{
ARMul_UndefInstr (state, instr);
return;
}
base = state->Reg[addr_reg];
offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
if (add_to_base)
sum = base + offset;
else
sum = base - offset;
if (pre_indexed)
addr = sum;
else
addr = base;
if (addr & 0x7)
{
#ifdef ABORTS
ARMul_DATAABORT (addr);
#else
ARMul_UndefInstr (state, instr);
#endif
return;
}
if ((! pre_indexed || write_back)
&& ( addr_reg == src_reg
|| addr_reg == src_reg + 1))
{
ARMul_UndefInstr (state, instr);
return;
}
ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
if (state->Aborted)
{
TAKEABORT;
return;
}
if (! pre_indexed)
addr = sum;
if (! pre_indexed || write_back)
state->Reg[addr_reg] = addr;
}
static unsigned
StoreWord (ARMul_State * state, ARMword instr, ARMword address)
{
BUSUSEDINCPCN;
#ifndef MODE32
if (DESTReg == 15)
state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
#endif
#ifdef MODE32
ARMul_StoreWordN (state, address, DEST);
#else
if (VECTORACCESS (address) || ADDREXCEPT (address))
{
INTERNALABORT (address);
(void) ARMul_LoadWordN (state, address);
}
else
ARMul_StoreWordN (state, address, DEST);
#endif
if (state->Aborted)
{
TAKEABORT;
return state->lateabtSig;
}
return TRUE;
}
#ifdef MODET
static unsigned
StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
{
BUSUSEDINCPCN;
#ifndef MODE32
if (DESTReg == 15)
state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
#endif
#ifdef MODE32
ARMul_StoreHalfWord (state, address, DEST);
#else
if (VECTORACCESS (address) || ADDREXCEPT (address))
{
INTERNALABORT (address);
(void) ARMul_LoadHalfWord (state, address);
}
else
ARMul_StoreHalfWord (state, address, DEST);
#endif
if (state->Aborted)
{
TAKEABORT;
return state->lateabtSig;
}
return TRUE;
}
#endif
static unsigned
StoreByte (ARMul_State * state, ARMword instr, ARMword address)
{
BUSUSEDINCPCN;
#ifndef MODE32
if (DESTReg == 15)
state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
#endif
#ifdef MODE32
ARMul_StoreByte (state, address, DEST);
#else
if (VECTORACCESS (address) || ADDREXCEPT (address))
{
INTERNALABORT (address);
(void) ARMul_LoadByte (state, address);
}
else
ARMul_StoreByte (state, address, DEST);
#endif
if (state->Aborted)
{
TAKEABORT;
return state->lateabtSig;
}
UNDEF_LSRBPC;
return TRUE;
}
static void
LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
{
ARMword dest, temp;
UNDEF_LSMNoRegs;
UNDEF_LSMPCBase;
UNDEF_LSMBaseInListWb;
BUSUSEDINCPCS;
#ifndef MODE32
if (ADDREXCEPT (address))
INTERNALABORT (address);
#endif
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
for (temp = 0; !BIT (temp); temp++)
;
dest = ARMul_LoadWordN (state, address);
if (!state->abortSig && !state->Aborted)
state->Reg[temp++] = dest;
else if (!state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
for (; temp < 16; temp ++)
if (BIT (temp))
{
address += 4;
dest = ARMul_LoadWordS (state, address);
if (!state->abortSig && !state->Aborted)
state->Reg[temp] = dest;
else if (!state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
}
if (BIT (15) && !state->Aborted)
WriteR15Branch (state, PC);
ARMul_Icycles (state, 1, 0L);
if (state->Aborted)
{
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
TAKEABORT;
}
}
static void
LoadSMult (ARMul_State * state,
ARMword instr,
ARMword address,
ARMword WBBase)
{
ARMword dest, temp;
UNDEF_LSMNoRegs;
UNDEF_LSMPCBase;
UNDEF_LSMBaseInListWb;
BUSUSEDINCPCS;
#ifndef MODE32
if (ADDREXCEPT (address))
INTERNALABORT (address);
#endif
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
if (!BIT (15) && state->Bank != USERBANK)
{
(void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
UNDEF_LSMUserBankWb;
}
for (temp = 0; !BIT (temp); temp ++)
;
dest = ARMul_LoadWordN (state, address);
if (!state->abortSig)
state->Reg[temp++] = dest;
else if (!state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
for (; temp < 16; temp++)
if (BIT (temp))
{
address += 4;
dest = ARMul_LoadWordS (state, address);
if (!state->abortSig && !state->Aborted)
state->Reg[temp] = dest;
else if (!state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
}
if (BIT (15) && !state->Aborted)
{
#ifdef MODE32
if (state->Mode != USER26MODE && state->Mode != USER32MODE)
{
state->Cpsr = GETSPSR (state->Bank);
ARMul_CPSRAltered (state);
}
WriteR15 (state, PC);
#else
if (state->Mode == USER26MODE || state->Mode == USER32MODE)
{
ASSIGNN ((state->Reg[15] & NBIT) != 0);
ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
ASSIGNC ((state->Reg[15] & CBIT) != 0);
ASSIGNV ((state->Reg[15] & VBIT) != 0);
}
else
ARMul_R15Altered (state);
FLUSHPIPE;
#endif
}
if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
(void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
ARMul_Icycles (state, 1, 0L);
if (state->Aborted)
{
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
TAKEABORT;
}
}
static void
StoreMult (ARMul_State * state,
ARMword instr,
ARMword address,
ARMword WBBase)
{
ARMword temp;
UNDEF_LSMNoRegs;
UNDEF_LSMPCBase;
UNDEF_LSMBaseInListWb;
if (!TFLAG)
BUSUSEDINCPCN;
#ifndef MODE32
if (VECTORACCESS (address) || ADDREXCEPT (address))
INTERNALABORT (address);
if (BIT (15))
PATCHR15;
#endif
for (temp = 0; !BIT (temp); temp ++)
;
#ifdef MODE32
ARMul_StoreWordN (state, address, state->Reg[temp++]);
#else
if (state->Aborted)
{
(void) ARMul_LoadWordN (state, address);
for (; temp < 16; temp++)
if (BIT (temp))
{
address += 4;
(void) ARMul_LoadWordS (state, address);
}
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
TAKEABORT;
return;
}
else
ARMul_StoreWordN (state, address, state->Reg[temp++]);
#endif
if (state->abortSig && !state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
for (; temp < 16; temp ++)
if (BIT (temp))
{
address += 4;
ARMul_StoreWordS (state, address, state->Reg[temp]);
if (state->abortSig && !state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
}
if (state->Aborted)
TAKEABORT;
}
static void
StoreSMult (ARMul_State * state,
ARMword instr,
ARMword address,
ARMword WBBase)
{
ARMword temp;
UNDEF_LSMNoRegs;
UNDEF_LSMPCBase;
UNDEF_LSMBaseInListWb;
BUSUSEDINCPCN;
#ifndef MODE32
if (VECTORACCESS (address) || ADDREXCEPT (address))
INTERNALABORT (address);
if (BIT (15))
PATCHR15;
#endif
if (state->Bank != USERBANK)
{
(void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
UNDEF_LSMUserBankWb;
}
for (temp = 0; !BIT (temp); temp++)
;
#ifdef MODE32
ARMul_StoreWordN (state, address, state->Reg[temp++]);
#else
if (state->Aborted)
{
(void) ARMul_LoadWordN (state, address);
for (; temp < 16; temp++)
if (BIT (temp))
{
address += 4;
(void) ARMul_LoadWordS (state, address);
}
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
TAKEABORT;
return;
}
else
ARMul_StoreWordN (state, address, state->Reg[temp++]);
#endif
if (state->abortSig && !state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
for (; temp < 16; temp++)
if (BIT (temp))
{
address += 4;
ARMul_StoreWordS (state, address, state->Reg[temp]);
if (state->abortSig && !state->Aborted)
{
XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
state->Aborted = ARMul_DataAbortV;
}
}
if (state->Mode != USER26MODE && state->Mode != USER32MODE)
(void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
if (BIT (21) && LHSReg != 15)
LSBase = WBBase;
if (state->Aborted)
TAKEABORT;
}
static ARMword
Add32 (ARMword a1, ARMword a2, int *carry)
{
ARMword result = (a1 + a2);
unsigned int uresult = (unsigned int) result;
unsigned int ua1 = (unsigned int) a1;
if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
*carry = 1;
else
*carry = 0;
return result;
}
static unsigned
Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
{
int nRdHi, nRdLo, nRs, nRm;
ARMword RdHi = 0, RdLo = 0, Rm;
int scount;
nRdHi = BITS (16, 19);
nRdLo = BITS (12, 15);
nRs = BITS (8, 11);
nRm = BITS (0, 3);
Rm = state->Reg[nRm];
if ( nRdHi != 15
&& nRdLo != 15
&& nRs != 15
&& nRm != 15
&& nRdHi != nRdLo
&& nRdHi != nRm
&& nRdLo != nRm)
{
ARMword lo, mid1, mid2, hi;
int carry;
ARMword Rs = state->Reg[nRs];
int sign = 0;
if (msigned)
{
sign = (Rm ^ Rs) & 0x80000000;
if (((signed long) Rm) < 0)
Rm = -Rm;
if (((signed long) Rs) < 0)
Rs = -Rs;
}
lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
RdLo = Add32 (lo, (mid1 << 16), &carry);
RdHi = carry;
RdLo = Add32 (RdLo, (mid2 << 16), &carry);
RdHi +=
(carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
if (sign)
{
RdLo = ~RdLo;
RdHi = ~RdHi;
if (RdLo == 0xFFFFFFFF)
{
RdLo = 0;
RdHi += 1;
}
else
RdLo += 1;
}
state->Reg[nRdLo] = RdLo;
state->Reg[nRdHi] = RdHi;
}
else
fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
if (scc)
ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
if (msigned && (Rm & ((unsigned) 1 << 31)))
Rm = ~Rm;
if ((Rm & 0xFFFFFF00) == 0)
scount = 1;
else if ((Rm & 0xFFFF0000) == 0)
scount = 2;
else if ((Rm & 0xFF000000) == 0)
scount = 3;
else
scount = 4;
return 2 + scount;
}
static unsigned
MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
{
unsigned scount;
ARMword RdLo, RdHi;
int nRdHi, nRdLo;
int carry = 0;
nRdHi = BITS (16, 19);
nRdLo = BITS (12, 15);
RdHi = state->Reg[nRdHi];
RdLo = state->Reg[nRdLo];
scount = Multiply64 (state, instr, msigned, LDEFAULT);
RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
RdHi = (RdHi + state->Reg[nRdHi]) + carry;
state->Reg[nRdLo] = RdLo;
state->Reg[nRdHi] = RdHi;
if (scc)
ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
return scount + 1;
}